dear_imgui/widget/
combo.rs1use std::borrow::Cow;
2
3use crate::sys;
4use crate::ui::Ui;
5use crate::widget::ComboBoxFlags;
6
7impl Ui {
9 #[must_use]
16 #[doc(alias = "BeginCombo")]
17 pub fn begin_combo(
18 &self,
19 label: impl AsRef<str>,
20 preview_value: impl AsRef<str>,
21 ) -> Option<ComboBoxToken<'_>> {
22 self.begin_combo_with_flags(label, preview_value, ComboBoxFlags::NONE)
23 }
24
25 #[must_use]
32 #[doc(alias = "BeginCombo")]
33 pub fn begin_combo_with_flags(
34 &self,
35 label: impl AsRef<str>,
36 preview_value: impl AsRef<str>,
37 flags: ComboBoxFlags,
38 ) -> Option<ComboBoxToken<'_>> {
39 let label_ptr = self.scratch_txt(label);
40 let preview_ptr = self.scratch_txt(preview_value);
41
42 let should_render = unsafe { sys::igBeginCombo(label_ptr, preview_ptr, flags.bits()) };
43
44 if should_render {
45 Some(ComboBoxToken::new(self))
46 } else {
47 None
48 }
49 }
50
51 #[must_use]
58 #[doc(alias = "BeginCombo")]
59 pub fn begin_combo_no_preview(&self, label: impl AsRef<str>) -> Option<ComboBoxToken<'_>> {
60 self.begin_combo_no_preview_with_flags(label, ComboBoxFlags::NONE)
61 }
62
63 #[must_use]
70 #[doc(alias = "BeginCombo")]
71 pub fn begin_combo_no_preview_with_flags(
72 &self,
73 label: impl AsRef<str>,
74 flags: ComboBoxFlags,
75 ) -> Option<ComboBoxToken<'_>> {
76 let label_ptr = self.scratch_txt(label);
77
78 let should_render = unsafe { sys::igBeginCombo(label_ptr, std::ptr::null(), flags.bits()) };
79
80 if should_render {
81 Some(ComboBoxToken::new(self))
82 } else {
83 None
84 }
85 }
86
87 #[doc(alias = "Combo")]
89 pub fn combo<V, L>(
90 &self,
91 label: impl AsRef<str>,
92 current_item: &mut usize,
93 items: &[V],
94 label_fn: L,
95 ) -> bool
96 where
97 for<'b> L: Fn(&'b V) -> Cow<'b, str>,
98 {
99 let label_fn = &label_fn;
100 let mut result = false;
101 let preview_value = items.get(*current_item).map(label_fn);
102
103 if let Some(combo_token) = self.begin_combo(
104 label,
105 preview_value.as_ref().map(|s| s.as_ref()).unwrap_or(""),
106 ) {
107 for (idx, item) in items.iter().enumerate() {
108 let is_selected = idx == *current_item;
109 if is_selected {
110 self.set_item_default_focus();
111 }
112
113 let clicked = self.selectable(label_fn(item).as_ref());
114
115 if clicked {
116 *current_item = idx;
117 result = true;
118 }
119 }
120 combo_token.end();
121 }
122
123 result
124 }
125
126 #[doc(alias = "Combo")]
128 pub fn combo_simple_string(
129 &self,
130 label: impl AsRef<str>,
131 current_item: &mut usize,
132 items: &[impl AsRef<str>],
133 ) -> bool {
134 self.combo(label, current_item, items, |s| Cow::Borrowed(s.as_ref()))
135 }
136
137 pub fn set_item_default_focus(&self) {
139 unsafe {
140 sys::igSetItemDefaultFocus();
141 }
142 }
143}
144
145#[derive(Clone, Debug)]
147#[must_use]
148pub struct ComboBox<'ui, Label, Preview = &'static str> {
149 pub label: Label,
150 pub preview_value: Option<Preview>,
151 pub flags: ComboBoxFlags,
152 pub ui: &'ui Ui,
153}
154
155impl<'ui, Label: AsRef<str>> ComboBox<'ui, Label> {
156 pub fn preview_value<P: AsRef<str>>(self, preview: P) -> ComboBox<'ui, Label, P> {
158 ComboBox {
159 label: self.label,
160 preview_value: Some(preview),
161 flags: self.flags,
162 ui: self.ui,
163 }
164 }
165
166 pub fn flags(mut self, flags: ComboBoxFlags) -> Self {
168 self.flags = flags;
169 self
170 }
171
172 #[must_use]
179 pub fn begin(self) -> Option<ComboBoxToken<'ui>> {
180 let label_ptr = self.ui.scratch_txt(&self.label);
181 let preview_ptr = self
182 .preview_value
183 .as_ref()
184 .map(|p| self.ui.scratch_txt(p))
185 .unwrap_or(std::ptr::null());
186
187 let should_render = unsafe { sys::igBeginCombo(label_ptr, preview_ptr, self.flags.bits()) };
188
189 if should_render {
190 Some(ComboBoxToken::new(self.ui))
191 } else {
192 None
193 }
194 }
195}
196
197#[must_use]
199pub struct ComboBoxToken<'ui> {
200 ui: &'ui Ui,
201}
202
203impl<'ui> ComboBoxToken<'ui> {
204 fn new(ui: &'ui Ui) -> Self {
206 ComboBoxToken { ui }
207 }
208
209 pub fn end(self) {
211 }
213}
214
215impl<'ui> Drop for ComboBoxToken<'ui> {
216 fn drop(&mut self) {
217 unsafe {
218 sys::igEndCombo();
219 }
220 }
221}