updating more widgets. Wow this is boring!

This commit is contained in:
Jack Spira 2021-09-08 09:05:30 -07:00 committed by Jack Mac
parent d490093dae
commit 5143968429
9 changed files with 181 additions and 127 deletions

View File

@ -19,9 +19,7 @@ fn main() {
ui.separator();
ui.text("This progress bar uses overlay text:");
ProgressBar::new(0.8)
.overlay_text(im_str!("Lorem ipsum"))
.build(ui);
ProgressBar::new_with_overlay(0.8, "Lorem ipsum").build(ui);
});
});
}

View File

@ -56,7 +56,7 @@ fn example_1(ui: &Ui, state: &mut State) {
ui.separator();
ui.text("Value formatting can be customized with a C-style printf string:");
Slider::new(im_str!("f64 value with custom formatting"), -999_999_999.0, 999_999_999.0)
.display_format(im_str!("%09.0f"))
.display_format("%09.0f")
.build(ui, &mut state.f64_formatted);
ui.separator();

View File

@ -449,7 +449,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
ui.spacing();
Slider::new(im_str!("Wrap width"), -20.0, 600.0)
.display_format(im_str!("%.0f"))
.display_format("%.0f")
.build(ui, &mut state.wrap_width);
ui.text(im_str!("Test paragraph 1:"));

View File

@ -137,6 +137,14 @@ impl<'ui> Ui<'ui> {
}
}
/// Internal method to push an option text to our scratch buffer.
fn scratch_txt_opt(&self, txt: Option<impl AsRef<str>>) -> *const sys::cty::c_char {
match txt {
Some(v) => self.scratch_txt(v),
None => std::ptr::null(),
}
}
fn scratch_txt_two(
&self,
txt_0: impl AsRef<str>,

View File

@ -1,7 +1,5 @@
use std::ptr;
use crate::string::ImStr;
use crate::sys;
// use crate::ImStr;
use crate::Ui;
/// Builder for a progress bar widget.
@ -19,13 +17,13 @@ use crate::Ui;
/// ```
#[derive(Copy, Clone, Debug)]
#[must_use]
pub struct ProgressBar<'a> {
pub struct ProgressBar<T> {
fraction: f32,
size: [f32; 2],
overlay_text: Option<&'a ImStr>,
overlay_text: Option<T>,
}
impl<'a> ProgressBar<'a> {
impl ProgressBar<&'static str> {
/// Creates a progress bar with a given fraction showing
/// the progress (0.0 = 0%, 1.0 = 100%).
///
@ -33,19 +31,29 @@ impl<'a> ProgressBar<'a> {
/// custom size is specified.
#[inline]
#[doc(alias = "ProgressBar")]
pub const fn new(fraction: f32) -> ProgressBar<'a> {
pub fn new(fraction: f32) -> Self {
ProgressBar {
fraction,
size: [-1.0, 0.0],
overlay_text: None,
}
}
}
/// Sets an optional text that will be drawn over the progress bar.
impl<T: AsRef<str>> ProgressBar<T> {
/// Creates a progress bar with a given fraction showing
/// the progress (0.0 = 0%, 1.0 = 100%).
///
/// The progress bar will be automatically sized to fill the entire width of the window if no
/// custom size is specified.
#[inline]
pub const fn overlay_text(mut self, overlay_text: &'a ImStr) -> ProgressBar {
self.overlay_text = Some(overlay_text);
self
#[doc(alias = "ProgressBar")]
pub fn new_with_overlay(fraction: f32, overlay_text: T) -> Self {
ProgressBar {
fraction,
size: [-1.0, 0.0],
overlay_text: Some(overlay_text),
}
}
/// Sets the size of the progress bar.
@ -53,18 +61,18 @@ impl<'a> ProgressBar<'a> {
/// Negative values will automatically align to the end of the axis, zero will let the progress
/// bar choose a size, and positive values will use the given size.
#[inline]
pub const fn size(mut self, size: [f32; 2]) -> Self {
pub fn size(mut self, size: [f32; 2]) -> Self {
self.size = size;
self
}
/// Builds the progress bar
pub fn build(self, _: &Ui) {
pub fn build(self, ui: &Ui) {
unsafe {
sys::igProgressBar(
self.fraction,
self.size.into(),
self.overlay_text.map(|x| x.as_ptr()).unwrap_or(ptr::null()),
ui.scratch_txt_opt(self.overlay_text),
);
}
}

View File

@ -23,20 +23,20 @@ bitflags!(
/// Builder for a selectable widget.
#[derive(Copy, Clone, Debug)]
#[must_use]
pub struct Selectable<'a> {
label: &'a str,
pub struct Selectable<T> {
label: T,
selected: bool,
flags: SelectableFlags,
size: [f32; 2],
}
impl<'a> Selectable<'a> {
impl<T: AsRef<str>> Selectable<T> {
/// Constructs a new selectable builder.
#[inline]
#[doc(alias = "Selectable")]
pub fn new(label: &'a impl AsRef<str>) -> Selectable<'a> {
pub fn new(label: T) -> Self {
Selectable {
label: label.as_ref(),
label,
selected: false,
flags: SelectableFlags::empty(),
size: [0.0, 0.0],
@ -117,10 +117,7 @@ impl<'a> Selectable<'a> {
)
}
}
}
/// # Convenience functions
impl<'a> Selectable<'a> {
/// Builds the selectable using a mutable reference to selected state.
pub fn build_with_ref(self, ui: &Ui, selected: &mut bool) -> bool {
if self.selected(*selected).build(ui) {

View File

@ -1,9 +1,7 @@
use bitflags::bitflags;
use std::os::raw::c_void;
use std::ptr;
use crate::internal::DataTypeKind;
use crate::string::ImStr;
use crate::sys;
use crate::Ui;
@ -27,18 +25,18 @@ bitflags!(
/// Builder for a slider widget.
#[derive(Copy, Clone, Debug)]
#[must_use]
pub struct Slider<'a, T: DataTypeKind> {
label: &'a ImStr,
min: T,
max: T,
display_format: Option<&'a ImStr>,
pub struct Slider<'a, T, K: DataTypeKind> {
label: T,
min: K,
max: K,
display_format: Option<&'a str>,
flags: SliderFlags,
}
impl<'a, T: DataTypeKind> Slider<'a, T> {
impl<'a, T: AsRef<str>, K: DataTypeKind> Slider<'a, T, K> {
/// Constructs a new slider builder with the given range.
#[doc(alias = "SliderScalar", alias = "SliderScalarN")]
pub fn new(label: &ImStr, min: T, max: T) -> Slider<T> {
pub fn new(label: T, min: K, max: K) -> Self {
Slider {
label,
min,
@ -61,14 +59,14 @@ impl<'a, T: DataTypeKind> Slider<'a, T> {
/// It is safe, though up to C++ Dear ImGui, on how to handle when
/// `min > max`.
#[inline]
pub fn range(mut self, min: T, max: T) -> Self {
pub fn range(mut self, min: K, max: K) -> Self {
self.min = min;
self.max = max;
self
}
/// 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
}
@ -81,17 +79,17 @@ impl<'a, T: DataTypeKind> Slider<'a, T> {
/// Builds a 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 K) -> bool {
unsafe {
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
sys::igSliderScalar(
self.label.as_ptr(),
T::KIND as i32,
value as *mut T as *mut c_void,
&self.min as *const T as *const c_void,
&self.max as *const T as *const c_void,
self.display_format
.map(ImStr::as_ptr)
.unwrap_or(ptr::null()),
label,
K::KIND as i32,
value as *mut K as *mut c_void,
&self.min as *const K as *const c_void,
&self.max as *const K as *const c_void,
display_format,
self.flags.bits() as i32,
)
}
@ -99,18 +97,18 @@ impl<'a, T: DataTypeKind> Slider<'a, T> {
/// Builds a horizontal array of multiple 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 [K]) -> bool {
unsafe {
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
sys::igSliderScalarN(
self.label.as_ptr(),
T::KIND as i32,
label,
K::KIND as i32,
values.as_mut_ptr() as *mut c_void,
values.len() as i32,
&self.min as *const T as *const c_void,
&self.max as *const T as *const c_void,
self.display_format
.map(ImStr::as_ptr)
.unwrap_or(ptr::null()),
&self.min as *const K as *const c_void,
&self.max as *const K as *const c_void,
display_format,
self.flags.bits() as i32,
)
}
@ -120,16 +118,16 @@ impl<'a, T: DataTypeKind> Slider<'a, T> {
/// Builder for a vertical slider widget.
#[derive(Clone, Debug)]
#[must_use]
pub struct VerticalSlider<'a, T: DataTypeKind + Copy> {
label: &'a ImStr,
pub struct VerticalSlider<'a, T, K: DataTypeKind> {
label: T,
size: [f32; 2],
min: T,
max: T,
display_format: Option<&'a ImStr>,
min: K,
max: K,
display_format: Option<&'a str>,
flags: SliderFlags,
}
impl<'a, T: DataTypeKind> VerticalSlider<'a, T> {
impl<'a, T: AsRef<str>, K: DataTypeKind> VerticalSlider<'a, T, K> {
/// Constructs a new vertical slider builder with the given size and range.
///
/// ```rust
@ -143,7 +141,7 @@ impl<'a, T: DataTypeKind> VerticalSlider<'a, T> {
/// It is safe, though up to C++ Dear ImGui, on how to handle when
/// `min > max`.
#[doc(alias = "VSliderScalar")]
pub fn new(label: &ImStr, size: [f32; 2], min: T, max: T) -> VerticalSlider<T> {
pub fn new(label: T, size: [f32; 2], min: K, max: K) -> Self {
VerticalSlider {
label,
size,
@ -167,14 +165,14 @@ impl<'a, T: DataTypeKind> VerticalSlider<'a, T> {
/// It is safe, though up to C++ Dear ImGui, on how to handle when
/// `min > max`.
#[inline]
pub fn range(mut self, min: T, max: T) -> Self {
pub fn range(mut self, min: K, max: K) -> Self {
self.min = min;
self.max = max;
self
}
/// 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
}
@ -187,18 +185,18 @@ impl<'a, T: DataTypeKind> VerticalSlider<'a, T> {
/// Builds a vertical 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 K) -> bool {
unsafe {
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
sys::igVSliderScalar(
self.label.as_ptr(),
label,
self.size.into(),
T::KIND as i32,
value as *mut T as *mut c_void,
&self.min as *const T as *const c_void,
&self.max as *const T as *const c_void,
self.display_format
.map(ImStr::as_ptr)
.unwrap_or(ptr::null()),
K::KIND as i32,
value as *mut K as *mut c_void,
&self.min as *const K as *const c_void,
&self.max as *const K as *const c_void,
display_format,
self.flags.bits() as i32,
)
}
@ -208,24 +206,24 @@ impl<'a, T: DataTypeKind> VerticalSlider<'a, T> {
/// Builder for an angle slider widget.
#[derive(Copy, Clone, Debug)]
#[must_use]
pub struct AngleSlider<'a> {
label: &'a ImStr,
pub struct AngleSlider<'a, T> {
label: T,
min_degrees: f32,
max_degrees: f32,
display_format: &'a ImStr,
display_format: &'a str,
flags: SliderFlags,
}
impl<'a> AngleSlider<'a> {
impl<'a, T: AsRef<str>> AngleSlider<'a, T> {
/// 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 {
pub fn new(label: T) -> Self {
AngleSlider {
label,
min_degrees: -360.0,
max_degrees: 360.0,
display_format: im_str!("%.0f deg"),
display_format: "%.0f deg",
flags: SliderFlags::empty(),
}
}
@ -260,7 +258,7 @@ impl<'a> AngleSlider<'a> {
}
/// 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 = display_format;
self
}
@ -273,14 +271,16 @@ impl<'a> AngleSlider<'a> {
/// Builds an angle slider that is bound to the given value (in radians).
///
/// Returns true if the slider value was changed.
pub fn build(self, _: &Ui, value_rad: &mut f32) -> bool {
pub fn build(self, ui: &Ui, value_rad: &mut f32) -> bool {
unsafe {
let (label, display_format) = ui.scratch_txt_two(self.label, self.display_format);
sys::igSliderAngle(
self.label.as_ptr(),
label,
value_rad as *mut _,
self.min_degrees,
self.max_degrees,
self.display_format.as_ptr(),
display_format,
self.flags.bits() as i32,
)
}

View File

@ -1,5 +1,3 @@
//! Safe wrapper around imgui-sys for tab menu.
//!
//! # Examples
//
//! ```no_run
@ -19,7 +17,6 @@
//! ```
//!
//! See `test_window_impl.rs` for a more complicated example.
use crate::string::ImStr;
use crate::sys;
use crate::Ui;
use bitflags::bitflags;
@ -56,15 +53,15 @@ bitflags! {
}
/// Builder for a tab bar.
pub struct TabBar<'a> {
id: &'a ImStr,
pub struct TabBar<T> {
id: T,
flags: TabBarFlags,
}
impl<'a> TabBar<'a> {
impl<T: AsRef<str>> TabBar<T> {
#[inline]
#[doc(alias = "BeginTabBar")]
pub const fn new(id: &'a ImStr) -> Self {
pub fn new(id: T) -> Self {
Self {
id,
flags: TabBarFlags::empty(),
@ -90,23 +87,15 @@ impl<'a> TabBar<'a> {
}
#[must_use]
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<TabBarToken<'ui>> {
let should_render =
unsafe { sys::igBeginTabBar(self.id.as_ptr(), self.flags.bits() as i32) };
if should_render {
Some(TabBarToken::new(ui))
} else {
unsafe { sys::igEndTabBar() };
None
}
pub fn begin<'ui>(self, ui: &'ui Ui<'_>) -> Option<TabBarToken<'ui>> {
ui.tab_bar_with_flags(self.id, self.flags)
}
/// Creates a tab bar and runs a closure to construct the contents.
/// Returns the result of the closure, if it is called.
///
/// Note: the closure is not called if no tabbar content is visible
pub fn build<T, F: FnOnce() -> T>(self, ui: &Ui<'_>, f: F) -> Option<T> {
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
self.begin(ui).map(|_tab| f())
}
}
@ -120,23 +109,23 @@ create_token!(
drop { sys::igEndTabBar() }
);
pub struct TabItem<'a> {
name: &'a ImStr,
pub struct TabItem<'a, T> {
label: T,
opened: Option<&'a mut bool>,
flags: TabItemFlags,
}
impl<'a> TabItem<'a> {
impl<'a, T: AsRef<str>> TabItem<'a, T> {
#[doc(alias = "BeginTabItem")]
pub fn new(name: &'a ImStr) -> Self {
pub fn new(name: T) -> Self {
Self {
name,
label: name,
opened: None,
flags: TabItemFlags::empty(),
}
}
/// Will open or close the tab.\
/// Will open or close the tab.
///
/// True to display the tab. Tab item is visible by default.
#[inline]
@ -155,29 +144,15 @@ impl<'a> TabItem<'a> {
}
#[must_use]
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<TabItemToken<'ui>> {
let should_render = unsafe {
sys::igBeginTabItem(
self.name.as_ptr(),
self.opened
.map(|x| x as *mut bool)
.unwrap_or(ptr::null_mut()),
self.flags.bits() as i32,
)
};
if should_render {
Some(TabItemToken::new(ui))
} else {
None
}
pub fn begin<'ui>(self, ui: &'ui Ui<'_>) -> Option<TabItemToken<'ui>> {
ui.tab_item_with_flags(self.label, self.opened, self.flags)
}
/// Creates a tab item and runs a closure to construct the contents.
/// Returns the result of the closure, if it is called.
///
/// Note: the closure is not called if the tab item is not selected
pub fn build<T, F: FnOnce() -> T>(self, ui: &Ui<'_>, f: F) -> Option<T> {
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
self.begin(ui).map(|_tab| f())
}
}
@ -190,3 +165,71 @@ create_token!(
/// Ends a tab bar item.
drop { sys::igEndTabItem() }
);
impl Ui<'_> {
/// Creates a tab bar and returns a tab bar token, allowing you to append
/// Tab items afterwards. This passes no flags. To pass flags explicitly,
/// use [tab_bar_with_flags].
pub fn tab_bar(&self, id: impl AsRef<str>) -> Option<TabBarToken<'_>> {
self.tab_bar_with_flags(id, TabBarFlags::empty())
}
//
/// Creates a tab bar and returns a tab bar token, allowing you to append
/// Tab items afterwards.
pub fn tab_bar_with_flags(
&self,
id: impl AsRef<str>,
flags: TabBarFlags,
) -> Option<TabBarToken<'_>> {
let should_render =
unsafe { sys::igBeginTabBar(self.scratch_txt(id), flags.bits() as i32) };
if should_render {
Some(TabBarToken::new(self))
} else {
unsafe { sys::igEndTabBar() };
None
}
}
/// Creates a new tab item and returns a token if its contents are visible.
///
/// By default, this doesn't pass an opened bool nor any flags. See [tab_item_with_opened]
/// and `[tab_item_with_flags]` for more.
pub fn tab_item(&self, label: impl AsRef<str>) -> Option<TabItemToken<'_>> {
self.tab_item_with_flags(label, None, TabItemFlags::empty())
}
/// Creates a new tab item and returns a token if its contents are visible.
///
/// By default, this doesn't pass any flags. See `[tab_item_with_flags]` for more.
pub fn tab_item_with_opened(
&self,
label: impl AsRef<str>,
opened: &mut bool,
) -> Option<TabItemToken<'_>> {
self.tab_item_with_flags(label, Some(opened), TabItemFlags::empty())
}
/// Creates a new tab item and returns a token if its contents are visible.
pub fn tab_item_with_flags(
&self,
label: impl AsRef<str>,
opened: Option<&mut bool>,
flags: TabItemFlags,
) -> Option<TabItemToken<'_>> {
let should_render = unsafe {
sys::igBeginTabItem(
self.scratch_txt(label),
opened.map(|x| x as *mut bool).unwrap_or(ptr::null_mut()),
flags.bits() as i32,
)
};
if should_render {
Some(TabItemToken::new(self))
} else {
None
}
}
}

View File

@ -1,6 +1,6 @@
use std::os::raw::c_char;
use crate::string::ImStr;
// use crate::string::ImStr;
use crate::style::StyleColor;
use crate::Ui;
@ -49,7 +49,7 @@ impl<'ui> Ui<'ui> {
}
/// Renders text with a little bullet aligned to the typical tree node
#[doc(alias = "BulletText")]
pub fn bullet_text(&self, text: &ImStr) {
unsafe { sys::igBulletText(fmt_ptr(), text.as_ptr()) }
pub fn bullet_text(&self, text: impl AsRef<str>) {
unsafe { sys::igBulletText(fmt_ptr(), self.scratch_txt(text)) }
}
}