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);