dear_imgui_rs/widget/combo/
ui.rs1use std::borrow::Cow;
2
3use crate::sys;
4use crate::ui::Ui;
5
6use super::{ComboBoxFlags, ComboBoxOptions, ComboBoxPreviewMode, ComboBoxToken};
7
8impl Ui {
10 #[must_use]
17 #[doc(alias = "BeginCombo")]
18 pub fn begin_combo(
19 &self,
20 label: impl AsRef<str>,
21 preview_value: impl AsRef<str>,
22 ) -> Option<ComboBoxToken<'_>> {
23 self.begin_combo_with_flags(label, preview_value, ComboBoxFlags::NONE)
24 }
25
26 #[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: impl Into<ComboBoxOptions>,
38 ) -> Option<ComboBoxToken<'_>> {
39 let options = flags.into();
40 options.validate("Ui::begin_combo_with_flags()");
41 let (label_ptr, preview_ptr) = self.scratch_txt_two(label, preview_value);
42
43 let should_render = self.run_with_bound_context(|| unsafe {
44 sys::igBeginCombo(label_ptr, preview_ptr, options.raw())
45 });
46
47 if should_render {
48 Some(ComboBoxToken::new(self))
49 } else {
50 None
51 }
52 }
53
54 #[must_use]
61 #[doc(alias = "BeginCombo")]
62 pub fn begin_combo_no_preview(&self, label: impl AsRef<str>) -> Option<ComboBoxToken<'_>> {
63 self.begin_combo_no_preview_with_flags(label, ComboBoxFlags::NONE)
64 }
65
66 #[must_use]
73 #[doc(alias = "BeginCombo")]
74 pub fn begin_combo_no_preview_with_flags(
75 &self,
76 label: impl AsRef<str>,
77 flags: impl Into<ComboBoxOptions>,
78 ) -> Option<ComboBoxToken<'_>> {
79 let mut options = flags.into();
80 options.preview_mode = ComboBoxPreviewMode::NoPreview;
81 options.validate("Ui::begin_combo_no_preview_with_flags()");
82 let label_ptr = self.scratch_txt(label);
83
84 let should_render = self.run_with_bound_context(|| unsafe {
85 sys::igBeginCombo(label_ptr, std::ptr::null(), options.raw())
86 });
87
88 if should_render {
89 Some(ComboBoxToken::new(self))
90 } else {
91 None
92 }
93 }
94
95 #[doc(alias = "Combo")]
97 pub fn combo<V, L>(
98 &self,
99 label: impl AsRef<str>,
100 current_item: &mut usize,
101 items: &[V],
102 label_fn: L,
103 ) -> bool
104 where
105 for<'b> L: Fn(&'b V) -> Cow<'b, str>,
106 {
107 let label_fn = &label_fn;
108 let mut result = false;
109 let preview_value = items.get(*current_item).map(label_fn);
110
111 if let Some(combo_token) = self.begin_combo(
112 label,
113 preview_value.as_ref().map(|s| s.as_ref()).unwrap_or(""),
114 ) {
115 for (idx, item) in items.iter().enumerate() {
116 let is_selected = idx == *current_item;
117 if is_selected {
118 self.set_item_default_focus();
119 }
120
121 let clicked = self.selectable(label_fn(item).as_ref());
122
123 if clicked {
124 *current_item = idx;
125 result = true;
126 }
127 }
128 combo_token.end();
129 }
130
131 result
132 }
133
134 #[doc(alias = "Combo")]
139 pub fn combo_i32<V, L>(
140 &self,
141 label: impl AsRef<str>,
142 current_item: &mut i32,
143 items: &[V],
144 label_fn: L,
145 ) -> bool
146 where
147 for<'b> L: Fn(&'b V) -> Cow<'b, str>,
148 {
149 let label_fn = &label_fn;
150 let mut result = false;
151
152 let preview_value = if *current_item >= 0 {
153 items.get(*current_item as usize).map(|v| label_fn(v))
154 } else {
155 None
156 };
157
158 if let Some(combo_token) = self.begin_combo(
159 label,
160 preview_value.as_ref().map(|s| s.as_ref()).unwrap_or(""),
161 ) {
162 for (idx, item) in items.iter().enumerate() {
163 if idx > i32::MAX as usize {
164 break;
165 }
166 let idx_i32 = idx as i32;
167 let is_selected = idx_i32 == *current_item;
168 if is_selected {
169 self.set_item_default_focus();
170 }
171
172 let clicked = self.selectable(label_fn(item).as_ref());
173 if clicked {
174 *current_item = idx_i32;
175 result = true;
176 }
177 }
178 combo_token.end();
179 }
180
181 result
182 }
183
184 #[doc(alias = "Combo")]
186 pub fn combo_simple_string(
187 &self,
188 label: impl AsRef<str>,
189 current_item: &mut usize,
190 items: &[impl AsRef<str>],
191 ) -> bool {
192 self.combo(label, current_item, items, |s| Cow::Borrowed(s.as_ref()))
193 }
194
195 #[doc(alias = "Combo")]
197 pub fn combo_simple_string_i32(
198 &self,
199 label: impl AsRef<str>,
200 current_item: &mut i32,
201 items: &[impl AsRef<str>],
202 ) -> bool {
203 self.combo_i32(label, current_item, items, |s| Cow::Borrowed(s.as_ref()))
204 }
205
206 pub fn set_item_default_focus(&self) {
208 unsafe {
209 sys::igSetItemDefaultFocus();
210 }
211 }
212}