arcdps_imgui\widget/
selectable.rs

1use bitflags::bitflags;
2
3use crate::sys;
4use crate::Ui;
5
6bitflags!(
7    /// Flags for selectables
8    #[repr(transparent)]
9    pub struct SelectableFlags: u32 {
10        /// Clicking this don't close parent popup window
11        const DONT_CLOSE_POPUPS = sys::ImGuiSelectableFlags_DontClosePopups;
12        /// Selectable frame can span all columns (text will still fit in current column)
13        const SPAN_ALL_COLUMNS = sys::ImGuiSelectableFlags_SpanAllColumns;
14        /// Generate press events on double clicks too
15        const ALLOW_DOUBLE_CLICK = sys::ImGuiSelectableFlags_AllowDoubleClick;
16        /// Cannot be selected, display greyed out text
17        const DISABLED = sys::ImGuiSelectableFlags_Disabled;
18        /// (WIP) Hit testing to allow subsequent willdgets to overlap this one
19        const ALLOW_ITEM_OVERLAP = sys::ImGuiSelectableFlags_AllowItemOverlap;
20    }
21);
22
23/// Builder for a selectable widget.
24#[derive(Copy, Clone, Debug)]
25#[must_use]
26pub struct Selectable<T> {
27    label: T,
28    selected: bool,
29    flags: SelectableFlags,
30    size: [f32; 2],
31}
32
33impl<T: AsRef<str>> Selectable<T> {
34    /// Constructs a new selectable builder.
35    #[inline]
36    #[doc(alias = "Selectable")]
37    pub fn new(label: T) -> Self {
38        Selectable {
39            label,
40            selected: false,
41            flags: SelectableFlags::empty(),
42            size: [0.0, 0.0],
43        }
44    }
45    /// Replaces all current settings with the given flags
46    #[inline]
47    pub fn flags(mut self, flags: SelectableFlags) -> Self {
48        self.flags = flags;
49        self
50    }
51    /// Sets the selected state of the selectable
52    #[inline]
53    pub fn selected(mut self, selected: bool) -> Self {
54        self.selected = selected;
55        self
56    }
57    /// Enables/disables closing parent popup window on click.
58    ///
59    /// Default: enabled
60    #[inline]
61    pub fn close_popups(mut self, value: bool) -> Self {
62        self.flags.set(SelectableFlags::DONT_CLOSE_POPUPS, !value);
63        self
64    }
65    /// Enables/disables full column span (text will still fit in the current column).
66    ///
67    /// Default: disabled
68    #[inline]
69    pub fn span_all_columns(mut self, value: bool) -> Self {
70        self.flags.set(SelectableFlags::SPAN_ALL_COLUMNS, value);
71        self
72    }
73    /// Enables/disables click event generation on double clicks.
74    ///
75    /// Default: disabled
76    #[inline]
77    pub fn allow_double_click(mut self, value: bool) -> Self {
78        self.flags.set(SelectableFlags::ALLOW_DOUBLE_CLICK, value);
79        self
80    }
81    /// Enables/disables the selectable.
82    ///
83    /// When disabled, it cannot be selected and the text uses the disabled text color.
84    ///
85    /// Default: disabled
86    #[inline]
87    pub fn disabled(mut self, value: bool) -> Self {
88        self.flags.set(SelectableFlags::DISABLED, value);
89        self
90    }
91    /// Sets the size of the selectable.
92    ///
93    /// For the X axis:
94    ///
95    /// - `> 0.0`: use given width
96    /// - `= 0.0`: use remaining width
97    ///
98    /// For the Y axis:
99    ///
100    /// - `> 0.0`: use given height
101    /// - `= 0.0`: use label height
102    #[inline]
103    pub fn size(mut self, size: [f32; 2]) -> Self {
104        self.size = size;
105        self
106    }
107    /// Builds the selectable.
108    ///
109    /// Returns true if the selectable was clicked.
110    pub fn build(self, ui: &Ui<'_>) -> bool {
111        unsafe {
112            sys::igSelectable_Bool(
113                ui.scratch_txt(self.label),
114                self.selected,
115                self.flags.bits() as i32,
116                self.size.into(),
117            )
118        }
119    }
120
121    /// Builds the selectable using a mutable reference to selected state.
122    pub fn build_with_ref(self, ui: &Ui<'_>, selected: &mut bool) -> bool {
123        if self.selected(*selected).build(ui) {
124            *selected = !*selected;
125            true
126        } else {
127            false
128        }
129    }
130}