init draft

This commit is contained in:
Jack Spira 2021-09-04 19:26:20 -07:00
parent 7122366a43
commit 7b644bf159
5 changed files with 64 additions and 119 deletions

View File

@ -41,29 +41,27 @@ fn example_1(ui: &Ui, state: &mut State) {
ui.text("Unsigned: u8 u16 u32 u64");
ui.text("Floats: f32 f64");
Slider::new(im_str!("u8 value"))
Slider::new(im_str!("u8 value"), 0, 255)
.build(ui, &mut state.u8_value);
Slider::new(im_str!("f32 value"))
Slider::new(im_str!("f32 value"), -f32::MIN, f32::MAX)
.build(ui, &mut state.f32_value);
ui.separator();
ui.text("Slider range can be limited:");
Slider::new(im_str!("i32 value with range"))
.range(-999 ..= 999)
Slider::new(im_str!("i32 value with range"), -999, 999)
.build(ui, &mut state.i32_value);
ui.text("Note that for 32-bit/64-bit types, sliders are always limited to half of the natural type range!");
ui.separator();
ui.text("Value formatting can be customized with a C-style printf string:");
Slider::new(im_str!("f64 value with custom formatting"))
.range(-999_999_999.0 ..= 999_999_999.0)
Slider::new(im_str!("f64 value with custom formatting"), -999_999_999.0, 999_999_999.0)
.display_format(im_str!("%09.0f"))
.build(ui, &mut state.f64_formatted);
ui.separator();
ui.text("Vertical sliders require a size parameter but otherwise work in a similar way:");
VerticalSlider::new(im_str!("vertical\nu8 value"), [50.0, 50.0])
VerticalSlider::new(im_str!("vertical\nu8 value"), [50.0, 50.0], u8::MIN, u8::MAX)
.build(ui, &mut state.u8_value);
});
}
@ -74,11 +72,11 @@ fn example_2(ui: &Ui, state: &mut State) {
.position([20.0, 120.0], Condition::Appearing);
w.build(ui, || {
ui.text("You can easily build a slider group from an array of values:");
Slider::new(im_str!("[u8; 4]")).build_array(ui, &mut state.array);
Slider::new(im_str!("[u8; 4]"), 0, u8::MAX).build_array(ui, &mut state.array);
ui.text("You don't need to use arrays with known length; arbitrary slices can be used:");
let slice: &mut [u8] = &mut state.array[1..=2];
Slider::new(im_str!("subslice")).build_array(ui, slice);
Slider::new(im_str!("subslice"), 0, u8::MAX).build_array(ui, slice);
});
}

View File

@ -448,7 +448,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
));
ui.spacing();
Slider::new(im_str!("Wrap width")).range(-20.0 ..= 600.0)
Slider::new(im_str!("Wrap width"), -20.0, 600.0)
.display_format(im_str!("%.0f"))
.build(ui, &mut state.wrap_width);
@ -545,7 +545,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
.step(0.01)
.step_fast(1.0)
.build();
Drag::new(im_str!("drag float")).range(-1.0..=1.0).speed(0.001).build(ui, &mut state.f0);
Drag::new(im_str!("drag float")).range(-1.0, 1.0).speed(0.001).build(ui, &mut state.f0);
ui.input_float3(im_str!("input float3"), &mut state.vec3f)
.build();
ColorEdit::new(im_str!("color 1"), &mut state.col1).build(ui);
@ -899,9 +899,7 @@ fn show_example_menu_file<'a>(ui: &Ui<'a>, state: &mut FileMenuState) {
ui.text(format!("Scrolling Text {}", i));
}
});
Slider::new(im_str!("Value"))
.range(0.0..=1.0)
.build(ui, &mut state.f);
Slider::new(im_str!("Value"), 0.0, 1.0).build(ui, &mut state.f);
ui.input_float(im_str!("Input"), &mut state.f)
.step(0.1)
@ -936,9 +934,7 @@ fn show_example_app_auto_resize(ui: &Ui, state: &mut AutoResizeState, opened: &m
Note that you probably don't want to query the window size to
output your content because that would create a feedback loop.",
);
Slider::new(im_str!("Number of lines"))
.range(1..=20)
.build(ui, &mut state.lines);
Slider::new(im_str!("Number of lines"), 1, 20).build(ui, &mut state.lines);
for i in 0..state.lines {
ui.text(format!("{:2$}This is line {}", "", i, i as usize * 4));
}

View File

@ -1,6 +1,5 @@
//! Internal raw utilities (don't use unless you know what you're doing!)
use std::ops::{RangeFrom, RangeInclusive, RangeToInclusive};
use std::slice;
/// A generic version of the raw imgui-sys ImVector struct types
@ -127,94 +126,34 @@ pub enum DataType {
/// representation in memory as the primitive value described by the associated `KIND` constant.
pub unsafe trait DataTypeKind: Copy {
const KIND: DataType;
const SLIDER_MIN: Self;
const SLIDER_MAX: Self;
}
unsafe impl DataTypeKind for i8 {
const KIND: DataType = DataType::I8;
const SLIDER_MIN: Self = std::i8::MIN;
const SLIDER_MAX: Self = std::i8::MAX;
}
unsafe impl DataTypeKind for u8 {
const KIND: DataType = DataType::U8;
const SLIDER_MIN: Self = std::u8::MIN;
const SLIDER_MAX: Self = std::u8::MAX;
}
unsafe impl DataTypeKind for i16 {
const KIND: DataType = DataType::I16;
const SLIDER_MIN: Self = std::i16::MIN;
const SLIDER_MAX: Self = std::i16::MAX;
}
unsafe impl DataTypeKind for u16 {
const KIND: DataType = DataType::U16;
const SLIDER_MIN: Self = std::u16::MIN;
const SLIDER_MAX: Self = std::u16::MAX;
}
unsafe impl DataTypeKind for i32 {
const KIND: DataType = DataType::I32;
const SLIDER_MIN: Self = std::i32::MIN / 2;
const SLIDER_MAX: Self = std::i32::MAX / 2;
}
unsafe impl DataTypeKind for u32 {
const KIND: DataType = DataType::U32;
const SLIDER_MIN: Self = std::u32::MIN / 2;
const SLIDER_MAX: Self = std::u32::MAX / 2;
}
unsafe impl DataTypeKind for i64 {
const KIND: DataType = DataType::I64;
const SLIDER_MIN: Self = std::i64::MIN / 2;
const SLIDER_MAX: Self = std::i64::MAX / 2;
}
unsafe impl DataTypeKind for u64 {
const KIND: DataType = DataType::U64;
const SLIDER_MIN: Self = std::u64::MIN / 2;
const SLIDER_MAX: Self = std::u64::MAX / 2;
}
unsafe impl DataTypeKind for f32 {
const KIND: DataType = DataType::F32;
const SLIDER_MIN: Self = std::f32::MIN / 2.0;
const SLIDER_MAX: Self = std::f32::MAX / 2.0;
}
unsafe impl DataTypeKind for f64 {
const KIND: DataType = DataType::F64;
const SLIDER_MIN: Self = std::f64::MIN / 2.0;
const SLIDER_MAX: Self = std::f64::MAX / 2.0;
}
pub trait InclusiveRangeBounds<T: Copy> {
fn start_bound(&self) -> Option<&T>;
fn end_bound(&self) -> Option<&T>;
}
impl<T: Copy> InclusiveRangeBounds<T> for RangeFrom<T> {
#[inline]
fn start_bound(&self) -> Option<&T> {
Some(&self.start)
}
#[inline]
fn end_bound(&self) -> Option<&T> {
None
}
}
impl<T: Copy> InclusiveRangeBounds<T> for RangeInclusive<T> {
#[inline]
fn start_bound(&self) -> Option<&T> {
Some(self.start())
}
#[inline]
fn end_bound(&self) -> Option<&T> {
Some(self.end())
}
}
impl<T: Copy> InclusiveRangeBounds<T> for RangeToInclusive<T> {
#[inline]
fn start_bound(&self) -> Option<&T> {
None
}
#[inline]
fn end_bound(&self) -> Option<&T> {
Some(&self.end)
}
}

View File

@ -1,7 +1,7 @@
use std::os::raw::c_void;
use std::ptr;
use crate::internal::{DataTypeKind, InclusiveRangeBounds};
use crate::internal::DataTypeKind;
use crate::string::ImStr;
use crate::sys;
use crate::widget::slider::SliderFlags;
@ -34,9 +34,9 @@ impl<'a, T: DataTypeKind> Drag<'a, T> {
}
/// Sets the range (inclusive)
#[inline]
pub fn range<R: InclusiveRangeBounds<T>>(mut self, range: R) -> Self {
self.min = range.start_bound().copied();
self.max = range.end_bound().copied();
pub fn range(mut self, min: T, max: T) -> Self {
self.min = Some(min);
self.max = Some(max);
self
}
/// Sets the value increment for a movement of one pixel.
@ -140,9 +140,9 @@ impl<'a, T: DataTypeKind> DragRange<'a, T> {
}
}
#[inline]
pub fn range<R: InclusiveRangeBounds<T>>(mut self, range: R) -> Self {
self.min = range.start_bound().copied();
self.max = range.end_bound().copied();
pub fn range(mut self, min: T, max: T) -> Self {
self.min = Some(min);
self.max = Some(max);
self
}
/// Sets the value increment for a movement of one pixel.

View File

@ -2,7 +2,7 @@ use bitflags::bitflags;
use std::os::raw::c_void;
use std::ptr;
use crate::internal::{DataTypeKind, InclusiveRangeBounds};
use crate::internal::DataTypeKind;
use crate::string::ImStr;
use crate::sys;
use crate::Ui;
@ -38,42 +38,32 @@ pub struct Slider<'a, T: DataTypeKind> {
impl<'a, T: DataTypeKind> Slider<'a, T> {
/// Constructs a new slider builder with the given range.
#[doc(alias = "SliderScalar", alias = "SliderScalarN")]
pub fn new(label: &ImStr) -> Slider<T> {
pub fn new(label: &ImStr, min: T, max: T) -> Slider<T> {
Slider {
label,
min: T::SLIDER_MIN,
max: T::SLIDER_MAX,
min,
max,
display_format: None,
flags: SliderFlags::empty(),
}
}
/// Sets the range (inclusive)
///
/// The argument uses the standard Rust [`std::ops::Range`] syntax.
///
/// For example, to set both the min and max values:
/// Sets the range inclusively, such that both values given
/// are valid values which the slider can be dragged to.
///
/// ```rust
/// # use imgui::im_str;
/// imgui::Slider::new(im_str!("Example"))
/// .range(1 ..= 10)
/// .range(i8::MIN, i8::MAX)
/// // Remember to call .build(&ui)
/// ;
/// ```
///
/// To set only the max value, using the default minimum value:
///
/// ```rust
/// # use imgui::im_str;
/// imgui::Slider::new(im_str!("Example"))
/// .range(..= 10)
/// // Remember to call .build(&ui)
/// ;
/// ```
/// It is safe, though up to C++ Dear ImGui, on how to handle when
/// `min > max`.
#[inline]
pub fn range<R: InclusiveRangeBounds<T>>(mut self, range: R) -> Self {
self.min = range.start_bound().copied().unwrap_or(T::SLIDER_MIN);
self.max = range.end_bound().copied().unwrap_or(T::SLIDER_MAX);
pub fn range(mut self, min: T, max: T) -> Self {
self.min = min;
self.max = max;
self
}
/// Sets the display format using *a C-style printf string*
@ -142,21 +132,32 @@ pub struct VerticalSlider<'a, T: DataTypeKind + Copy> {
impl<'a, T: DataTypeKind> VerticalSlider<'a, T> {
/// Constructs a new vertical slider builder with the given size and range.
#[doc(alias = "VSliderScalar")]
pub fn new(label: &ImStr, size: [f32; 2]) -> VerticalSlider<T> {
pub fn new(label: &ImStr, size: [f32; 2], min: T, max: T) -> VerticalSlider<T> {
VerticalSlider {
label,
size,
min: T::SLIDER_MIN,
max: T::SLIDER_MAX,
min,
max,
display_format: None,
flags: SliderFlags::empty(),
}
}
/// Sets the range (inclusive)
///
/// ```rust
/// # use imgui::im_str;
/// imgui::VerticalSlider::new(im_str!("Example"))
/// .range(i8::MIN, i8::MAX)
/// // Remember to call .build(&ui)
/// ;
/// ```
///
/// It is safe, though up to C++ Dear ImGui, on how to handle when
/// `min > max`.
#[inline]
pub fn range<R: InclusiveRangeBounds<T>>(mut self, range: R) -> Self {
self.min = range.start_bound().copied().unwrap_or(T::SLIDER_MIN);
self.max = range.end_bound().copied().unwrap_or(T::SLIDER_MAX);
pub fn range(mut self, min: T, max: T) -> Self {
self.min = min;
self.max = max;
self
}
/// Sets the display format using *a C-style printf string*
@ -204,7 +205,8 @@ pub struct AngleSlider<'a> {
}
impl<'a> AngleSlider<'a> {
/// Constructs a new angle slider builder.
/// Constructs a new angle slider builder, where its minimum defaults to -360.0 and
/// maximum defaults to 360.0
#[doc(alias = "SliderAngle")]
pub fn new(label: &ImStr) -> AngleSlider {
AngleSlider {
@ -215,11 +217,21 @@ impl<'a> AngleSlider<'a> {
flags: SliderFlags::empty(),
}
}
/// Sets the range (in degrees, inclusive)
/// Sets the range in degrees (inclusive)
/// ```rust
/// # use imgui::im_str;
/// imgui::AngleSlider::new(im_str!("Example"))
/// .range_degrees(-20.0, 20.0)
/// // Remember to call .build(&ui)
/// ;
/// ```
///
/// It is safe, though up to C++ Dear ImGui, on how to handle when
/// `min > max`.
#[inline]
pub fn range_degrees<R: InclusiveRangeBounds<f32>>(mut self, range: R) -> Self {
self.min_degrees = range.start_bound().copied().unwrap_or(-360.0);
self.max_degrees = range.end_bound().copied().unwrap_or(360.0);
pub fn range_degrees(mut self, min_degrees: f32, max_degrees: f32) -> Self {
self.min_degrees = min_degrees;
self.max_degrees = max_degrees;
self
}
/// Sets the minimum value (in degrees)