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#[cfg(feature = "serde")]
51use serde::{Deserialize, Serialize};
52
53pub(crate) mod child_window;
54pub(crate) mod content_region;
55pub(crate) mod scroll;
56
57bitflags! {
61 #[repr(transparent)]
63 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
64 pub struct WindowFlags: i32 {
65 const NO_TITLE_BAR = sys::ImGuiWindowFlags_NoTitleBar as i32;
67 const NO_RESIZE = sys::ImGuiWindowFlags_NoResize as i32;
69 const NO_MOVE = sys::ImGuiWindowFlags_NoMove as i32;
71 const NO_SCROLLBAR = sys::ImGuiWindowFlags_NoScrollbar as i32;
73 const NO_SCROLL_WITH_MOUSE = sys::ImGuiWindowFlags_NoScrollWithMouse as i32;
75 const NO_COLLAPSE = sys::ImGuiWindowFlags_NoCollapse as i32;
77 const ALWAYS_AUTO_RESIZE = sys::ImGuiWindowFlags_AlwaysAutoResize as i32;
79 const NO_BACKGROUND = sys::ImGuiWindowFlags_NoBackground as i32;
81 const NO_SAVED_SETTINGS = sys::ImGuiWindowFlags_NoSavedSettings as i32;
83 const NO_MOUSE_INPUTS = sys::ImGuiWindowFlags_NoMouseInputs as i32;
85 const MENU_BAR = sys::ImGuiWindowFlags_MenuBar as i32;
87 const HORIZONTAL_SCROLLBAR = sys::ImGuiWindowFlags_HorizontalScrollbar as i32;
89 const NO_FOCUS_ON_APPEARING = sys::ImGuiWindowFlags_NoFocusOnAppearing as i32;
91 const NO_BRING_TO_FRONT_ON_FOCUS = sys::ImGuiWindowFlags_NoBringToFrontOnFocus as i32;
93 const ALWAYS_VERTICAL_SCROLLBAR = sys::ImGuiWindowFlags_AlwaysVerticalScrollbar as i32;
95 const ALWAYS_HORIZONTAL_SCROLLBAR = sys::ImGuiWindowFlags_AlwaysHorizontalScrollbar as i32;
97 const NO_NAV_INPUTS = sys::ImGuiWindowFlags_NoNavInputs as i32;
99 const NO_NAV_FOCUS = sys::ImGuiWindowFlags_NoNavFocus as i32;
101 const UNSAVED_DOCUMENT = sys::ImGuiWindowFlags_UnsavedDocument as i32;
103 const NO_DOCKING = sys::ImGuiWindowFlags_NoDocking as i32;
106 const DOCK_NODE_HOST = sys::ImGuiWindowFlags_DockNodeHost as i32;
108 const NO_NAV = Self::NO_NAV_INPUTS.bits() | Self::NO_NAV_FOCUS.bits();
110 const NO_DECORATION = Self::NO_TITLE_BAR.bits() | Self::NO_RESIZE.bits() | Self::NO_SCROLLBAR.bits() | Self::NO_COLLAPSE.bits();
112 const NO_INPUTS = Self::NO_MOUSE_INPUTS.bits() | Self::NO_NAV_INPUTS.bits();
114 }
115}
116
117#[cfg(feature = "serde")]
118impl Serialize for WindowFlags {
119 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
120 where
121 S: serde::Serializer,
122 {
123 serializer.serialize_i32(self.bits())
124 }
125}
126
127#[cfg(feature = "serde")]
128impl<'de> Deserialize<'de> for WindowFlags {
129 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
130 where
131 D: serde::Deserializer<'de>,
132 {
133 let bits = i32::deserialize(deserializer)?;
134 Ok(WindowFlags::from_bits_truncate(bits))
135 }
136}
137
138pub struct Window<'ui> {
140 ui: &'ui Ui,
141 name: String,
142 flags: WindowFlags,
143 size: Option<[f32; 2]>,
144 size_condition: Condition,
145 pos: Option<[f32; 2]>,
146 pos_condition: Condition,
147 content_size: Option<[f32; 2]>,
148 content_size_condition: Condition,
149 collapsed: Option<bool>,
150 collapsed_condition: Condition,
151 focused: Option<bool>,
152 bg_alpha: Option<f32>,
153}
154
155impl<'ui> Window<'ui> {
156 pub fn new(ui: &'ui Ui, name: impl Into<String>) -> Self {
158 Self {
159 ui,
160 name: name.into(),
161 flags: WindowFlags::empty(),
162 size: None,
163 size_condition: Condition::Always,
164 pos: None,
165 pos_condition: Condition::Always,
166 content_size: None,
167 content_size_condition: Condition::Always,
168 collapsed: None,
169 collapsed_condition: Condition::Always,
170 focused: None,
171 bg_alpha: None,
172 }
173 }
174
175 pub fn flags(mut self, flags: WindowFlags) -> Self {
177 self.flags = flags;
178 self
179 }
180
181 pub fn size(mut self, size: [f32; 2], condition: Condition) -> Self {
183 self.size = Some(size);
184 self.size_condition = condition;
185 self
186 }
187
188 pub fn position(mut self, pos: [f32; 2], condition: Condition) -> Self {
190 self.pos = Some(pos);
191 self.pos_condition = condition;
192 self
193 }
194
195 pub fn content_size(mut self, size: [f32; 2], condition: Condition) -> Self {
197 self.content_size = Some(size);
198 self.content_size_condition = condition;
199 self
200 }
201
202 pub fn collapsed(mut self, collapsed: bool, condition: Condition) -> Self {
204 self.collapsed = Some(collapsed);
205 self.collapsed_condition = condition;
206 self
207 }
208
209 pub fn focused(mut self, focused: bool) -> Self {
211 self.focused = Some(focused);
212 self
213 }
214
215 pub fn bg_alpha(mut self, alpha: f32) -> Self {
217 self.bg_alpha = Some(alpha);
218 self
219 }
220
221 pub fn build<F, R>(self, f: F) -> Option<R>
223 where
224 F: FnOnce() -> R,
225 {
226 let _token = self.begin()?;
227 Some(f())
228 }
229
230 fn begin(self) -> Option<WindowToken<'ui>> {
232 use std::ffi::CString;
233
234 let name_cstr = CString::new(self.name).ok()?;
235
236 if let Some(size) = self.size {
238 unsafe {
239 let size_vec = crate::sys::ImVec2 {
240 x: size[0],
241 y: size[1],
242 };
243 crate::sys::igSetNextWindowSize(size_vec, self.size_condition as i32);
244 }
245 }
246
247 if let Some(pos) = self.pos {
248 unsafe {
249 let pos_vec = crate::sys::ImVec2 {
250 x: pos[0],
251 y: pos[1],
252 };
253 let pivot_vec = crate::sys::ImVec2 { x: 0.0, y: 0.0 };
254 crate::sys::igSetNextWindowPos(pos_vec, self.pos_condition as i32, pivot_vec);
255 }
256 }
257
258 if let Some(content_size) = self.content_size {
259 unsafe {
260 let content_size_vec = crate::sys::ImVec2 {
261 x: content_size[0],
262 y: content_size[1],
263 };
264 crate::sys::igSetNextWindowContentSize(content_size_vec);
265 }
266 }
267
268 if let Some(collapsed) = self.collapsed {
269 unsafe {
270 crate::sys::igSetNextWindowCollapsed(collapsed, self.collapsed_condition as i32);
271 }
272 }
273
274 if let Some(focused) = self.focused
275 && focused
276 {
277 unsafe {
278 crate::sys::igSetNextWindowFocus();
279 }
280 }
281
282 if let Some(alpha) = self.bg_alpha {
283 unsafe {
284 crate::sys::igSetNextWindowBgAlpha(alpha);
285 }
286 }
287
288 let mut open = true;
290 let result =
291 unsafe { crate::sys::igBegin(name_cstr.as_ptr(), &mut open, self.flags.bits()) };
292
293 if result && open {
296 Some(WindowToken {
297 _phantom: std::marker::PhantomData,
298 })
299 } else {
300 unsafe {
302 crate::sys::igEnd();
303 }
304 None
305 }
306 }
307}
308
309pub struct WindowToken<'ui> {
311 _phantom: std::marker::PhantomData<&'ui ()>,
312}
313
314impl<'ui> Drop for WindowToken<'ui> {
315 fn drop(&mut self) {
316 unsafe {
317 crate::sys::igEnd();
318 }
319 }
320}