1use bitflags::bitflags;
2use std::f32;
3use std::ptr;
4
5use crate::sys;
6use crate::{Condition, Ui};
7
8pub(crate) mod child_window;
9pub(crate) mod content_region;
10pub(crate) mod scroll;
11
12bitflags! {
13 #[repr(transparent)]
15 pub struct WindowHoveredFlags: u32 {
16 const CHILD_WINDOWS = sys::ImGuiHoveredFlags_ChildWindows;
18 const ROOT_WINDOW = sys::ImGuiHoveredFlags_RootWindow;
20 const ANY_WINDOW = sys::ImGuiHoveredFlags_AnyWindow;
22 const ALLOW_WHEN_BLOCKED_BY_POPUP = sys::ImGuiHoveredFlags_AllowWhenBlockedByPopup;
24 const ALLOW_WHEN_BLOCKED_BY_ACTIVE_ITEM = sys::ImGuiHoveredFlags_AllowWhenBlockedByActiveItem;
26 const ROOT_AND_CHILD_WINDOWS = Self::ROOT_WINDOW.bits | Self::CHILD_WINDOWS.bits;
28 }
29}
30
31bitflags! {
32 #[repr(transparent)]
34 pub struct WindowFocusedFlags: u32 {
35 const CHILD_WINDOWS = sys::ImGuiFocusedFlags_ChildWindows;
37 const ROOT_WINDOW = sys::ImGuiFocusedFlags_RootWindow;
39 const ANY_WINDOW = sys::ImGuiFocusedFlags_AnyWindow;
41 const ROOT_AND_CHILD_WINDOWS = Self::ROOT_WINDOW.bits | Self::CHILD_WINDOWS.bits;
43 }
44}
45
46bitflags! {
47 #[repr(transparent)]
49 pub struct WindowFlags: u32 {
50 const NO_TITLE_BAR = sys::ImGuiWindowFlags_NoTitleBar;
52 const NO_RESIZE = sys::ImGuiWindowFlags_NoResize;
54 const NO_MOVE = sys::ImGuiWindowFlags_NoMove;
56 const NO_SCROLLBAR = sys::ImGuiWindowFlags_NoScrollbar;
58 const NO_SCROLL_WITH_MOUSE = sys::ImGuiWindowFlags_NoScrollWithMouse;
63 const NO_COLLAPSE = sys::ImGuiWindowFlags_NoCollapse;
65 const ALWAYS_AUTO_RESIZE = sys::ImGuiWindowFlags_AlwaysAutoResize;
67 const NO_BACKGROUND = sys::ImGuiWindowFlags_NoBackground;
69 const NO_SAVED_SETTINGS = sys::ImGuiWindowFlags_NoSavedSettings;
71 const NO_MOUSE_INPUTS = sys::ImGuiWindowFlags_NoMouseInputs;
73 const MENU_BAR = sys::ImGuiWindowFlags_MenuBar;
75 const HORIZONTAL_SCROLLBAR = sys::ImGuiWindowFlags_HorizontalScrollbar;
77 const NO_FOCUS_ON_APPEARING = sys::ImGuiWindowFlags_NoFocusOnAppearing;
79 const NO_BRING_TO_FRONT_ON_FOCUS = sys::ImGuiWindowFlags_NoBringToFrontOnFocus;
82 const ALWAYS_VERTICAL_SCROLLBAR = sys::ImGuiWindowFlags_AlwaysVerticalScrollbar;
84 const ALWAYS_HORIZONTAL_SCROLLBAR = sys::ImGuiWindowFlags_AlwaysHorizontalScrollbar;
86 const ALWAYS_USE_WINDOW_PADDING = sys::ImGuiWindowFlags_AlwaysUseWindowPadding;
88 const NO_NAV_INPUTS = sys::ImGuiWindowFlags_NoNavInputs;
90 const NO_NAV_FOCUS = sys::ImGuiWindowFlags_NoNavFocus;
93 const UNSAVED_DOCUMENT = sys::ImGuiWindowFlags_UnsavedDocument;
95 const NO_NAV = sys::ImGuiWindowFlags_NoNav;
99 const NO_DECORATION = sys::ImGuiWindowFlags_NoDecoration;
104 const NO_INPUTS = sys::ImGuiWindowFlags_NoInputs;
109 }
110}
111
112impl<'ui> Ui<'ui> {
114 #[doc(alias = "IsWindowAppearing")]
116 pub fn is_window_appearing(&self) -> bool {
117 unsafe { sys::igIsWindowAppearing() }
118 }
119 #[doc(alias = "IsWindowCollapsed")]
121 pub fn is_window_collapsed(&self) -> bool {
122 unsafe { sys::igIsWindowCollapsed() }
123 }
124 #[doc(alias = "IsWindowFocused")]
126 pub fn is_window_focused(&self) -> bool {
127 unsafe { sys::igIsWindowFocused(0) }
128 }
129 #[doc(alias = "IsWindowFocused")]
131 pub fn is_window_focused_with_flags(&self, flags: WindowFocusedFlags) -> bool {
132 unsafe { sys::igIsWindowFocused(flags.bits() as i32) }
133 }
134 #[doc(alias = "IsWindowHovered")]
136 pub fn is_window_hovered(&self) -> bool {
137 unsafe { sys::igIsWindowHovered(0) }
138 }
139 #[doc(alias = "IsWindowHovered")]
141 pub fn is_window_hovered_with_flags(&self, flags: WindowHoveredFlags) -> bool {
142 unsafe { sys::igIsWindowHovered(flags.bits() as i32) }
143 }
144 #[doc(alias = "GetWindowPos")]
146 pub fn window_pos(&self) -> [f32; 2] {
147 let mut out = sys::ImVec2::zero();
148 unsafe { sys::igGetWindowPos(&mut out) };
149 out.into()
150 }
151 #[doc(alias = "GetWindowPos")]
153 pub fn window_size(&self) -> [f32; 2] {
154 let mut out = sys::ImVec2::zero();
155 unsafe { sys::igGetWindowSize(&mut out) };
156 out.into()
157 }
158}
159
160#[derive(Debug)]
162#[must_use]
163pub struct Window<'a, T> {
164 name: T,
165 opened: Option<&'a mut bool>,
166 flags: WindowFlags,
167 pos: [f32; 2],
168 pos_cond: Condition,
169 pos_pivot: [f32; 2],
170 size: [f32; 2],
171 size_cond: Condition,
172 size_constraints: Option<([f32; 2], [f32; 2])>,
173 content_size: [f32; 2],
174 collapsed: bool,
175 collapsed_cond: Condition,
176 focused: bool,
177 bg_alpha: f32,
178}
179
180impl<'a, T: AsRef<str>> Window<'a, T> {
181 pub fn new(name: T) -> Self {
183 Window {
184 name,
185 opened: None,
186 flags: WindowFlags::empty(),
187 pos: [0.0, 0.0],
188 pos_cond: Condition::Never,
189 pos_pivot: [0.0, 0.0],
190 size: [0.0, 0.0],
191 size_cond: Condition::Never,
192 size_constraints: None,
193 content_size: [0.0, 0.0],
194 collapsed: false,
195 collapsed_cond: Condition::Never,
196 focused: false,
197 bg_alpha: f32::NAN,
198 }
199 }
200 #[inline]
202 pub fn opened(mut self, opened: &'a mut bool) -> Self {
203 self.opened = Some(opened);
204 self
205 }
206 #[inline]
208 pub fn flags(mut self, flags: WindowFlags) -> Self {
209 self.flags = flags;
210 self
211 }
212 #[inline]
214 pub fn position(mut self, position: [f32; 2], condition: Condition) -> Self {
215 self.pos = position;
216 self.pos_cond = condition;
217 self
218 }
219 #[inline]
225 pub fn position_pivot(mut self, pivot: [f32; 2]) -> Self {
226 self.pos_pivot = pivot;
227 self
228 }
229 #[inline]
231 pub fn size(mut self, size: [f32; 2], condition: Condition) -> Self {
232 self.size = size;
233 self.size_cond = condition;
234 self
235 }
236 #[inline]
240 pub fn size_constraints(mut self, size_min: [f32; 2], size_max: [f32; 2]) -> Self {
241 self.size_constraints = Some((size_min, size_max));
242 self
243 }
244 #[inline]
249 pub fn content_size(mut self, size: [f32; 2]) -> Self {
250 self.content_size = size;
251 self
252 }
253 #[inline]
255 pub fn collapsed(mut self, collapsed: bool, condition: Condition) -> Self {
256 self.collapsed = collapsed;
257 self.collapsed_cond = condition;
258 self
259 }
260 #[inline]
262 pub fn focused(mut self, focused: bool) -> Self {
263 self.focused = focused;
264 self
265 }
266 #[inline]
270 pub fn bg_alpha(mut self, bg_alpha: f32) -> Self {
271 self.bg_alpha = bg_alpha;
272 self
273 }
274 #[inline]
278 pub fn title_bar(mut self, value: bool) -> Self {
279 self.flags.set(WindowFlags::NO_TITLE_BAR, !value);
280 self
281 }
282 #[inline]
286 pub fn resizable(mut self, value: bool) -> Self {
287 self.flags.set(WindowFlags::NO_RESIZE, !value);
288 self
289 }
290 #[inline]
294 pub fn movable(mut self, value: bool) -> Self {
295 self.flags.set(WindowFlags::NO_MOVE, !value);
296 self
297 }
298 #[inline]
303 pub fn scroll_bar(mut self, value: bool) -> Self {
304 self.flags.set(WindowFlags::NO_SCROLLBAR, !value);
305 self
306 }
307 #[inline]
313 pub fn scrollable(mut self, value: bool) -> Self {
314 self.flags.set(WindowFlags::NO_SCROLL_WITH_MOUSE, !value);
315 self
316 }
317 #[inline]
321 pub fn collapsible(mut self, value: bool) -> Self {
322 self.flags.set(WindowFlags::NO_COLLAPSE, !value);
323 self
324 }
325 #[inline]
329 pub fn always_auto_resize(mut self, value: bool) -> Self {
330 self.flags.set(WindowFlags::ALWAYS_AUTO_RESIZE, value);
331 self
332 }
333 #[inline]
337 pub fn draw_background(mut self, value: bool) -> Self {
338 self.flags.set(WindowFlags::NO_BACKGROUND, !value);
339 self
340 }
341 #[inline]
345 pub fn save_settings(mut self, value: bool) -> Self {
346 self.flags.set(WindowFlags::NO_SAVED_SETTINGS, !value);
347 self
348 }
349 #[inline]
354 pub fn mouse_inputs(mut self, value: bool) -> Self {
355 self.flags.set(WindowFlags::NO_MOUSE_INPUTS, !value);
356 self
357 }
358 #[inline]
362 pub fn menu_bar(mut self, value: bool) -> Self {
363 self.flags.set(WindowFlags::MENU_BAR, value);
364 self
365 }
366 #[inline]
370 pub fn horizontal_scrollbar(mut self, value: bool) -> Self {
371 self.flags.set(WindowFlags::HORIZONTAL_SCROLLBAR, value);
372 self
373 }
374 #[inline]
378 pub fn focus_on_appearing(mut self, value: bool) -> Self {
379 self.flags.set(WindowFlags::NO_FOCUS_ON_APPEARING, !value);
380 self
381 }
382 #[inline]
387 pub fn bring_to_front_on_focus(mut self, value: bool) -> Self {
388 self.flags
389 .set(WindowFlags::NO_BRING_TO_FRONT_ON_FOCUS, !value);
390 self
391 }
392 #[inline]
396 pub fn always_vertical_scrollbar(mut self, value: bool) -> Self {
397 self.flags
398 .set(WindowFlags::ALWAYS_VERTICAL_SCROLLBAR, value);
399 self
400 }
401 #[inline]
405 pub fn always_horizontal_scrollbar(mut self, value: bool) -> Self {
406 self.flags
407 .set(WindowFlags::ALWAYS_HORIZONTAL_SCROLLBAR, value);
408 self
409 }
410 #[inline]
414 pub fn always_use_window_padding(mut self, value: bool) -> Self {
415 self.flags
416 .set(WindowFlags::ALWAYS_USE_WINDOW_PADDING, value);
417 self
418 }
419 #[inline]
423 pub fn nav_inputs(mut self, value: bool) -> Self {
424 self.flags.set(WindowFlags::NO_NAV_INPUTS, !value);
425 self
426 }
427 #[inline]
432 pub fn nav_focus(mut self, value: bool) -> Self {
433 self.flags.set(WindowFlags::NO_NAV_FOCUS, !value);
434 self
435 }
436 #[inline]
440 pub fn unsaved_document(mut self, value: bool) -> Self {
441 self.flags.set(WindowFlags::UNSAVED_DOCUMENT, value);
442 self
443 }
444 #[inline]
452 pub fn no_nav(mut self) -> Self {
453 self.flags |= WindowFlags::NO_NAV;
454 self
455 }
456 #[inline]
466 pub fn no_decoration(mut self) -> Self {
467 self.flags |= WindowFlags::NO_DECORATION;
468 self
469 }
470 #[inline]
479 pub fn no_inputs(mut self) -> Self {
480 self.flags |= WindowFlags::NO_INPUTS;
481 self
482 }
483 #[must_use]
490 pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<WindowToken<'ui>> {
491 if self.pos_cond != Condition::Never {
492 unsafe {
493 sys::igSetNextWindowPos(
494 self.pos.into(),
495 self.pos_cond as i32,
496 self.pos_pivot.into(),
497 )
498 };
499 }
500 if self.size_cond != Condition::Never {
501 unsafe { sys::igSetNextWindowSize(self.size.into(), self.size_cond as i32) };
502 }
503 if let Some((size_min, size_max)) = self.size_constraints {
504 unsafe {
506 sys::igSetNextWindowSizeConstraints(
507 size_min.into(),
508 size_max.into(),
509 None,
510 ptr::null_mut(),
511 )
512 };
513 }
514 if self.content_size[0] != 0.0 || self.content_size[1] != 0.0 {
515 unsafe { sys::igSetNextWindowContentSize(self.content_size.into()) };
516 }
517 if self.collapsed_cond != Condition::Never {
518 unsafe { sys::igSetNextWindowCollapsed(self.collapsed, self.collapsed_cond as i32) };
519 }
520 if self.focused {
521 unsafe { sys::igSetNextWindowFocus() };
522 }
523 if self.bg_alpha.is_finite() {
524 unsafe { sys::igSetNextWindowBgAlpha(self.bg_alpha) };
525 }
526 let should_render = unsafe {
527 sys::igBegin(
528 ui.scratch_txt(self.name),
529 self.opened
530 .map(|x| x as *mut bool)
531 .unwrap_or(ptr::null_mut()),
532 self.flags.bits() as i32,
533 )
534 };
535 if should_render {
536 Some(WindowToken::new(ui))
537 } else {
538 unsafe { sys::igEnd() };
539 None
540 }
541 }
542 pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
548 self.begin(ui).map(|_window| f())
549 }
550}
551
552create_token!(
553 pub struct WindowToken<'ui>;
556
557 drop { sys::igEnd() }
559);