dear_imgui_rs/widget/
selectable.rs1#![allow(
7 clippy::cast_possible_truncation,
8 clippy::cast_sign_loss,
9 clippy::as_conversions
10)]
11use crate::Ui;
12use crate::sys;
13
14fn assert_non_negative_finite_vec2(caller: &str, name: &str, value: [f32; 2]) {
15 assert!(
16 value[0].is_finite() && value[1].is_finite(),
17 "{caller} {name} must contain finite values"
18 );
19 assert!(
20 value[0] >= 0.0 && value[1] >= 0.0,
21 "{caller} {name} must contain non-negative values"
22 );
23}
24
25fn validate_selectable_flags(caller: &str, flags: SelectableFlags) {
26 let unsupported = flags.bits() & !SelectableFlags::all().bits();
27 assert!(
28 unsupported == 0,
29 "{caller} received unsupported ImGuiSelectableFlags bits: 0x{unsupported:X}"
30 );
31}
32
33bitflags::bitflags! {
34 #[repr(transparent)]
36 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
37 pub struct SelectableFlags: i32 {
38 const NO_AUTO_CLOSE_POPUPS = sys::ImGuiSelectableFlags_NoAutoClosePopups as i32;
40 const SPAN_ALL_COLUMNS = sys::ImGuiSelectableFlags_SpanAllColumns as i32;
42 const ALLOW_DOUBLE_CLICK = sys::ImGuiSelectableFlags_AllowDoubleClick as i32;
44 const DISABLED = sys::ImGuiSelectableFlags_Disabled as i32;
46 const ALLOW_OVERLAP = sys::ImGuiSelectableFlags_AllowOverlap as i32;
48 const HIGHLIGHT = sys::ImGuiSelectableFlags_Highlight as i32;
50 const SELECT_ON_NAV = sys::ImGuiSelectableFlags_SelectOnNav as i32;
52 }
53}
54
55impl Ui {
56 #[doc(alias = "Selectable")]
62 pub fn selectable<T: AsRef<str>>(&self, label: T) -> bool {
63 self.selectable_config(label).build()
64 }
65
66 #[doc(alias = "Selectable")]
68 pub fn selectable_config<T: AsRef<str>>(&self, label: T) -> Selectable<'_, T> {
69 Selectable {
70 label,
71 selected: false,
72 flags: SelectableFlags::empty(),
73 size: [0.0, 0.0],
74 ui: self,
75 }
76 }
77}
78
79#[derive(Clone, Debug)]
81#[must_use]
82pub struct Selectable<'ui, T> {
83 label: T,
84 selected: bool,
85 flags: SelectableFlags,
86 size: [f32; 2],
87 ui: &'ui Ui,
88}
89
90impl<'ui, T: AsRef<str>> Selectable<'ui, T> {
91 #[doc(alias = "Selectable")]
93 #[deprecated(
94 since = "0.9.0",
95 note = "use `ui.selectable` or `ui.selectable_config`"
96 )]
97 pub fn new(label: T, ui: &'ui Ui) -> Self {
98 Selectable {
99 label,
100 selected: false,
101 flags: SelectableFlags::empty(),
102 size: [0.0, 0.0],
103 ui,
104 }
105 }
106 pub fn flags(mut self, flags: SelectableFlags) -> Self {
108 self.flags = flags;
109 self
110 }
111 pub fn selected(mut self, selected: bool) -> Self {
113 self.selected = selected;
114 self
115 }
116 pub fn close_popups(mut self, value: bool) -> Self {
120 self.flags
121 .set(SelectableFlags::NO_AUTO_CLOSE_POPUPS, !value);
122 self
123 }
124 pub fn span_all_columns(mut self, value: bool) -> Self {
128 self.flags.set(SelectableFlags::SPAN_ALL_COLUMNS, value);
129 self
130 }
131 pub fn allow_double_click(mut self, value: bool) -> Self {
135 self.flags.set(SelectableFlags::ALLOW_DOUBLE_CLICK, value);
136 self
137 }
138 pub fn disabled(mut self, value: bool) -> Self {
144 self.flags.set(SelectableFlags::DISABLED, value);
145 self
146 }
147 pub fn size(mut self, size: impl Into<[f32; 2]>) -> Self {
159 self.size = size.into();
160 self
161 }
162
163 pub fn build(self) -> bool {
167 validate_selectable_flags("Selectable::build()", self.flags);
168 assert_non_negative_finite_vec2("Selectable::build()", "size", self.size);
169 let size_vec = sys::ImVec2 {
170 x: self.size[0],
171 y: self.size[1],
172 };
173 unsafe {
174 sys::igSelectable_Bool(
175 self.ui.scratch_txt(self.label),
176 self.selected,
177 self.flags.bits(),
178 size_vec,
179 )
180 }
181 }
182
183 pub fn build_with_ref(self, selected: &mut bool) -> bool {
185 validate_selectable_flags("Selectable::build_with_ref()", self.flags);
186 assert_non_negative_finite_vec2("Selectable::build_with_ref()", "size", self.size);
187 let size_vec = sys::ImVec2 {
188 x: self.size[0],
189 y: self.size[1],
190 };
191 unsafe {
192 sys::igSelectable_BoolPtr(
193 self.ui.scratch_txt(self.label),
194 selected as *mut bool,
195 self.flags.bits(),
196 size_vec,
197 )
198 }
199 }
200}