dear_imgui_rs/widget/
selectable.rs

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