diff --git a/examples/test_window.rs b/examples/test_window.rs index 2c551de..f83896f 100644 --- a/examples/test_window.rs +++ b/examples/test_window.rs @@ -30,6 +30,7 @@ struct State { no_collapse: bool, no_menu: bool, bg_alpha: f32, + auto_resize_state: AutoResizeState, file_menu: FileMenuState } @@ -55,6 +56,7 @@ impl Default for State { no_collapse: false, no_menu: false, bg_alpha: 0.65, + auto_resize_state: Default::default(), file_menu: Default::default() } } @@ -72,6 +74,18 @@ impl Default for FileMenuState { } } +struct AutoResizeState { + lines: usize +} + +impl Default for AutoResizeState { + fn default() -> Self { + AutoResizeState { + lines: 10 + } + } +} + fn main() { let mut state = State { .. Default::default() @@ -110,6 +124,9 @@ fn show_test_window<'a>(frame: &Frame<'a>, state: &mut State) -> bool { state.show_app_metrics = frame.show_metrics_window(); } if state.show_app_main_menu_bar { show_example_app_main_menu_bar(frame, state) } + if state.show_app_auto_resize { + state.show_app_auto_resize = show_example_app_auto_resize(frame, &mut state.auto_resize_state); + } if state.show_app_fixed_overlay { state.show_app_fixed_overlay = show_example_app_fixed_overlay(frame); } @@ -243,6 +260,25 @@ fn show_example_menu_file<'a>(frame: &Frame<'a>, state: &mut FileMenuState) { if frame.menu_item(im_str!("Quit")).shortcut(im_str!("Alt+F4")).build() { } } +fn show_example_app_auto_resize<'a>(frame: &Frame<'a>, state: &mut AutoResizeState) -> bool { + frame.window() + .name(im_str!("Example: Auto-resizing window")) + .closable(true) + .always_auto_resize(true) + .build(|| { + frame.text(im_str!("Window will resize every-frame to the size of its content. +Note that you probably don't want to query the window size to +output your content because that would create a feedback loop.")); + if let Some(lines) = frame.slider_i32(im_str!("Number of lines"), + state.lines as i32, 1, 20).build() { + state.lines = lines as usize; + } + for i in 0 .. state.lines { + frame.text(im_str!("{:2$}This is line {}", "", i, i * 4)); + } + }) +} + fn show_example_app_fixed_overlay<'a>(frame: &Frame<'a>) -> bool { frame.window() .name(im_str!("Example: Fixed Overlay")) diff --git a/src/lib.rs b/src/lib.rs index 5f020f9..4ced5d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,11 +31,13 @@ pub use ffi::{ ImVec2, ImVec4 }; pub use menus::{Menu, MenuItem}; +pub use sliders::{SliderInt}; pub use widgets::{CollapsingHeader}; pub use window::{Window}; pub mod ffi; mod menus; +mod sliders; mod widgets; mod window; @@ -276,6 +278,14 @@ impl<'fr> Frame<'fr> { } } +// Widgets: Sliders +impl<'fr> Frame<'fr> { + pub fn slider_i32<'p>(&self, label: ImStr<'p>, + value: i32, min: i32, max: i32) -> SliderInt<'fr, 'p> { + SliderInt::new(label, value, min, max) + } +} + // Widgets: Menus impl<'fr> Frame<'fr> { pub fn main_menu_bar(&self, f: F) where F: FnOnce() { diff --git a/src/sliders.rs b/src/sliders.rs new file mode 100644 index 0000000..396229c --- /dev/null +++ b/src/sliders.rs @@ -0,0 +1,48 @@ +use libc::c_int; +use std::marker::PhantomData; + +use super::ffi; +use super::{Frame, ImStr}; + +// TODO: Consider using Range, even though it is half-open + +pub struct SliderInt<'fr, 'p> { + label: ImStr<'p>, + value: i32, + min: i32, + max: i32, + display_format: ImStr<'p>, + _phantom: PhantomData<&'fr Frame<'fr>> +} + +impl<'fr, 'p> SliderInt<'fr, 'p> { + pub fn new(label: ImStr<'p>, value: i32, min: i32, max: i32) -> Self { + SliderInt { + label: label, + value: value, + min: min, + max: max, + display_format: unsafe { ImStr::from_bytes(b"%.0f") }, + _phantom: PhantomData + } + } + #[inline] + pub fn display_format(self, display_format: ImStr<'p>) -> Self { + SliderInt { + display_format: display_format, + .. self + } + } + pub fn build(self) -> Option { + let mut value = self.value as c_int; + let changed = unsafe { + ffi::igSliderInt(self.label.as_ptr(), + &mut value, + self.min as c_int, + self.max as c_int, + self.display_format.as_ptr() + ) + }; + if changed { Some(value as i32) } else { None } + } +}