Skip to main content

dear_imgui_rs/widget/multi_select/
options.rs

1use crate::sys;
2
3bitflags::bitflags! {
4    /// Independent flags controlling multi-selection behavior.
5    ///
6    /// The click-selection policy, box-select mode, and scope are represented by
7    /// [`MultiSelectClickPolicy`], [`MultiSelectBoxSelect`], and [`MultiSelectScopeKind`].
8    #[repr(transparent)]
9    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
10    pub struct MultiSelectFlags: i32 {
11        /// No flags.
12        const NONE = sys::ImGuiMultiSelectFlags_None as i32;
13        /// Single-selection scope. Ctrl/Shift range selection is disabled.
14        const SINGLE_SELECT = sys::ImGuiMultiSelectFlags_SingleSelect as i32;
15        /// Disable `Ctrl+A` "select all" shortcut.
16        const NO_SELECT_ALL = sys::ImGuiMultiSelectFlags_NoSelectAll as i32;
17        /// Disable range selection (Shift+click / Shift+arrow).
18        const NO_RANGE_SELECT = sys::ImGuiMultiSelectFlags_NoRangeSelect as i32;
19        /// Disable automatic selection of newly focused items.
20        const NO_AUTO_SELECT = sys::ImGuiMultiSelectFlags_NoAutoSelect as i32;
21        /// Disable automatic clearing of selection when focus moves within the scope.
22        const NO_AUTO_CLEAR = sys::ImGuiMultiSelectFlags_NoAutoClear as i32;
23        /// Disable automatic clearing when reselecting the same range.
24        const NO_AUTO_CLEAR_ON_RESELECT =
25            sys::ImGuiMultiSelectFlags_NoAutoClearOnReselect as i32;
26        /// Disable drag-scrolling when box-selecting near edges of the scope.
27        const BOX_SELECT_NO_SCROLL = sys::ImGuiMultiSelectFlags_BoxSelectNoScroll as i32;
28        /// Clear selection when pressing Escape while the scope is focused.
29        const CLEAR_ON_ESCAPE = sys::ImGuiMultiSelectFlags_ClearOnEscape as i32;
30        /// Clear selection when clicking on empty space (void) inside the scope.
31        const CLEAR_ON_CLICK_VOID = sys::ImGuiMultiSelectFlags_ClearOnClickVoid as i32;
32        /// Disable default right-click behavior that selects item before opening a context menu.
33        const NO_SELECT_ON_RIGHT_CLICK =
34            sys::ImGuiMultiSelectFlags_NoSelectOnRightClick as i32;
35    }
36}
37
38/// Box-selection geometry for multi-select scopes.
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
40pub enum MultiSelectBoxSelect {
41    /// Same x-position/full-row items.
42    OneDimensional,
43    /// Arbitrary item layout, at a higher clipping cost.
44    TwoDimensional,
45}
46
47impl MultiSelectBoxSelect {
48    #[inline]
49    const fn raw(self) -> i32 {
50        match self {
51            Self::OneDimensional => sys::ImGuiMultiSelectFlags_BoxSelect1d as i32,
52            Self::TwoDimensional => sys::ImGuiMultiSelectFlags_BoxSelect2d as i32,
53        }
54    }
55}
56
57/// Click-selection policy for multi-select scopes.
58#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
59pub enum MultiSelectClickPolicy {
60    /// Apply selection on mouse down for unselected items and on mouse up for
61    /// selected items.
62    Auto,
63    /// Apply selection on mouse down for any clicked item.
64    ClickAlways,
65    /// Apply selection on mouse release for unselected items.
66    ClickRelease,
67}
68
69impl MultiSelectClickPolicy {
70    #[inline]
71    const fn raw(self) -> i32 {
72        match self {
73            Self::Auto => sys::ImGuiMultiSelectFlags_SelectOnAuto as i32,
74            Self::ClickAlways => sys::ImGuiMultiSelectFlags_SelectOnClickAlways as i32,
75            Self::ClickRelease => sys::ImGuiMultiSelectFlags_SelectOnClickRelease as i32,
76        }
77    }
78}
79
80/// Scope for box-select and clear-on-empty-click behavior.
81#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
82pub enum MultiSelectScopeKind {
83    /// Scope is the whole window.
84    Window,
85    /// Scope is the whole window and enables Dear ImGui's temporary X-axis navigation wrap helper.
86    WindowWithNavWrapX,
87    /// Scope is the rectangle between `BeginMultiSelect()` and `EndMultiSelect()`.
88    Rect,
89}
90
91impl MultiSelectScopeKind {
92    #[inline]
93    const fn raw(self) -> i32 {
94        match self {
95            Self::Window => sys::ImGuiMultiSelectFlags_ScopeWindow as i32,
96            Self::WindowWithNavWrapX => {
97                (sys::ImGuiMultiSelectFlags_ScopeWindow | sys::ImGuiMultiSelectFlags_NavWrapX)
98                    as i32
99            }
100            Self::Rect => sys::ImGuiMultiSelectFlags_ScopeRect as i32,
101        }
102    }
103}
104
105/// Complete multi-select options assembled from independent flags and an
106/// optional single-choice policies.
107#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
108pub struct MultiSelectOptions {
109    pub flags: MultiSelectFlags,
110    pub click_policy: Option<MultiSelectClickPolicy>,
111    pub box_select: Option<MultiSelectBoxSelect>,
112    pub scope: Option<MultiSelectScopeKind>,
113}
114
115impl MultiSelectOptions {
116    pub const fn new() -> Self {
117        Self {
118            flags: MultiSelectFlags::NONE,
119            click_policy: None,
120            box_select: None,
121            scope: None,
122        }
123    }
124
125    pub fn flags(mut self, flags: MultiSelectFlags) -> Self {
126        self.flags = flags;
127        self
128    }
129
130    pub fn click_policy(mut self, policy: MultiSelectClickPolicy) -> Self {
131        self.click_policy = Some(policy);
132        self
133    }
134
135    pub fn box_select(mut self, mode: MultiSelectBoxSelect) -> Self {
136        self.box_select = Some(mode);
137        self
138    }
139
140    pub fn scope(mut self, scope: MultiSelectScopeKind) -> Self {
141        self.scope = Some(scope);
142        self
143    }
144
145    pub fn bits(self) -> i32 {
146        self.raw()
147    }
148
149    #[inline]
150    pub(crate) fn raw(self) -> i32 {
151        self.flags.bits()
152            | self.click_policy.map_or(0, MultiSelectClickPolicy::raw)
153            | self.box_select.map_or(0, MultiSelectBoxSelect::raw)
154            | self.scope.map_or(0, MultiSelectScopeKind::raw)
155    }
156}
157
158impl Default for MultiSelectOptions {
159    fn default() -> Self {
160        Self::new()
161    }
162}
163
164impl From<MultiSelectFlags> for MultiSelectOptions {
165    fn from(flags: MultiSelectFlags) -> Self {
166        Self::new().flags(flags)
167    }
168}