dear_imgui_rs/window/
mod.rs1#![allow(
41 clippy::cast_possible_truncation,
42 clippy::cast_sign_loss,
43 clippy::as_conversions
44)]
45use bitflags::bitflags;
46use std::f32;
47
48use crate::sys;
49use crate::{Condition, Ui};
50
51pub(crate) mod child_window;
52pub(crate) mod content_region;
53pub(crate) mod scroll;
54
55bitflags! {
59 #[repr(transparent)]
61 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
62 pub struct WindowFlags: i32 {
63 const NO_TITLE_BAR = sys::ImGuiWindowFlags_NoTitleBar as i32;
65 const NO_RESIZE = sys::ImGuiWindowFlags_NoResize as i32;
67 const NO_MOVE = sys::ImGuiWindowFlags_NoMove as i32;
69 const NO_SCROLLBAR = sys::ImGuiWindowFlags_NoScrollbar as i32;
71 const NO_SCROLL_WITH_MOUSE = sys::ImGuiWindowFlags_NoScrollWithMouse as i32;
73 const NO_COLLAPSE = sys::ImGuiWindowFlags_NoCollapse as i32;
75 const ALWAYS_AUTO_RESIZE = sys::ImGuiWindowFlags_AlwaysAutoResize as i32;
77 const NO_BACKGROUND = sys::ImGuiWindowFlags_NoBackground as i32;
79 const NO_SAVED_SETTINGS = sys::ImGuiWindowFlags_NoSavedSettings as i32;
81 const NO_MOUSE_INPUTS = sys::ImGuiWindowFlags_NoMouseInputs as i32;
83 const MENU_BAR = sys::ImGuiWindowFlags_MenuBar as i32;
85 const HORIZONTAL_SCROLLBAR = sys::ImGuiWindowFlags_HorizontalScrollbar as i32;
87 const NO_FOCUS_ON_APPEARING = sys::ImGuiWindowFlags_NoFocusOnAppearing as i32;
89 const NO_BRING_TO_FRONT_ON_FOCUS = sys::ImGuiWindowFlags_NoBringToFrontOnFocus as i32;
91 const ALWAYS_VERTICAL_SCROLLBAR = sys::ImGuiWindowFlags_AlwaysVerticalScrollbar as i32;
93 const ALWAYS_HORIZONTAL_SCROLLBAR = sys::ImGuiWindowFlags_AlwaysHorizontalScrollbar as i32;
95 const NO_NAV_INPUTS = sys::ImGuiWindowFlags_NoNavInputs as i32;
97 const NO_NAV_FOCUS = sys::ImGuiWindowFlags_NoNavFocus as i32;
99 const UNSAVED_DOCUMENT = sys::ImGuiWindowFlags_UnsavedDocument as i32;
101 const NO_DOCKING = sys::ImGuiWindowFlags_NoDocking as i32;
104 const DOCK_NODE_HOST = sys::ImGuiWindowFlags_DockNodeHost as i32;
106 const NO_NAV = Self::NO_NAV_INPUTS.bits() | Self::NO_NAV_FOCUS.bits();
108 const NO_DECORATION = Self::NO_TITLE_BAR.bits() | Self::NO_RESIZE.bits() | Self::NO_SCROLLBAR.bits() | Self::NO_COLLAPSE.bits();
110 const NO_INPUTS = Self::NO_MOUSE_INPUTS.bits() | Self::NO_NAV_INPUTS.bits();
112 }
113}
114
115pub struct Window<'ui> {
117 ui: &'ui Ui,
118 name: String,
119 flags: WindowFlags,
120 size: Option<[f32; 2]>,
121 size_condition: Condition,
122 pos: Option<[f32; 2]>,
123 pos_condition: Condition,
124 content_size: Option<[f32; 2]>,
125 content_size_condition: Condition,
126 collapsed: Option<bool>,
127 collapsed_condition: Condition,
128 focused: Option<bool>,
129 bg_alpha: Option<f32>,
130}
131
132impl<'ui> Window<'ui> {
133 pub fn new(ui: &'ui Ui, name: impl Into<String>) -> Self {
135 Self {
136 ui,
137 name: name.into(),
138 flags: WindowFlags::empty(),
139 size: None,
140 size_condition: Condition::Always,
141 pos: None,
142 pos_condition: Condition::Always,
143 content_size: None,
144 content_size_condition: Condition::Always,
145 collapsed: None,
146 collapsed_condition: Condition::Always,
147 focused: None,
148 bg_alpha: None,
149 }
150 }
151
152 pub fn flags(mut self, flags: WindowFlags) -> Self {
154 self.flags = flags;
155 self
156 }
157
158 pub fn size(mut self, size: [f32; 2], condition: Condition) -> Self {
160 self.size = Some(size);
161 self.size_condition = condition;
162 self
163 }
164
165 pub fn position(mut self, pos: [f32; 2], condition: Condition) -> Self {
167 self.pos = Some(pos);
168 self.pos_condition = condition;
169 self
170 }
171
172 pub fn content_size(mut self, size: [f32; 2], condition: Condition) -> Self {
174 self.content_size = Some(size);
175 self.content_size_condition = condition;
176 self
177 }
178
179 pub fn collapsed(mut self, collapsed: bool, condition: Condition) -> Self {
181 self.collapsed = Some(collapsed);
182 self.collapsed_condition = condition;
183 self
184 }
185
186 pub fn focused(mut self, focused: bool) -> Self {
188 self.focused = Some(focused);
189 self
190 }
191
192 pub fn bg_alpha(mut self, alpha: f32) -> Self {
194 self.bg_alpha = Some(alpha);
195 self
196 }
197
198 pub fn build<F, R>(self, f: F) -> Option<R>
200 where
201 F: FnOnce() -> R,
202 {
203 let _token = self.begin()?;
204 Some(f())
205 }
206
207 fn begin(self) -> Option<WindowToken<'ui>> {
209 use std::ffi::CString;
210
211 let name_cstr = CString::new(self.name).ok()?;
212
213 if let Some(size) = self.size {
215 unsafe {
216 let size_vec = crate::sys::ImVec2 {
217 x: size[0],
218 y: size[1],
219 };
220 crate::sys::igSetNextWindowSize(size_vec, self.size_condition as i32);
221 }
222 }
223
224 if let Some(pos) = self.pos {
225 unsafe {
226 let pos_vec = crate::sys::ImVec2 {
227 x: pos[0],
228 y: pos[1],
229 };
230 let pivot_vec = crate::sys::ImVec2 { x: 0.0, y: 0.0 };
231 crate::sys::igSetNextWindowPos(pos_vec, self.pos_condition as i32, pivot_vec);
232 }
233 }
234
235 if let Some(content_size) = self.content_size {
236 unsafe {
237 let content_size_vec = crate::sys::ImVec2 {
238 x: content_size[0],
239 y: content_size[1],
240 };
241 crate::sys::igSetNextWindowContentSize(content_size_vec);
242 }
243 }
244
245 if let Some(collapsed) = self.collapsed {
246 unsafe {
247 crate::sys::igSetNextWindowCollapsed(collapsed, self.collapsed_condition as i32);
248 }
249 }
250
251 if let Some(focused) = self.focused
252 && focused
253 {
254 unsafe {
255 crate::sys::igSetNextWindowFocus();
256 }
257 }
258
259 if let Some(alpha) = self.bg_alpha {
260 unsafe {
261 crate::sys::igSetNextWindowBgAlpha(alpha);
262 }
263 }
264
265 let mut open = true;
267 let result =
268 unsafe { crate::sys::igBegin(name_cstr.as_ptr(), &mut open, self.flags.bits()) };
269
270 if result && open {
273 Some(WindowToken {
274 _phantom: std::marker::PhantomData,
275 })
276 } else {
277 unsafe {
279 crate::sys::igEnd();
280 }
281 None
282 }
283 }
284}
285
286pub struct WindowToken<'ui> {
288 _phantom: std::marker::PhantomData<&'ui ()>,
289}
290
291impl<'ui> Drop for WindowToken<'ui> {
292 fn drop(&mut self) {
293 unsafe {
294 crate::sys::igEnd();
295 }
296 }
297}