mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-13 22:48:34 +00:00
Create windows via ui.window("title").build() [#454]
This commit is contained in:
parent
8fddba0143
commit
0f7cb49865
@ -314,6 +314,53 @@ impl<'a> Default for Id<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ui> Ui<'ui> {
|
||||
/// # Windows
|
||||
/// Start constructing a window.
|
||||
///
|
||||
/// This, like many objects in the library, uses the builder
|
||||
/// pattern to set optional arguments (like window size, flags,
|
||||
/// etc). Once all desired options are set, you must call either
|
||||
/// [`Window::build`] or [`Window::begin`] must be called to
|
||||
/// actually create the window.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a window using the closure based [`Window::build`]:
|
||||
/// ```no_run
|
||||
/// # let mut ctx = imgui::Context::create();
|
||||
/// # let ui = ctx.frame();
|
||||
/// ui.window("Example Window")
|
||||
/// .size([100.0, 50.0], imgui::Condition::FirstUseEver)
|
||||
/// .build(|| {
|
||||
/// ui.text("An example");
|
||||
/// });
|
||||
/// ```
|
||||
pub fn window<Label: AsRef<str>>(&'ui self, name: Label) -> Window<'ui, '_, Label> {
|
||||
Window::new(self, name)
|
||||
}
|
||||
|
||||
/// Same as [`Ui::window`] but using the "token based" `.begin()` approach.
|
||||
///
|
||||
/// ```
|
||||
/// fn example(ui: &imgui::Ui) {
|
||||
/// let wt = ui.window("Example Window")
|
||||
/// .size([100.0, 50.0], imgui::Condition::FirstUseEver)
|
||||
/// .begin();
|
||||
/// if wt.is_some() {
|
||||
/// ui.text("Window is visible");
|
||||
/// }
|
||||
/// // Window ends where where wt is dropped,
|
||||
/// // or you could call
|
||||
/// wt.unwrap().end()
|
||||
/// }
|
||||
/// ```
|
||||
pub fn child_window<Label: AsRef<str>>(&'ui self, name: Label) -> ChildWindow<'ui, Label> {
|
||||
ChildWindow::new(self, name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Widgets: Input
|
||||
impl<'ui> Ui<'ui> {
|
||||
#[doc(alias = "InputText", alias = "InputTextWithHint")]
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
use std::f32;
|
||||
use std::os::raw::{c_char, c_void};
|
||||
|
||||
use crate::sys;
|
||||
use crate::window::WindowFlags;
|
||||
use crate::{Id, Ui};
|
||||
use crate::Ui;
|
||||
|
||||
/// Builder for a child window
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[must_use]
|
||||
pub struct ChildWindow<'a> {
|
||||
id: Id<'a>,
|
||||
pub struct ChildWindow<'ui, Label> {
|
||||
ui: &'ui Ui<'ui>,
|
||||
name: Label,
|
||||
flags: WindowFlags,
|
||||
size: [f32; 2],
|
||||
content_size: [f32; 2],
|
||||
@ -18,12 +18,13 @@ pub struct ChildWindow<'a> {
|
||||
border: bool,
|
||||
}
|
||||
|
||||
impl<'a> ChildWindow<'a> {
|
||||
impl<'ui, Label: AsRef<str>> ChildWindow<'ui, Label> {
|
||||
/// Creates a new child window builder with the given ID
|
||||
#[doc(alias = "BeginChildID")]
|
||||
pub fn new<T: Into<Id<'a>>>(id: T) -> ChildWindow<'a> {
|
||||
pub fn new(ui: &'ui Ui<'ui>, name: Label) -> ChildWindow<'ui, Label> {
|
||||
ChildWindow {
|
||||
id: id.into(),
|
||||
ui,
|
||||
name,
|
||||
flags: WindowFlags::empty(),
|
||||
size: [0.0, 0.0],
|
||||
content_size: [0.0, 0.0],
|
||||
@ -245,7 +246,7 @@ impl<'a> ChildWindow<'a> {
|
||||
/// rendered, the token must be ended by calling `.end()`.
|
||||
///
|
||||
/// Returns `None` if the window is not visible and no content should be rendered.
|
||||
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<ChildWindowToken<'ui>> {
|
||||
pub fn begin(self) -> Option<ChildWindowToken<'ui>> {
|
||||
if self.content_size[0] != 0.0 || self.content_size[1] != 0.0 {
|
||||
unsafe { sys::igSetNextWindowContentSize(self.content_size.into()) };
|
||||
}
|
||||
@ -255,22 +256,16 @@ impl<'a> ChildWindow<'a> {
|
||||
if self.bg_alpha.is_finite() {
|
||||
unsafe { sys::igSetNextWindowBgAlpha(self.bg_alpha) };
|
||||
}
|
||||
let id = unsafe {
|
||||
match self.id {
|
||||
Id::Int(i) => sys::igGetID_Ptr(i as *const c_void),
|
||||
Id::Ptr(p) => sys::igGetID_Ptr(p),
|
||||
Id::Str(s) => {
|
||||
let start = s.as_ptr() as *const c_char;
|
||||
let end = start.add(s.len());
|
||||
sys::igGetID_StrStr(start, end)
|
||||
}
|
||||
}
|
||||
};
|
||||
let should_render = unsafe {
|
||||
sys::igBeginChild_ID(id, self.size.into(), self.border, self.flags.bits() as i32)
|
||||
sys::igBeginChild_Str(
|
||||
self.ui.scratch_txt(self.name),
|
||||
self.size.into(),
|
||||
self.border,
|
||||
self.flags.bits() as i32,
|
||||
)
|
||||
};
|
||||
if should_render {
|
||||
Some(ChildWindowToken::new(ui))
|
||||
Some(ChildWindowToken::new(self.ui))
|
||||
} else {
|
||||
unsafe { sys::igEndChild() };
|
||||
None
|
||||
@ -281,8 +276,8 @@ impl<'a> ChildWindow<'a> {
|
||||
///
|
||||
/// Note: the closure is not called if no window content is visible (e.g. window is collapsed
|
||||
/// or fully clipped).
|
||||
pub fn build<T, F: FnOnce() -> T>(self, ui: &Ui<'_>, f: F) -> Option<T> {
|
||||
self.begin(ui).map(|_window| f())
|
||||
pub fn build<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
|
||||
self.begin().map(|_window| f())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -160,8 +160,9 @@ impl<'ui> Ui<'ui> {
|
||||
/// Builder for a window
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
pub struct Window<'a, T> {
|
||||
name: T,
|
||||
pub struct Window<'ui, 'a, Label> {
|
||||
ui: &'ui Ui<'ui>,
|
||||
name: Label,
|
||||
opened: Option<&'a mut bool>,
|
||||
flags: WindowFlags,
|
||||
pos: [f32; 2],
|
||||
@ -177,10 +178,11 @@ pub struct Window<'a, T> {
|
||||
bg_alpha: f32,
|
||||
}
|
||||
|
||||
impl<'a, T: AsRef<str>> Window<'a, T> {
|
||||
/// Creates a new window builder with the given name
|
||||
pub fn new(name: T) -> Self {
|
||||
impl<'ui, 'a, Label: AsRef<str>> Window<'ui, 'a, Label> {
|
||||
/// Typically created via [`Ui::window`]
|
||||
pub fn new(ui: &'ui Ui<'ui>, name: Label) -> Self {
|
||||
Window {
|
||||
ui,
|
||||
name,
|
||||
opened: None,
|
||||
flags: WindowFlags::empty(),
|
||||
@ -487,7 +489,7 @@ impl<'a, T: AsRef<str>> Window<'a, T> {
|
||||
///
|
||||
/// Returns `None` if the window is not visible and no content should be rendered.
|
||||
#[must_use]
|
||||
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<WindowToken<'ui>> {
|
||||
pub fn begin(self) -> Option<WindowToken<'ui>> {
|
||||
if self.pos_cond != Condition::Never {
|
||||
unsafe {
|
||||
sys::igSetNextWindowPos(
|
||||
@ -525,7 +527,7 @@ impl<'a, T: AsRef<str>> Window<'a, T> {
|
||||
}
|
||||
let should_render = unsafe {
|
||||
sys::igBegin(
|
||||
ui.scratch_txt(self.name),
|
||||
self.ui.scratch_txt(self.name),
|
||||
self.opened
|
||||
.map(|x| x as *mut bool)
|
||||
.unwrap_or(ptr::null_mut()),
|
||||
@ -533,7 +535,7 @@ impl<'a, T: AsRef<str>> Window<'a, T> {
|
||||
)
|
||||
};
|
||||
if should_render {
|
||||
Some(WindowToken::new(ui))
|
||||
Some(WindowToken::new(self.ui))
|
||||
} else {
|
||||
unsafe { sys::igEnd() };
|
||||
None
|
||||
@ -542,10 +544,10 @@ impl<'a, T: AsRef<str>> Window<'a, T> {
|
||||
/// Creates a window 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 window content is visible (e.g. window is collapsed
|
||||
/// or fully clipped).
|
||||
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
|
||||
self.begin(ui).map(|_window| f())
|
||||
/// Note: the closure is only called if the window content is
|
||||
/// visible (e.g. will not run if window is collapsed).
|
||||
pub fn build<R, F: FnOnce() -> R>(self, f: F) -> Option<R> {
|
||||
self.begin().map(|_window| f())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user