arcdps_imgui\window/
child_window.rs

1use std::f32;
2use std::os::raw::{c_char, c_void};
3
4use crate::sys;
5use crate::window::WindowFlags;
6use crate::{Id, Ui};
7
8/// Builder for a child window
9#[derive(Copy, Clone, Debug)]
10#[must_use]
11pub struct ChildWindow<'a> {
12    id: Id<'a>,
13    flags: WindowFlags,
14    size: [f32; 2],
15    content_size: [f32; 2],
16    focused: bool,
17    bg_alpha: f32,
18    border: bool,
19}
20
21impl<'a> ChildWindow<'a> {
22    /// Creates a new child window builder with the given ID
23    #[doc(alias = "BeginChildID")]
24    pub fn new<T: Into<Id<'a>>>(id: T) -> ChildWindow<'a> {
25        ChildWindow {
26            id: id.into(),
27            flags: WindowFlags::empty(),
28            size: [0.0, 0.0],
29            content_size: [0.0, 0.0],
30            focused: false,
31            bg_alpha: f32::NAN,
32            border: false,
33        }
34    }
35    /// Replace current window flags with the given value
36    #[inline]
37    pub fn flags(mut self, flags: WindowFlags) -> Self {
38        self.flags = flags;
39        self
40    }
41    /// Sets the child window size.
42    ///
43    /// For each independent axis of size:
44    ///
45    /// - `> 0.0`: fixed size
46    /// - `= 0.0`: use remaining host window size
47    /// - `< 0.0`: use remaining host window size minus abs(size)
48    #[inline]
49    pub fn size(mut self, size: [f32; 2]) -> Self {
50        self.size = size;
51        self
52    }
53    /// Sets the window content size, which can be used to enforce scrollbars.
54    ///
55    /// Does not include window decorations (title bar, menu bar, etc.). Set one of the values to
56    /// 0.0 to leave the size automatic.
57    #[inline]
58    #[doc(alias = "SetNextWindowContentSize")]
59    pub fn content_size(mut self, size: [f32; 2]) -> Self {
60        self.content_size = size;
61        self
62    }
63    /// Sets the window focused state, which can be used to bring the window to front
64    #[inline]
65    #[doc(alias = "SetNextWindwowFocus")]
66    pub fn focused(mut self, focused: bool) -> Self {
67        self.focused = focused;
68        self
69    }
70    /// Sets the background color alpha value.
71    ///
72    /// See also `draw_background`
73    #[inline]
74    #[doc(alias = "SetNextWindowContentBgAlpha")]
75    pub fn bg_alpha(mut self, bg_alpha: f32) -> Self {
76        self.bg_alpha = bg_alpha;
77        self
78    }
79    /// Enables/disables the child window border.
80    ///
81    /// Disabled by default.
82    #[inline]
83    pub fn border(mut self, border: bool) -> Self {
84        self.border = border;
85        self
86    }
87    /// Enables/disables moving the window when child window is dragged.
88    ///
89    /// Enabled by default.
90    #[inline]
91    pub fn movable(mut self, value: bool) -> Self {
92        self.flags.set(WindowFlags::NO_MOVE, !value);
93        self
94    }
95    /// Enables/disables scrollbars (scrolling is still possible with the mouse or
96    /// programmatically).
97    ///
98    /// Enabled by default.
99    #[inline]
100    pub fn scroll_bar(mut self, value: bool) -> Self {
101        self.flags.set(WindowFlags::NO_SCROLLBAR, !value);
102        self
103    }
104    /// Enables/disables vertical scrolling with the mouse wheel.
105    ///
106    /// Enabled by default.
107    /// When enabled, child windows forward the mouse wheel to the parent unless `NO_SCROLLBAR`
108    /// is also set.
109    #[inline]
110    pub fn scrollable(mut self, value: bool) -> Self {
111        self.flags.set(WindowFlags::NO_SCROLL_WITH_MOUSE, !value);
112        self
113    }
114    /// Enables/disables resizing the window to its content on every frame.
115    ///
116    /// Disabled by default.
117    #[inline]
118    pub fn always_auto_resize(mut self, value: bool) -> Self {
119        self.flags.set(WindowFlags::ALWAYS_AUTO_RESIZE, value);
120        self
121    }
122    /// Enables/disables drawing of background color and outside border.
123    ///
124    /// Enabled by default.
125    #[inline]
126    pub fn draw_background(mut self, value: bool) -> Self {
127        self.flags.set(WindowFlags::NO_BACKGROUND, !value);
128        self
129    }
130    /// Enables/disables catching mouse input.
131    ///
132    /// Enabled by default.
133    /// Note: Hovering test will pass through when disabled
134    #[inline]
135    pub fn mouse_inputs(mut self, value: bool) -> Self {
136        self.flags.set(WindowFlags::NO_MOUSE_INPUTS, !value);
137        self
138    }
139    /// Enables/disables the menu bar.
140    ///
141    /// Disabled by default.
142    #[inline]
143    pub fn menu_bar(mut self, value: bool) -> Self {
144        self.flags.set(WindowFlags::MENU_BAR, value);
145        self
146    }
147    /// Enables/disables the horizontal scrollbar.
148    ///
149    /// Disabled by default.
150    #[inline]
151    pub fn horizontal_scrollbar(mut self, value: bool) -> Self {
152        self.flags.set(WindowFlags::HORIZONTAL_SCROLLBAR, value);
153        self
154    }
155    /// Enables/disables taking focus when transitioning from hidden to visible state.
156    ///
157    /// Enabled by default.
158    #[inline]
159    pub fn focus_on_appearing(mut self, value: bool) -> Self {
160        self.flags.set(WindowFlags::NO_FOCUS_ON_APPEARING, !value);
161        self
162    }
163    /// Enables/disables bringing the window to front when taking focus (e.g. clicking it or
164    /// programmatically giving it focus).
165    ///
166    /// Enabled by default.
167    #[inline]
168    pub fn bring_to_front_on_focus(mut self, value: bool) -> Self {
169        self.flags
170            .set(WindowFlags::NO_BRING_TO_FRONT_ON_FOCUS, !value);
171        self
172    }
173    /// When enabled, forces the vertical scrollbar to render regardless of the content size.
174    ///
175    /// Disabled by default.
176    #[inline]
177    pub fn always_vertical_scrollbar(mut self, value: bool) -> Self {
178        self.flags
179            .set(WindowFlags::ALWAYS_VERTICAL_SCROLLBAR, value);
180        self
181    }
182    /// When enabled, forces the horizontal scrollbar to render regardless of the content size.
183    ///
184    /// Disabled by default.
185    #[inline]
186    pub fn always_horizontal_scrollbar(mut self, value: bool) -> Self {
187        self.flags
188            .set(WindowFlags::ALWAYS_HORIZONTAL_SCROLLBAR, value);
189        self
190    }
191    /// When enabled, ensures child windows without border use `style.window_padding`.
192    ///
193    /// Disabled by default.
194    #[inline]
195    pub fn always_use_window_padding(mut self, value: bool) -> Self {
196        self.flags
197            .set(WindowFlags::ALWAYS_USE_WINDOW_PADDING, value);
198        self
199    }
200    /// Enables/disables gamepad/keyboard navigation within the window.
201    ///
202    /// Enabled by default.
203    #[inline]
204    pub fn nav_inputs(mut self, value: bool) -> Self {
205        self.flags.set(WindowFlags::NO_NAV_INPUTS, !value);
206        self
207    }
208    /// Enables/disables focusing toward this window with gamepad/keyboard navigation (e.g.
209    /// CTRL+TAB).
210    ///
211    /// Enabled by default.
212    #[inline]
213    pub fn nav_focus(mut self, value: bool) -> Self {
214        self.flags.set(WindowFlags::NO_NAV_FOCUS, !value);
215        self
216    }
217    /// Disable gamepad/keyboard navigation and focusing.
218    ///
219    /// Shorthand for
220    /// ```text
221    /// .nav_inputs(false)
222    /// .nav_focus(false)
223    /// ```
224    #[inline]
225    pub fn no_nav(mut self) -> Self {
226        self.flags |= WindowFlags::NO_NAV;
227        self
228    }
229    /// Don't handle input.
230    ///
231    /// Shorthand for
232    /// ```text
233    /// .mouse_inputs(false)
234    /// .nav_inputs(false)
235    /// .nav_focus(false)
236    /// ```
237    #[inline]
238    pub fn no_inputs(mut self) -> Self {
239        self.flags |= WindowFlags::NO_INPUTS;
240        self
241    }
242    /// Creates a child window and starts append to it.
243    ///
244    /// Returns `Some(ChildWindowToken)` if the window is visible. After content has been
245    /// rendered, the token must be ended by calling `.end()`.
246    ///
247    /// Returns `None` if the window is not visible and no content should be rendered.
248    pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<ChildWindowToken<'ui>> {
249        if self.content_size[0] != 0.0 || self.content_size[1] != 0.0 {
250            unsafe { sys::igSetNextWindowContentSize(self.content_size.into()) };
251        }
252        if self.focused {
253            unsafe { sys::igSetNextWindowFocus() };
254        }
255        if self.bg_alpha.is_finite() {
256            unsafe { sys::igSetNextWindowBgAlpha(self.bg_alpha) };
257        }
258        let id = unsafe {
259            match self.id {
260                Id::Int(i) => sys::igGetID_Ptr(i as *const c_void),
261                Id::Ptr(p) => sys::igGetID_Ptr(p),
262                Id::Str(s) => {
263                    let start = s.as_ptr() as *const c_char;
264                    let end = start.add(s.len());
265                    sys::igGetID_StrStr(start, end)
266                }
267            }
268        };
269        let should_render = unsafe {
270            sys::igBeginChild_ID(id, self.size.into(), self.border, self.flags.bits() as i32)
271        };
272        if should_render {
273            Some(ChildWindowToken::new(ui))
274        } else {
275            unsafe { sys::igEndChild() };
276            None
277        }
278    }
279    /// Creates a child window and runs a closure to construct the contents.
280    /// Returns the result of the closure, if it is called.
281    ///
282    /// Note: the closure is not called if no window content is visible (e.g. window is collapsed
283    /// or fully clipped).
284    pub fn build<T, F: FnOnce() -> T>(self, ui: &Ui<'_>, f: F) -> Option<T> {
285        self.begin(ui).map(|_window| f())
286    }
287}
288
289create_token!(
290    /// Tracks a child window that can be ended by calling `.end()`
291    /// or by dropping
292    pub struct ChildWindowToken<'ui>;
293
294    /// Ends a window
295    drop { sys::igEndChild() }
296);