mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-15 07:28:28 +00:00
converted combo_box and drag
This commit is contained in:
parent
08d285d029
commit
540aa5f292
@ -480,7 +480,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
|
||||
|
||||
ui.separator();
|
||||
ui.label_text(im_str!("label"), im_str!("Value"));
|
||||
ComboBox::new(&"combo").build_simple_string(ui,
|
||||
ui.combo_simple_string("combo",
|
||||
&mut state.item,
|
||||
&[
|
||||
im_str!("aaaa"),
|
||||
@ -502,8 +502,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
|
||||
im_str!("JJJJ"),
|
||||
im_str!("KKKK"),
|
||||
];
|
||||
ComboBox::new(im_str!("combo scroll")).build_simple_string(ui, &mut state.item2, &items);
|
||||
|
||||
ui.combo_simple_string("combo scroll", &mut state.item2, &items);
|
||||
ui.list_box(im_str!("list"), &mut state.item3, &items, 8);
|
||||
|
||||
|
||||
@ -540,7 +539,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
|
||||
.hint(im_str!("enter text here"))
|
||||
.build();
|
||||
ui.input_int(im_str!("input int"), &mut state.i0).build();
|
||||
Drag::new(im_str!("drag int")).build(ui, &mut state.i0);
|
||||
// Drag::new(im_str!("drag int")).build(ui, &mut state.i0);
|
||||
ui.input_float(im_str!("input float"), &mut state.f0)
|
||||
.step(0.01)
|
||||
.step_fast(1.0)
|
||||
@ -808,7 +807,7 @@ CTRL+click on individual component to input value.\n",
|
||||
);
|
||||
|
||||
let items = &[im_str!("aaaa"), im_str!("bbbb"), im_str!("cccc"), im_str!("dddd"), im_str!("eeee")];
|
||||
ComboBox::new(im_str!("Combo")).build_simple_string(ui, &mut state.stacked_modals_item, items);
|
||||
ui.combo_simple_string("Combo", &mut state.stacked_modals_item, items);
|
||||
|
||||
ColorEdit::new(im_str!("color"), &mut state.stacked_modals_color).build(ui);
|
||||
|
||||
@ -904,8 +903,8 @@ fn show_example_menu_file<'a>(ui: &Ui<'a>, state: &mut FileMenuState) {
|
||||
ui.input_float(im_str!("Input"), &mut state.f)
|
||||
.step(0.1)
|
||||
.build();
|
||||
let items = [im_str!("Yes"), im_str!("No"), im_str!("Maybe")];
|
||||
ComboBox::new(im_str!("Combo")).build_simple_string(ui, &mut state.n, &items);
|
||||
let items = ["Yes", "No", "Maybe"];
|
||||
ui.combo_simple_string("Combo", &mut state.n, &items);
|
||||
ui.checkbox(im_str!("Check"), &mut state.b);
|
||||
menu.end();
|
||||
}
|
||||
|
||||
@ -157,6 +157,31 @@ impl<'ui> Ui<'ui> {
|
||||
}
|
||||
}
|
||||
|
||||
fn scratch_txt_with_opt(
|
||||
&self,
|
||||
txt_0: impl AsRef<str>,
|
||||
txt_1: Option<impl AsRef<str>>,
|
||||
) -> (*const sys::cty::c_char, *const sys::cty::c_char) {
|
||||
unsafe {
|
||||
let handle = &mut *self.buffer.get();
|
||||
handle.clear();
|
||||
handle.extend(txt_0.as_ref().as_bytes());
|
||||
handle.push(b'\0');
|
||||
|
||||
if let Some(txt_1) = txt_1 {
|
||||
handle.extend(txt_1.as_ref().as_bytes());
|
||||
handle.push(b'\0');
|
||||
|
||||
(
|
||||
handle.as_ptr() as *const _,
|
||||
handle.as_ptr().add(txt_1.as_ref().len() + 1) as *const _,
|
||||
)
|
||||
} else {
|
||||
(handle.as_ptr() as *const _, std::ptr::null())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an immutable reference to the inputs/outputs object
|
||||
#[doc(alias = "GetIO")]
|
||||
pub fn io(&self) -> &Io {
|
||||
|
||||
@ -54,7 +54,7 @@ pub struct ComboBoxFlags: u32 {
|
||||
/// Builder for a combo box widget
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[must_use]
|
||||
pub struct ComboBox<T, P = String> {
|
||||
pub struct ComboBox<T, P> {
|
||||
label: T,
|
||||
preview_value: Option<P>,
|
||||
flags: ComboBoxFlags,
|
||||
@ -63,21 +63,14 @@ pub struct ComboBox<T, P = String> {
|
||||
impl<'a, T: AsRef<str>, P: AsRef<str>> ComboBox<T, P> {
|
||||
/// Constructs a new combo box builder.
|
||||
#[doc(alias = "BeginCombo")]
|
||||
pub fn new(label: T) -> Self {
|
||||
pub fn new(label: T, preview_value: Option<P>) -> Self {
|
||||
ComboBox {
|
||||
label,
|
||||
preview_value: None,
|
||||
preview_value,
|
||||
flags: ComboBoxFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the preview value displayed in the preview box (if visible).
|
||||
#[inline]
|
||||
pub fn preview_value(mut self, preview_value: P) -> Self {
|
||||
self.preview_value = Some(preview_value);
|
||||
self
|
||||
}
|
||||
|
||||
/// Replaces all current settings with the given flags.
|
||||
#[inline]
|
||||
pub fn flags(mut self, flags: ComboBoxFlags) -> Self {
|
||||
@ -173,48 +166,143 @@ create_token!(
|
||||
);
|
||||
|
||||
/// # Convenience functions
|
||||
impl<'a, T: AsRef<str> + Clone> ComboBox<T, Cow<'a, str>> {
|
||||
/// Builds a simple combo box for choosing from a slice of values
|
||||
impl<'ui> Ui<'ui> {
|
||||
/// Creates a combo box which can be appended to with `Selectable::new`.
|
||||
///
|
||||
/// If you do not want to provide a preview, use [begin_combo_no_preview]. If you want
|
||||
/// to pass flags, use [begin_combo_with_flags].
|
||||
///
|
||||
/// Returns `Some(ComboBoxToken)` if the combo box is open. After content has been
|
||||
/// rendered, the token must be ended by calling `.end()`.
|
||||
///
|
||||
/// Returns `None` if the combo box is not open and no content should be rendered.
|
||||
#[must_use]
|
||||
#[doc(alias = "BeginCombo")]
|
||||
pub fn build_simple<V, L>(
|
||||
mut self,
|
||||
ui: &Ui,
|
||||
pub fn begin_combo(
|
||||
&self,
|
||||
label: impl AsRef<str>,
|
||||
preview_value: impl AsRef<str>,
|
||||
) -> Option<ComboBoxToken<'ui>> {
|
||||
self.begin_combo_with_flags(label, preview_value, ComboBoxFlags::empty())
|
||||
}
|
||||
|
||||
/// Creates a combo box which can be appended to with `Selectable::new`.
|
||||
///
|
||||
/// If you do not want to provide a preview, use [begin_combo_no_preview].
|
||||
/// Returns `Some(ComboBoxToken)` if the combo box is open. After content has been
|
||||
/// rendered, the token must be ended by calling `.end()`.
|
||||
///
|
||||
/// Returns `None` if the combo box is not open and no content should be rendered.
|
||||
#[must_use]
|
||||
#[doc(alias = "BeginCombo")]
|
||||
pub fn begin_combo_with_flags(
|
||||
&self,
|
||||
label: impl AsRef<str>,
|
||||
preview_value: impl AsRef<str>,
|
||||
flags: ComboBoxFlags,
|
||||
) -> Option<ComboBoxToken<'ui>> {
|
||||
self._begin_combo(label, Some(preview_value), flags)
|
||||
}
|
||||
|
||||
/// Creates a combo box which can be appended to with `Selectable::new`.
|
||||
///
|
||||
/// If you want to provide a preview, use [begin_combo]. If you want
|
||||
/// to pass flags, use [begin_combo_no_preview_with_flags].
|
||||
///
|
||||
/// Returns `Some(ComboBoxToken)` if the combo box is open. After content has been
|
||||
/// rendered, the token must be ended by calling `.end()`.
|
||||
///
|
||||
/// Returns `None` if the combo box is not open and no content should be rendered.
|
||||
#[must_use]
|
||||
#[doc(alias = "BeginCombo")]
|
||||
pub fn begin_combo_no_preview(&self, label: impl AsRef<str>) -> Option<ComboBoxToken<'ui>> {
|
||||
self.begin_combo_no_preview_with_flags(label, ComboBoxFlags::empty())
|
||||
}
|
||||
|
||||
/// Creates a combo box which can be appended to with `Selectable::new`.
|
||||
///
|
||||
/// If you do not want to provide a preview, use [begin_combo_no_preview].
|
||||
/// Returns `Some(ComboBoxToken)` if the combo box is open. After content has been
|
||||
/// rendered, the token must be ended by calling `.end()`.
|
||||
///
|
||||
/// Returns `None` if the combo box is not open and no content should be rendered.
|
||||
#[must_use]
|
||||
#[doc(alias = "BeginCombo")]
|
||||
pub fn begin_combo_no_preview_with_flags(
|
||||
&self,
|
||||
label: impl AsRef<str>,
|
||||
flags: ComboBoxFlags,
|
||||
) -> Option<ComboBoxToken<'ui>> {
|
||||
self._begin_combo(label, Option::<&'static str>::None, flags)
|
||||
}
|
||||
|
||||
/// This is the internal begin combo method that they all...eventually call.
|
||||
fn _begin_combo(
|
||||
&self,
|
||||
label: impl AsRef<str>,
|
||||
preview_value: Option<impl AsRef<str>>,
|
||||
flags: ComboBoxFlags,
|
||||
) -> Option<ComboBoxToken<'ui>> {
|
||||
let should_render = unsafe {
|
||||
let (ptr_one, ptr_two) = self.scratch_txt_with_opt(label, preview_value);
|
||||
sys::igBeginCombo(ptr_one, ptr_two, flags.bits() as i32)
|
||||
};
|
||||
if should_render {
|
||||
Some(ComboBoxToken::new(self))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
/// Builds a simple combo box for choosing from a slice of values
|
||||
#[doc(alias = "Combo")]
|
||||
pub fn combo<V, L>(
|
||||
&self,
|
||||
label: impl AsRef<str>,
|
||||
current_item: &mut usize,
|
||||
items: &'a [V],
|
||||
label_fn: &L,
|
||||
items: &[V],
|
||||
label_fn: L,
|
||||
) -> bool
|
||||
where
|
||||
for<'b> L: Fn(&'b V) -> Cow<'b, str>,
|
||||
{
|
||||
use crate::widget::selectable::Selectable;
|
||||
let label_fn = &label_fn;
|
||||
let mut result = false;
|
||||
let preview_value = items.get(*current_item).map(label_fn);
|
||||
if self.preview_value.is_none() {
|
||||
if let Some(preview_value) = preview_value {
|
||||
self = self.preview_value(preview_value);
|
||||
}
|
||||
}
|
||||
if let Some(_cb) = self.begin(ui) {
|
||||
|
||||
if let Some(_cb) = self._begin_combo(label, preview_value, ComboBoxFlags::empty()) {
|
||||
for (idx, item) in items.iter().enumerate() {
|
||||
let text = label_fn(item);
|
||||
let selected = idx == *current_item;
|
||||
if Selectable::new(&text).selected(selected).build(ui) {
|
||||
if Selectable::new(&text).selected(selected).build(self) {
|
||||
*current_item = idx;
|
||||
result = true;
|
||||
}
|
||||
if selected {
|
||||
ui.set_item_default_focus();
|
||||
self.set_item_default_focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
/// Builds a simple combo box for choosing from a slice of strings
|
||||
#[doc(alias = "BeginCombo")]
|
||||
pub fn build_simple_string<S>(self, ui: &Ui, current_item: &mut usize, items: &[&S]) -> bool
|
||||
where
|
||||
S: AsRef<str> + ?Sized,
|
||||
{
|
||||
self.build_simple(ui, current_item, items, &|&s| s.as_ref().into())
|
||||
|
||||
/// Builds a simple combo box for choosing from a slice of values
|
||||
#[doc(alias = "Combo")]
|
||||
pub fn combo_simple_string(
|
||||
&self,
|
||||
label: impl AsRef<str>,
|
||||
current_item: &mut usize,
|
||||
items: &[impl AsRef<str>],
|
||||
) -> bool {
|
||||
self.combo(label, current_item, items, |s| Cow::Borrowed(s.as_ref()))
|
||||
}
|
||||
|
||||
// /// Builds a simple combo box for choosing from a slice of strings
|
||||
// #[doc(alias = "BeginCombo")]
|
||||
// pub fn build_simple_string<S>(self, ui: &Ui, current_item: &mut usize, items: &[&S]) -> bool
|
||||
// where
|
||||
// S: AsRef<str> + ?Sized,
|
||||
// {
|
||||
// self.build_simple(ui, current_item, items, &|&s| s.as_ref().into())
|
||||
// }
|
||||
}
|
||||
|
||||
@ -10,19 +10,19 @@ use crate::Ui;
|
||||
/// Builder for a drag slider widget.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[must_use]
|
||||
pub struct Drag<'a, T: DataTypeKind> {
|
||||
label: &'a ImStr,
|
||||
pub struct Drag<'a, T, L> {
|
||||
label: L,
|
||||
speed: f32,
|
||||
min: Option<T>,
|
||||
max: Option<T>,
|
||||
display_format: Option<&'a ImStr>,
|
||||
display_format: Option<&'a str>,
|
||||
flags: SliderFlags,
|
||||
}
|
||||
|
||||
impl<'a, T: DataTypeKind> Drag<'a, T> {
|
||||
impl<'a, L: AsRef<str>, T: DataTypeKind> Drag<'a, T, L> {
|
||||
/// Constructs a new drag slider builder.
|
||||
#[doc(alias = "DragScalar", alias = "DragScalarN")]
|
||||
pub fn new(label: &ImStr) -> Drag<T> {
|
||||
pub fn new(label: L) -> Self {
|
||||
Drag {
|
||||
label,
|
||||
speed: 1.0,
|
||||
@ -49,7 +49,7 @@ impl<'a, T: DataTypeKind> Drag<'a, T> {
|
||||
}
|
||||
/// Sets the display format using *a C-style printf string*
|
||||
#[inline]
|
||||
pub fn display_format(mut self, display_format: &'a ImStr) -> Self {
|
||||
pub fn display_format(mut self, display_format: &'a str) -> Self {
|
||||
self.display_format = Some(display_format);
|
||||
self
|
||||
}
|
||||
@ -62,10 +62,12 @@ impl<'a, T: DataTypeKind> Drag<'a, T> {
|
||||
/// Builds a drag slider that is bound to the given value.
|
||||
///
|
||||
/// Returns true if the slider value was changed.
|
||||
pub fn build(self, _: &Ui, value: &mut T) -> bool {
|
||||
pub fn build(self, ui: &Ui, value: &mut T) -> bool {
|
||||
unsafe {
|
||||
let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
||||
|
||||
sys::igDragScalar(
|
||||
self.label.as_ptr(),
|
||||
one,
|
||||
T::KIND as i32,
|
||||
value as *mut T as *mut c_void,
|
||||
self.speed,
|
||||
@ -77,9 +79,7 @@ impl<'a, T: DataTypeKind> Drag<'a, T> {
|
||||
.as_ref()
|
||||
.map(|max| max as *const T)
|
||||
.unwrap_or(ptr::null()) as *const c_void,
|
||||
self.display_format
|
||||
.map(ImStr::as_ptr)
|
||||
.unwrap_or(ptr::null()),
|
||||
two,
|
||||
self.flags.bits() as i32,
|
||||
)
|
||||
}
|
||||
@ -87,10 +87,12 @@ impl<'a, T: DataTypeKind> Drag<'a, T> {
|
||||
/// Builds a horizontal array of multiple drag sliders attached to the given slice.
|
||||
///
|
||||
/// Returns true if any slider value was changed.
|
||||
pub fn build_array(self, _: &Ui, values: &mut [T]) -> bool {
|
||||
pub fn build_array(self, ui: &Ui, values: &mut [T]) -> bool {
|
||||
unsafe {
|
||||
let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
||||
|
||||
sys::igDragScalarN(
|
||||
self.label.as_ptr(),
|
||||
one,
|
||||
T::KIND as i32,
|
||||
values.as_mut_ptr() as *mut c_void,
|
||||
values.len() as i32,
|
||||
@ -103,9 +105,7 @@ impl<'a, T: DataTypeKind> Drag<'a, T> {
|
||||
.as_ref()
|
||||
.map(|max| max as *const T)
|
||||
.unwrap_or(ptr::null()) as *const c_void,
|
||||
self.display_format
|
||||
.map(ImStr::as_ptr)
|
||||
.unwrap_or(ptr::null()),
|
||||
two,
|
||||
self.flags.bits() as i32,
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user