dear_imgui_rs/widget/
combo.rs1use std::borrow::Cow;
7
8use crate::sys;
9use crate::ui::Ui;
10use crate::widget::ComboBoxFlags;
11
12impl Ui {
14 #[must_use]
21 #[doc(alias = "BeginCombo")]
22 pub fn begin_combo(
23 &self,
24 label: impl AsRef<str>,
25 preview_value: impl AsRef<str>,
26 ) -> Option<ComboBoxToken<'_>> {
27 self.begin_combo_with_flags(label, preview_value, ComboBoxFlags::NONE)
28 }
29
30 #[must_use]
37 #[doc(alias = "BeginCombo")]
38 pub fn begin_combo_with_flags(
39 &self,
40 label: impl AsRef<str>,
41 preview_value: impl AsRef<str>,
42 flags: ComboBoxFlags,
43 ) -> Option<ComboBoxToken<'_>> {
44 let label_ptr = self.scratch_txt(label);
45 let preview_ptr = self.scratch_txt(preview_value);
46
47 let should_render = unsafe { sys::igBeginCombo(label_ptr, preview_ptr, flags.bits()) };
48
49 if should_render {
50 Some(ComboBoxToken::new(self))
51 } else {
52 None
53 }
54 }
55
56 #[must_use]
63 #[doc(alias = "BeginCombo")]
64 pub fn begin_combo_no_preview(&self, label: impl AsRef<str>) -> Option<ComboBoxToken<'_>> {
65 self.begin_combo_no_preview_with_flags(label, ComboBoxFlags::NONE)
66 }
67
68 #[must_use]
75 #[doc(alias = "BeginCombo")]
76 pub fn begin_combo_no_preview_with_flags(
77 &self,
78 label: impl AsRef<str>,
79 flags: ComboBoxFlags,
80 ) -> Option<ComboBoxToken<'_>> {
81 let label_ptr = self.scratch_txt(label);
82
83 let should_render = unsafe { sys::igBeginCombo(label_ptr, std::ptr::null(), flags.bits()) };
84
85 if should_render {
86 Some(ComboBoxToken::new(self))
87 } else {
88 None
89 }
90 }
91
92 #[doc(alias = "Combo")]
94 pub fn combo<V, L>(
95 &self,
96 label: impl AsRef<str>,
97 current_item: &mut usize,
98 items: &[V],
99 label_fn: L,
100 ) -> bool
101 where
102 for<'b> L: Fn(&'b V) -> Cow<'b, str>,
103 {
104 let label_fn = &label_fn;
105 let mut result = false;
106 let preview_value = items.get(*current_item).map(label_fn);
107
108 if let Some(combo_token) = self.begin_combo(
109 label,
110 preview_value.as_ref().map(|s| s.as_ref()).unwrap_or(""),
111 ) {
112 for (idx, item) in items.iter().enumerate() {
113 let is_selected = idx == *current_item;
114 if is_selected {
115 self.set_item_default_focus();
116 }
117
118 let clicked = self.selectable(label_fn(item).as_ref());
119
120 if clicked {
121 *current_item = idx;
122 result = true;
123 }
124 }
125 combo_token.end();
126 }
127
128 result
129 }
130
131 #[doc(alias = "Combo")]
133 pub fn combo_simple_string(
134 &self,
135 label: impl AsRef<str>,
136 current_item: &mut usize,
137 items: &[impl AsRef<str>],
138 ) -> bool {
139 self.combo(label, current_item, items, |s| Cow::Borrowed(s.as_ref()))
140 }
141
142 pub fn set_item_default_focus(&self) {
144 unsafe {
145 sys::igSetItemDefaultFocus();
146 }
147 }
148}
149
150#[derive(Clone, Debug)]
152#[must_use]
153pub struct ComboBox<'ui, Label, Preview = &'static str> {
154 pub label: Label,
155 pub preview_value: Option<Preview>,
156 pub flags: ComboBoxFlags,
157 pub ui: &'ui Ui,
158}
159
160impl<'ui, Label: AsRef<str>> ComboBox<'ui, Label> {
161 pub fn preview_value<P: AsRef<str>>(self, preview: P) -> ComboBox<'ui, Label, P> {
163 ComboBox {
164 label: self.label,
165 preview_value: Some(preview),
166 flags: self.flags,
167 ui: self.ui,
168 }
169 }
170
171 pub fn flags(mut self, flags: ComboBoxFlags) -> Self {
173 self.flags = flags;
174 self
175 }
176
177 #[must_use]
184 pub fn begin(self) -> Option<ComboBoxToken<'ui>> {
185 let label_ptr = self.ui.scratch_txt(&self.label);
186 let preview_ptr = self
187 .preview_value
188 .as_ref()
189 .map(|p| self.ui.scratch_txt(p))
190 .unwrap_or(std::ptr::null());
191
192 let should_render = unsafe { sys::igBeginCombo(label_ptr, preview_ptr, self.flags.bits()) };
193
194 if should_render {
195 Some(ComboBoxToken::new(self.ui))
196 } else {
197 None
198 }
199 }
200}
201
202#[must_use]
204pub struct ComboBoxToken<'ui> {
205 ui: &'ui Ui,
206}
207
208impl<'ui> ComboBoxToken<'ui> {
209 fn new(ui: &'ui Ui) -> Self {
211 ComboBoxToken { ui }
212 }
213
214 pub fn end(self) {
216 }
218}
219
220impl<'ui> Drop for ComboBoxToken<'ui> {
221 fn drop(&mut self) {
222 unsafe {
223 sys::igEndCombo();
224 }
225 }
226}