imgui-rs/src/widget/selectable.rs
Malik Olivier Boussejra 55a8f28e0a Fix toggling of MenuItem and Selectable with build_with_ref
Selectable or MenuItem should be toggled on click when called with
build_with_ref.

This is the behavior that is done in ImGui when
`bool ImGui::MenuItem(const char* label, const char* shortcut, bool*p_selected, bool enabled)` is called.
2019-12-06 11:24:41 +09:00

133 lines
3.8 KiB
Rust

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;
/// (WIP) Hit testing to allow subsequent willdgets to overlap this one
const ALLOW_ITEM_OVERLAP = sys::ImGuiSelectableFlags_AllowItemOverlap;
}
);
/// Builder for a selectable widget.
#[derive(Copy, 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;
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 = !*selected;
true
} else {
false
}
}
}