dear_imgui/widget/
selectable.rs

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