dear_imgui_rs/window/
child_window.rs1#![allow(
22 clippy::cast_possible_truncation,
23 clippy::cast_sign_loss,
24 clippy::as_conversions
25)]
26use crate::sys;
27use crate::{Ui, WindowFlags};
28use std::ffi::CString;
29
30bitflags::bitflags! {
31 #[repr(transparent)]
33 pub struct ChildFlags: u32 {
34 const NONE = 0;
36 const BORDERS = sys::ImGuiChildFlags_Borders as u32;
38 const ALWAYS_USE_WINDOW_PADDING = sys::ImGuiChildFlags_AlwaysUseWindowPadding as u32;
40 const RESIZE_X = sys::ImGuiChildFlags_ResizeX as u32;
42 const RESIZE_Y = sys::ImGuiChildFlags_ResizeY as u32;
44 const AUTO_RESIZE_X = sys::ImGuiChildFlags_AutoResizeX as u32;
46 const AUTO_RESIZE_Y = sys::ImGuiChildFlags_AutoResizeY as u32;
48 const ALWAYS_AUTO_RESIZE = sys::ImGuiChildFlags_AlwaysAutoResize as u32;
50 const FRAME_STYLE = sys::ImGuiChildFlags_FrameStyle as u32;
52 const NAV_FLATTENED = sys::ImGuiChildFlags_NavFlattened as u32;
54 }
55}
56
57pub struct ChildWindow<'ui> {
59 name: String,
60 size: [f32; 2],
61 child_flags: ChildFlags,
62 flags: WindowFlags,
63 _phantom: std::marker::PhantomData<&'ui ()>,
64}
65
66impl<'ui> ChildWindow<'ui> {
67 pub fn new(name: impl Into<String>) -> Self {
69 Self {
70 name: name.into(),
71 size: [0.0, 0.0],
72 child_flags: ChildFlags::NONE,
73 flags: WindowFlags::empty(),
74 _phantom: std::marker::PhantomData,
75 }
76 }
77
78 pub fn size(mut self, size: [f32; 2]) -> Self {
80 self.size = size;
81 self
82 }
83
84 pub fn border(mut self, border: bool) -> Self {
86 self.child_flags.set(ChildFlags::BORDERS, border);
87 self
88 }
89
90 pub fn child_flags(mut self, child_flags: ChildFlags) -> Self {
92 self.child_flags = child_flags;
93 self
94 }
95
96 pub fn flags(mut self, flags: WindowFlags) -> Self {
98 self.flags = flags;
99 self
100 }
101
102 pub fn build<F, R>(self, ui: &'ui Ui, f: F) -> Option<R>
104 where
105 F: FnOnce() -> R,
106 {
107 let token = self.begin(ui)?;
108 let result = f();
109 drop(token); Some(result)
111 }
112
113 fn begin(self, _ui: &'ui Ui) -> Option<ChildWindowToken<'ui>> {
115 let name_cstr = CString::new(self.name).ok()?;
116
117 let result = unsafe {
118 let size_vec = sys::ImVec2 {
119 x: self.size[0],
120 y: self.size[1],
121 };
122 sys::igBeginChild_Str(
123 name_cstr.as_ptr(),
124 size_vec,
125 self.child_flags.bits() as i32,
126 self.flags.bits(),
127 )
128 };
129
130 if result {
135 Some(ChildWindowToken {
136 _phantom: std::marker::PhantomData,
137 })
138 } else {
139 unsafe {
141 sys::igEndChild();
142 }
143 None
144 }
145 }
146}
147
148pub struct ChildWindowToken<'ui> {
150 _phantom: std::marker::PhantomData<&'ui ()>,
151}
152
153impl<'ui> Drop for ChildWindowToken<'ui> {
154 fn drop(&mut self) {
155 unsafe {
156 sys::igEndChild();
157 }
158 }
159}
160
161impl Ui {
162 pub fn child_window(&self, name: impl Into<String>) -> ChildWindow<'_> {
164 ChildWindow::new(name)
165 }
166}