Redesign selectable API

This commit is contained in:
Joonas Javanainen 2019-07-13 13:11:51 +03:00
parent c0b9571160
commit baa9362a25
No known key found for this signature in database
GPG Key ID: D39CCA5CB19B9179
7 changed files with 152 additions and 37 deletions

View File

@ -16,6 +16,7 @@
- Redesigned child window API (previously known as child frame)
- Redesigned image / image button API
- Redesigned combo box API
- Redesigned selectable API
- Updated layout API
- Renderer errors implement std::error::Error
- Glium renderer re-exports imgui and glium

View File

@ -623,12 +623,7 @@ CTRL+click on individual component to input value.\n",
ui.text(im_str!("Aquarium"));
ui.separator();
for (index, name) in names.iter().enumerate() {
if ui.selectable(
name,
false,
ImGuiSelectableFlags::empty(),
[0.0, 0.0]
) {
if Selectable::new(name).build(ui) {
state.selected_fish = Some(index);
}
}

View File

@ -8,6 +8,7 @@ use crate::widget::color_editors::*;
use crate::widget::combo_box::*;
use crate::widget::image::{Image, ImageButton};
use crate::widget::progress_bar::ProgressBar;
use crate::widget::selectable::*;
use crate::window::{Window, WindowFlags, WindowFocusedFlags};
use crate::{Id, Ui};
@ -131,20 +132,8 @@ bitflags!(
}
);
bitflags!(
/// Flags for selectables
#[repr(C)]
pub struct ImGuiSelectableFlags: c_int {
/// Clicking this don't close parent popup window
const DontClosePopups = 1;
/// Selectable frame can span all columns (text will still fit in current column)
const SpanAllColumns = 1 << 1;
/// Generate press events on double clicks too
const AllowDoubleClick = 1 << 2;
/// Cannot be selected, display greyed out text
const Disabled = 1 << 3;
}
);
#[deprecated(since = "0.2.0", note = "use SelectableFlags instead")]
pub type ImGuiSelectableFlags = SelectableFlags;
bitflags!(
/// Flags for trees and collapsing headers
@ -365,3 +354,16 @@ impl<'ui> Ui<'ui> {
}
}
}
impl<'ui> Ui<'ui> {
#[deprecated(since = "0.2.0", note = "use imgui::Selectable::new(...) instead")]
pub fn selectable(
&self,
label: &ImStr,
selected: bool,
flags: SelectableFlags,
size: [f32; 2],
) -> bool {
unsafe { sys::igSelectable(label.as_ptr(), selected, flags.bits() as i32, size.into()) }
}
}

View File

@ -46,6 +46,7 @@ pub use self::widget::color_editors::*;
pub use self::widget::combo_box::*;
pub use self::widget::image::*;
pub use self::widget::progress_bar::*;
pub use self::widget::selectable::*;
pub use self::window::child_window::*;
pub use self::window::*;
pub use self::window_draw_list::{ChannelsSplit, ImColor, WindowDrawList};
@ -424,19 +425,6 @@ impl<'ui> Ui<'ui> {
}
}
// Widgets: Selectable / Lists
impl<'ui> Ui<'ui> {
pub fn selectable(
&self,
label: &ImStr,
selected: bool,
flags: ImGuiSelectableFlags,
size: [f32; 2],
) -> bool {
unsafe { sys::igSelectable(label.as_ptr(), selected, flags.bits(), size.into()) }
}
}
/// # Tooltips
impl<'ui> Ui<'ui> {
/// Construct a tooltip window that can have any kind of content.

View File

@ -192,6 +192,7 @@ impl<'a> ComboBox<'a> {
where
for<'b> L: Fn(&'b T) -> Cow<'b, ImStr>,
{
use crate::widget::selectable::Selectable;
let mut result = false;
let mut cb = self;
let preview_value = items.get(*current_item).map(label_fn);
@ -204,10 +205,7 @@ impl<'a> ComboBox<'a> {
for (idx, item) in items.iter().enumerate() {
let text = label_fn(item);
let selected = idx == *current_item;
// TODO: use safe API
let change =
unsafe { sys::igSelectable(text.as_ptr(), selected, 0, [0.0, 0.0].into()) };
if change {
if Selectable::new(&text).selected(selected).build(ui) {
*current_item = idx;
result = true;
}

View File

@ -3,4 +3,5 @@ pub mod combo_box;
pub mod image;
pub mod misc;
pub mod progress_bar;
pub mod selectable;
pub mod text;

130
src/widget/selectable.rs Normal file
View File

@ -0,0 +1,130 @@
use bitflags::bitflags;
use crate::string::ImStr;
use crate::sys;
use crate::Ui;
bitflags!(
/// Flags for selectables
#[repr(transparent)]
pub struct SelectableFlags: u32 {
/// Clicking this don't close parent popup window
const DONT_CLOSE_POPUPS = sys::ImGuiSelectableFlags_DontClosePopups;
/// Selectable frame can span all columns (text will still fit in current column)
const SPAN_ALL_COLUMNS = sys::ImGuiSelectableFlags_SpanAllColumns;
/// Generate press events on double clicks too
const ALLOW_DOUBLE_CLICK = sys::ImGuiSelectableFlags_AllowDoubleClick;
/// Cannot be selected, display greyed out text
const DISABLED = sys::ImGuiSelectableFlags_Disabled;
}
);
/// Builder for a selectable widget.
#[derive(Clone, Debug)]
#[must_use]
pub struct Selectable<'a> {
label: &'a ImStr,
selected: bool,
flags: SelectableFlags,
size: [f32; 2],
}
impl<'a> Selectable<'a> {
/// Constructs a new selectable builder.
pub fn new(label: &ImStr) -> Selectable {
Selectable {
label,
selected: false,
flags: SelectableFlags::empty(),
size: [0.0, 0.0],
}
}
/// Replaces all current settings with the given flags
#[inline]
pub fn flags(mut self, flags: SelectableFlags) -> Self {
self.flags = flags;
self
}
/// Sets the selected state of the selectable
#[inline]
pub fn selected(mut self, selected: bool) -> Self {
self.selected = selected;
self
}
/// Enables/disables closing parent popup window on click.
///
/// Default: enabled
#[inline]
pub fn close_popups(mut self, value: bool) -> Self {
self.flags.set(SelectableFlags::DONT_CLOSE_POPUPS, !value);
self
}
/// Enables/disables full column span (text will still fit in the current column).
///
/// Default: disabled
#[inline]
pub fn span_all_columns(mut self, value: bool) -> Self {
self.flags.set(SelectableFlags::SPAN_ALL_COLUMNS, value);
self
}
/// Enables/disables click event generation on double clicks.
///
/// Default: disabled
#[inline]
pub fn allow_double_click(mut self, value: bool) -> Self {
self.flags.set(SelectableFlags::ALLOW_DOUBLE_CLICK, value);
self
}
/// Enables/disables the selectable.
///
/// When disabled, it cannot be selected and the text uses the disabled text color.
///
/// Default: disabled
#[inline]
pub fn disabled(mut self, value: bool) -> Self {
self.flags.set(SelectableFlags::DISABLED, value);
self
}
/// Sets the size of the selectable.
///
/// For the X axis:
///
/// - `> 0.0`: use given width
/// - `= 0.0`: use remaining width
///
/// For the Y axis:
///
/// - `> 0.0`: use given height
/// - `= 0.0`: use label height
#[inline]
pub fn size(mut self, size: [f32; 2]) -> Self {
self.size = size.into();
self
}
/// Builds the selectable.
///
/// Returns true if the selectable was clicked.
pub fn build(self, _: &Ui) -> bool {
unsafe {
sys::igSelectable(
self.label.as_ptr(),
self.selected,
self.flags.bits() as i32,
self.size.into(),
)
}
}
}
/// # Convenience functions
impl<'a> Selectable<'a> {
/// Builds the selectable using a mutable reference to selected state.
pub fn build_with_ref(self, ui: &Ui, selected: &mut bool) -> bool {
if self.selected(*selected).build(ui) {
*selected = true;
true
} else {
false
}
}
}