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_NAV = Self::NO_NAV_INPUTS.bits() | Self::NO_NAV_FOCUS.bits();
103 const NO_DECORATION = Self::NO_TITLE_BAR.bits() | Self::NO_RESIZE.bits() | Self::NO_SCROLLBAR.bits() | Self::NO_COLLAPSE.bits();
105 const NO_INPUTS = Self::NO_MOUSE_INPUTS.bits() | Self::NO_NAV_INPUTS.bits();
107 }
108}
109
110pub struct Window<'ui> {
112 ui: &'ui Ui,
113 name: String,
114 flags: WindowFlags,
115 size: Option<[f32; 2]>,
116 size_condition: Condition,
117 pos: Option<[f32; 2]>,
118 pos_condition: Condition,
119 content_size: Option<[f32; 2]>,
120 content_size_condition: Condition,
121 collapsed: Option<bool>,
122 collapsed_condition: Condition,
123 focused: Option<bool>,
124 bg_alpha: Option<f32>,
125}
126
127impl<'ui> Window<'ui> {
128 pub fn new(ui: &'ui Ui, name: impl Into<String>) -> Self {
130 Self {
131 ui,
132 name: name.into(),
133 flags: WindowFlags::empty(),
134 size: None,
135 size_condition: Condition::Always,
136 pos: None,
137 pos_condition: Condition::Always,
138 content_size: None,
139 content_size_condition: Condition::Always,
140 collapsed: None,
141 collapsed_condition: Condition::Always,
142 focused: None,
143 bg_alpha: None,
144 }
145 }
146
147 pub fn flags(mut self, flags: WindowFlags) -> Self {
149 self.flags = flags;
150 self
151 }
152
153 pub fn size(mut self, size: [f32; 2], condition: Condition) -> Self {
155 self.size = Some(size);
156 self.size_condition = condition;
157 self
158 }
159
160 pub fn position(mut self, pos: [f32; 2], condition: Condition) -> Self {
162 self.pos = Some(pos);
163 self.pos_condition = condition;
164 self
165 }
166
167 pub fn content_size(mut self, size: [f32; 2], condition: Condition) -> Self {
169 self.content_size = Some(size);
170 self.content_size_condition = condition;
171 self
172 }
173
174 pub fn collapsed(mut self, collapsed: bool, condition: Condition) -> Self {
176 self.collapsed = Some(collapsed);
177 self.collapsed_condition = condition;
178 self
179 }
180
181 pub fn focused(mut self, focused: bool) -> Self {
183 self.focused = Some(focused);
184 self
185 }
186
187 pub fn bg_alpha(mut self, alpha: f32) -> Self {
189 self.bg_alpha = Some(alpha);
190 self
191 }
192
193 pub fn build<F, R>(self, f: F) -> Option<R>
195 where
196 F: FnOnce() -> R,
197 {
198 let _token = self.begin()?;
199 Some(f())
200 }
201
202 fn begin(self) -> Option<WindowToken<'ui>> {
204 use std::ffi::CString;
205
206 let name_cstr = CString::new(self.name).ok()?;
207
208 if let Some(size) = self.size {
210 unsafe {
211 let size_vec = crate::sys::ImVec2 {
212 x: size[0],
213 y: size[1],
214 };
215 crate::sys::igSetNextWindowSize(size_vec, self.size_condition as i32);
216 }
217 }
218
219 if let Some(pos) = self.pos {
220 unsafe {
221 let pos_vec = crate::sys::ImVec2 {
222 x: pos[0],
223 y: pos[1],
224 };
225 let pivot_vec = crate::sys::ImVec2 { x: 0.0, y: 0.0 };
226 crate::sys::igSetNextWindowPos(pos_vec, self.pos_condition as i32, pivot_vec);
227 }
228 }
229
230 if let Some(content_size) = self.content_size {
231 unsafe {
232 let content_size_vec = crate::sys::ImVec2 {
233 x: content_size[0],
234 y: content_size[1],
235 };
236 crate::sys::igSetNextWindowContentSize(content_size_vec);
237 }
238 }
239
240 if let Some(collapsed) = self.collapsed {
241 unsafe {
242 crate::sys::igSetNextWindowCollapsed(collapsed, self.collapsed_condition as i32);
243 }
244 }
245
246 if let Some(focused) = self.focused
247 && focused
248 {
249 unsafe {
250 crate::sys::igSetNextWindowFocus();
251 }
252 }
253
254 if let Some(alpha) = self.bg_alpha {
255 unsafe {
256 crate::sys::igSetNextWindowBgAlpha(alpha);
257 }
258 }
259
260 let mut open = true;
262 let result =
263 unsafe { crate::sys::igBegin(name_cstr.as_ptr(), &mut open, self.flags.bits()) };
264
265 if result && open {
268 Some(WindowToken {
269 _phantom: std::marker::PhantomData,
270 })
271 } else {
272 unsafe {
274 crate::sys::igEnd();
275 }
276 None
277 }
278 }
279}
280
281pub struct WindowToken<'ui> {
283 _phantom: std::marker::PhantomData<&'ui ()>,
284}
285
286impl<'ui> Drop for WindowToken<'ui> {
287 fn drop(&mut self) {
288 unsafe {
289 crate::sys::igEnd();
290 }
291 }
292}