#![allow(
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
clippy::as_conversions
)]
use crate::sys;
use crate::{Ui, WindowFlags};
use std::borrow::Cow;
bitflags::bitflags! {
#[repr(transparent)]
pub struct ChildFlags: u32 {
const NONE = 0;
const BORDERS = sys::ImGuiChildFlags_Borders as u32;
const ALWAYS_USE_WINDOW_PADDING = sys::ImGuiChildFlags_AlwaysUseWindowPadding as u32;
const RESIZE_X = sys::ImGuiChildFlags_ResizeX as u32;
const RESIZE_Y = sys::ImGuiChildFlags_ResizeY as u32;
const AUTO_RESIZE_X = sys::ImGuiChildFlags_AutoResizeX as u32;
const AUTO_RESIZE_Y = sys::ImGuiChildFlags_AutoResizeY as u32;
const ALWAYS_AUTO_RESIZE = sys::ImGuiChildFlags_AlwaysAutoResize as u32;
const FRAME_STYLE = sys::ImGuiChildFlags_FrameStyle as u32;
const NAV_FLATTENED = sys::ImGuiChildFlags_NavFlattened as u32;
}
}
pub struct ChildWindow<'ui> {
name: Cow<'ui, str>,
size: [f32; 2],
child_flags: ChildFlags,
flags: WindowFlags,
_phantom: std::marker::PhantomData<&'ui ()>,
}
impl<'ui> ChildWindow<'ui> {
pub fn new(name: impl Into<Cow<'ui, str>>) -> Self {
Self {
name: name.into(),
size: [0.0, 0.0],
child_flags: ChildFlags::NONE,
flags: WindowFlags::empty(),
_phantom: std::marker::PhantomData,
}
}
pub fn size(mut self, size: [f32; 2]) -> Self {
self.size = size;
self
}
pub fn border(mut self, border: bool) -> Self {
self.child_flags.set(ChildFlags::BORDERS, border);
self
}
pub fn child_flags(mut self, child_flags: ChildFlags) -> Self {
self.child_flags = child_flags;
self
}
pub fn flags(mut self, flags: WindowFlags) -> Self {
self.flags = flags;
self
}
pub fn build<F, R>(self, ui: &'ui Ui, f: F) -> Option<R>
where
F: FnOnce() -> R,
{
let token = self.begin(ui)?;
let result = f();
drop(token); Some(result)
}
fn begin(self, ui: &'ui Ui) -> Option<ChildWindowToken<'ui>> {
let name_ptr = ui.scratch_txt(self.name);
let result = unsafe {
let size_vec = sys::ImVec2 {
x: self.size[0],
y: self.size[1],
};
sys::igBeginChild_Str(
name_ptr,
size_vec,
self.child_flags.bits() as i32,
self.flags.bits(),
)
};
if result {
Some(ChildWindowToken {
_phantom: std::marker::PhantomData,
})
} else {
unsafe {
sys::igEndChild();
}
None
}
}
}
pub struct ChildWindowToken<'ui> {
_phantom: std::marker::PhantomData<&'ui ()>,
}
impl<'ui> Drop for ChildWindowToken<'ui> {
fn drop(&mut self) {
unsafe {
sys::igEndChild();
}
}
}
impl Ui {
pub fn child_window<'ui>(&'ui self, name: impl Into<Cow<'ui, str>>) -> ChildWindow<'ui> {
ChildWindow::new(name)
}
}