diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs index 2c589f7..66a0f74 100644 --- a/imgui-examples/examples/test_window_impl.rs +++ b/imgui-examples/examples/test_window_impl.rs @@ -452,10 +452,16 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { ui.input_text(im_str!("input text"), &mut state.text) .build(); ui.input_int(im_str!("input int"), &mut state.i0).build(); + ui.drag_int(im_str!("drag int"), &mut state.i0).build(); ui.input_float(im_str!("input float"), &mut state.f0) .step(0.01) .step_fast(1.0) .build(); + ui.drag_float(im_str!("drag float"), &mut state.f0) + .speed(0.001) + .min(-1.0) + .max(1.0) + .build(); ui.input_float3(im_str!("input float3"), &mut state.vec3f) .build(); ui.color_edit(im_str!("color 1"), &mut state.col1).build(); diff --git a/src/drag.rs b/src/drag.rs new file mode 100644 index 0000000..f5f43a3 --- /dev/null +++ b/src/drag.rs @@ -0,0 +1,375 @@ +use sys; +use std::marker::PhantomData; +use std::ptr; + +use super::{ImStr, Ui}; + + +macro_rules! impl_display_format { + ($InputType:ident) => { + #[inline] + pub fn display_format(mut self, display_format: &'p ImStr) -> Self { + self.display_format = display_format; + self + } + } +} + +macro_rules! impl_speed { + ($InputType:ident) => { + #[inline] + pub fn speed(mut self, value: f32) -> Self { + self.speed = value; + self + } + } +} + +macro_rules! impl_power { + ($InputType:ident) => { + #[inline] + pub fn power(mut self, value: f32) -> Self { + self.power = value; + self + } + } +} + +macro_rules! impl_min_max { + ($InputType:ident, $Value:ty) => { + #[inline] + pub fn min(mut self, value: $Value) -> Self { + self.min = value; + self + } + + #[inline] + pub fn max(mut self, value: $Value) -> Self { + self.max = value; + self + } + } +} + + +#[must_use] +pub struct DragFloat<'ui, 'p> { + label: &'p ImStr, + value: &'p mut f32, + speed: f32, + min: f32, + max: f32, + display_format: &'p ImStr, + power: f32, + _phantom: PhantomData<&'ui Ui<'ui>>, +} + + +impl<'ui, 'p> DragFloat<'ui, 'p> { + pub fn new(_: &Ui<'ui>, label: &'p ImStr, value: &'p mut f32) -> Self { + DragFloat { + label: label, + value: value, + speed: 1.0, + min: 0.0, + max: 0.0, + display_format: unsafe { ImStr::from_utf8_with_nul_unchecked(b"%.3f\0") }, + power: 1.0, + _phantom: PhantomData, + } + } + + pub fn build(self) -> bool { + unsafe { + sys::igDragFloat( + self.label.as_ptr(), + self.value as *mut f32, + self.speed, + self.min, + self.max, + self.display_format.as_ptr(), + self.power, + ) + } + } + + impl_display_format!(DragFloat); + impl_min_max!(DragFloat, f32); + impl_speed!(DragFloat); + impl_power!(DragFloat); +} + + +macro_rules! impl_drag_floatn { + ($DragFloatN:ident, $N:expr, $igDragFloatN:ident) => { + #[must_use] + pub struct $DragFloatN<'ui, 'p> { + label: &'p ImStr, + value: &'p mut [f32;$N], + speed: f32, + min: f32, + max: f32, + display_format: &'p ImStr, + power: f32, + _phantom: PhantomData<&'ui Ui<'ui>> + } + + impl<'ui, 'p> $DragFloatN<'ui, 'p> { + pub fn new(_: &Ui<'ui>, label: &'p ImStr, value: &'p mut [f32;$N]) -> Self { + $DragFloatN { + label: label, + value: value, + speed: 1.0, + min: 0.0, + max: 0.0, + display_format: unsafe { ImStr::from_utf8_with_nul_unchecked(b"%.3f\0") }, + power: 1.0, + _phantom: PhantomData + } + } + + pub fn build(self) -> bool { + unsafe { + sys::$igDragFloatN( + self.label.as_ptr(), + self.value.as_mut_ptr(), + self.speed, + self.min, + self.max, + self.display_format.as_ptr(), + self.power, + ) + } + } + + impl_display_format!(DragFloat); + impl_min_max!(DragFloat, f32); + impl_speed!(DragFloat); + impl_power!(DragFloat); + } + } +} + +impl_drag_floatn!(DragFloat2, 2, igDragFloat2); +impl_drag_floatn!(DragFloat3, 3, igDragFloat3); +impl_drag_floatn!(DragFloat4, 4, igDragFloat4); + +#[must_use] +pub struct DragFloatRange2<'ui, 'p> { + label: &'p ImStr, + current_min: &'p mut f32, + current_max: &'p mut f32, + speed: f32, + min: f32, + max: f32, + display_format: &'p ImStr, + display_format_max: Option<&'p ImStr>, + power: f32, + _phantom: PhantomData<&'ui Ui<'ui>>, +} + + +impl<'ui, 'p> DragFloatRange2<'ui, 'p> { + pub fn new( + _: &Ui<'ui>, + label: &'p ImStr, + current_min: &'p mut f32, + current_max: &'p mut f32, + ) -> Self { + DragFloatRange2 { + label: label, + current_min: current_min, + current_max: current_max, + speed: 1.0, + min: 0.0, + max: 0.0, + display_format: unsafe { ImStr::from_utf8_with_nul_unchecked(b"%.3f\0") }, + display_format_max: None, + power: 1.0, + _phantom: PhantomData, + } + } + + pub fn build(self) -> bool { + unsafe { + sys::igDragFloatRange2( + self.label.as_ptr(), + self.current_min as *mut f32, + self.current_max as *mut f32, + self.speed, + self.min, + self.max, + self.display_format.as_ptr(), + self.display_format_max.map_or(ptr::null(), |f| f.as_ptr()), + self.power, + ) + } + } + + #[inline] + pub fn display_format_max(mut self, display_format: Option<&'p ImStr>) -> Self { + self.display_format_max = display_format; + self + } + + impl_display_format!(DragFloatRange2); + impl_min_max!(DragFloatRange2, f32); + impl_speed!(DragFloatRange2); + impl_power!(DragFloatRange2); +} + + +#[must_use] +pub struct DragInt<'ui, 'p> { + label: &'p ImStr, + value: &'p mut i32, + speed: f32, + min: i32, + max: i32, + display_format: &'p ImStr, + _phantom: PhantomData<&'ui Ui<'ui>>, +} + + +impl<'ui, 'p> DragInt<'ui, 'p> { + pub fn new(_: &Ui<'ui>, label: &'p ImStr, value: &'p mut i32) -> Self { + DragInt { + label: label, + value: value, + speed: 1.0, + min: 0, + max: 0, + display_format: unsafe { ImStr::from_utf8_with_nul_unchecked(b"%.0f\0") }, + _phantom: PhantomData, + } + } + + pub fn build(self) -> bool { + unsafe { + sys::igDragInt( + self.label.as_ptr(), + self.value as *mut i32, + self.speed, + self.min, + self.max, + self.display_format.as_ptr(), + ) + } + } + + impl_display_format!(DragInt); + impl_min_max!(DragInt, i32); + impl_speed!(DragInt); +} + + +macro_rules! impl_drag_intn { + ($DragIntN:ident, $N:expr, $igDragIntN:ident) => { + #[must_use] + pub struct $DragIntN<'ui, 'p> { + label: &'p ImStr, + value: &'p mut [i32;$N], + speed: f32, + min: i32, + max: i32, + display_format: &'p ImStr, + _phantom: PhantomData<&'ui Ui<'ui>> + } + + impl<'ui, 'p> $DragIntN<'ui, 'p> { + pub fn new(_: &Ui<'ui>, label: &'p ImStr, value: &'p mut [i32;$N]) -> Self { + $DragIntN { + label: label, + value: value, + speed: 1.0, + min: 0, + max: 0, + display_format: unsafe { ImStr::from_utf8_with_nul_unchecked(b"%.0f\0") }, + _phantom: PhantomData + } + } + + pub fn build(self) -> bool { + unsafe { + sys::$igDragIntN( + self.label.as_ptr(), + self.value.as_mut_ptr(), + self.speed, + self.min, + self.max, + self.display_format.as_ptr(), + ) + } + } + + impl_display_format!(DragInt); + impl_min_max!(DragInt, i32); + impl_speed!(DragInt); + } + } +} + +impl_drag_intn!(DragInt2, 2, igDragInt2); +impl_drag_intn!(DragInt3, 3, igDragInt3); +impl_drag_intn!(DragInt4, 4, igDragInt4); + + + +#[must_use] +pub struct DragIntRange2<'ui, 'p> { + label: &'p ImStr, + current_min: &'p mut i32, + current_max: &'p mut i32, + speed: f32, + min: i32, + max: i32, + display_format: &'p ImStr, + display_format_max: Option<&'p ImStr>, + _phantom: PhantomData<&'ui Ui<'ui>>, +} + +impl<'ui, 'p> DragIntRange2<'ui, 'p> { + pub fn new( + _: &Ui<'ui>, + label: &'p ImStr, + current_min: &'p mut i32, + current_max: &'p mut i32, + ) -> Self { + DragIntRange2 { + label: label, + current_min: current_min, + current_max: current_max, + speed: 1.0, + min: 0, + max: 0, + display_format: unsafe { ImStr::from_utf8_with_nul_unchecked(b"%.0f\0") }, + display_format_max: None, + _phantom: PhantomData, + } + } + + pub fn build(self) -> bool { + unsafe { + sys::igDragIntRange2( + self.label.as_ptr(), + self.current_min as *mut i32, + self.current_max as *mut i32, + self.speed, + self.min, + self.max, + self.display_format.as_ptr(), + self.display_format_max.map_or(ptr::null(), |f| f.as_ptr()), + ) + } + } + + #[inline] + pub fn display_format_max(mut self, display_format: Option<&'p ImStr>) -> Self { + self.display_format_max = display_format; + self + } + + impl_display_format!(DragIntRange2); + impl_min_max!(DragIntRange2, i32); + impl_speed!(DragIntRange2); +} diff --git a/src/lib.rs b/src/lib.rs index f97a91b..888405c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,8 @@ pub use sys::{ImDrawIdx, ImDrawVert, ImGuiColorEditFlags, ImGuiHoveredFlags, ImG pub use child_frame::ChildFrame; pub use color_editors::{ColorButton, ColorEdit, ColorEditMode, ColorFormat, ColorPicker, ColorPickerMode, ColorPreview, EditableColor}; +pub use drag::{DragFloat, DragFloat2, DragFloat3, DragFloat4, DragInt, DragInt2, DragInt3, + DragInt4, DragFloatRange2, DragIntRange2}; pub use fonts::{FontGlyphRange, ImFontAtlas, ImFont, ImFontConfig}; pub use input::{InputFloat, InputFloat2, InputFloat3, InputFloat4, InputInt, InputInt2, InputInt3, InputInt4, InputText}; @@ -31,6 +33,7 @@ pub use window_draw_list::{ImColor, WindowDrawList, ChannelsSplit}; mod child_frame; mod color_editors; +mod drag; mod fonts; mod input; mod menus; @@ -674,6 +677,62 @@ impl<'ui> Ui<'ui> { } } +// Widgets: Drag +impl<'ui> Ui<'ui> { + pub fn drag_float<'p>(&self, label: &'p ImStr, value: &'p mut f32) -> DragFloat<'ui, 'p> { + DragFloat::new(self, label, value) + } + pub fn drag_float2<'p>( + &self, + label: &'p ImStr, + value: &'p mut [f32; 2], + ) -> DragFloat2<'ui, 'p> { + DragFloat2::new(self, label, value) + } + pub fn drag_float3<'p>( + &self, + label: &'p ImStr, + value: &'p mut [f32; 3], + ) -> DragFloat3<'ui, 'p> { + DragFloat3::new(self, label, value) + } + pub fn drag_float4<'p>( + &self, + label: &'p ImStr, + value: &'p mut [f32; 4], + ) -> DragFloat4<'ui, 'p> { + DragFloat4::new(self, label, value) + } + pub fn drag_float_range2<'p>( + &self, + label: &'p ImStr, + current_min: &'p mut f32, + current_max: &'p mut f32, + ) -> DragFloatRange2<'ui, 'p> { + DragFloatRange2::new(self, label, current_min, current_max) + } + pub fn drag_int<'p>(&self, label: &'p ImStr, value: &'p mut i32) -> DragInt<'ui, 'p> { + DragInt::new(self, label, value) + } + pub fn drag_int2<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 2]) -> DragInt2<'ui, 'p> { + DragInt2::new(self, label, value) + } + pub fn drag_int3<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 3]) -> DragInt3<'ui, 'p> { + DragInt3::new(self, label, value) + } + pub fn drag_int4<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 4]) -> DragInt4<'ui, 'p> { + DragInt4::new(self, label, value) + } + pub fn drag_int_range2<'p>( + &self, + label: &'p ImStr, + current_min: &'p mut i32, + current_max: &'p mut i32, + ) -> DragIntRange2<'ui, 'p> { + DragIntRange2::new(self, label, current_min, current_max) + } +} + // Widgets: Sliders impl<'ui> Ui<'ui> { pub fn slider_float<'p>(