Skip to main content

dear_imgui_rs/dock_space/
window_class.rs

1use super::flags::{DockNodeFlags, validate_dock_node_flags};
2use super::validation::{assert_nonzero_id, optional_nonzero_id_raw};
3use crate::{Id, sys};
4use std::ptr;
5
6/// Parent viewport policy for a docking window class.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum WindowClassParentViewport {
9    /// Use Dear ImGui's default parent viewport behavior.
10    Default,
11    /// Request the platform backend to avoid parent-child platform windows.
12    NoParent,
13    /// Request a specific parent viewport.
14    Parent(Id),
15}
16
17impl Default for WindowClassParentViewport {
18    fn default() -> Self {
19        Self::Default
20    }
21}
22
23impl WindowClassParentViewport {
24    pub(super) fn raw(self, caller: &str) -> sys::ImGuiID {
25        match self {
26            Self::Default => !0,
27            Self::NoParent => 0,
28            Self::Parent(id) => {
29                assert_nonzero_id(caller, "parent_viewport_id", id);
30                id.raw()
31            }
32        }
33    }
34}
35
36/// Window class for docking configuration
37#[derive(Debug, Clone)]
38pub struct WindowClass {
39    /// User class ID. `None` means the default unclassed window class.
40    pub class_id: Option<Id>,
41    /// Hint for the platform backend parent viewport behavior.
42    pub parent_viewport: WindowClassParentViewport,
43    /// ID of parent window for shortcut focus route evaluation
44    pub focus_route_parent_window_id: Option<Id>,
45    /// Viewport flags to set when a window of this class owns a viewport.
46    pub viewport_flags_override_set: crate::ViewportFlags,
47    /// Viewport flags to clear when a window of this class owns a viewport.
48    pub viewport_flags_override_clear: crate::ViewportFlags,
49    /// Tab item flags to set when a window of this class is submitted into a dock node tab bar.
50    pub tab_item_flags_override_set: crate::widget::TabItemOptions,
51    /// Dock node flags to set when a window of this class is hosted by a dock node.
52    pub dock_node_flags_override_set: DockNodeFlags,
53    /// Set to true to enforce single floating windows of this class always having their own docking node
54    pub docking_always_tab_bar: bool,
55    /// Set to true to allow windows of this class to be docked/merged with an unclassed window
56    pub docking_allow_unclassed: bool,
57    /// Opaque platform-backend icon payload.
58    ///
59    /// Dear ImGui treats this as backend-owned data. Keep the pointed-to allocation valid for as
60    /// long as the platform backend may inspect this window class.
61    pub platform_icon_data: Option<ptr::NonNull<std::ffi::c_void>>,
62}
63
64impl Default for WindowClass {
65    fn default() -> Self {
66        Self {
67            class_id: None,
68            parent_viewport: WindowClassParentViewport::Default,
69            focus_route_parent_window_id: None,
70            viewport_flags_override_set: crate::ViewportFlags::NONE,
71            viewport_flags_override_clear: crate::ViewportFlags::NONE,
72            tab_item_flags_override_set: crate::widget::TabItemOptions::new(),
73            dock_node_flags_override_set: DockNodeFlags::NONE,
74            docking_always_tab_bar: false,
75            docking_allow_unclassed: true,
76            platform_icon_data: None,
77        }
78    }
79}
80
81impl WindowClass {
82    /// Creates a new window class with the specified class ID
83    pub fn new(class_id: Id) -> Self {
84        assert_nonzero_id("WindowClass::new()", "class_id", class_id);
85        Self {
86            class_id: Some(class_id),
87            ..Default::default()
88        }
89    }
90
91    /// Sets the parent viewport policy.
92    pub fn parent_viewport(mut self, parent: WindowClassParentViewport) -> Self {
93        self.parent_viewport = parent;
94        self
95    }
96
97    /// Requests the platform backend to avoid parenting this class's platform windows.
98    pub fn no_parent_viewport(mut self) -> Self {
99        self.parent_viewport = WindowClassParentViewport::NoParent;
100        self
101    }
102
103    /// Requests a specific parent viewport ID.
104    pub fn parent_viewport_id(mut self, id: Id) -> Self {
105        assert_nonzero_id("WindowClass::parent_viewport_id()", "id", id);
106        self.parent_viewport = WindowClassParentViewport::Parent(id);
107        self
108    }
109
110    /// Sets the focus route parent window ID
111    pub fn focus_route_parent_window_id(mut self, id: Id) -> Self {
112        assert_nonzero_id("WindowClass::focus_route_parent_window_id()", "id", id);
113        self.focus_route_parent_window_id = Some(id);
114        self
115    }
116
117    /// Sets viewport flags when a window of this class owns a viewport.
118    pub fn viewport_flags_override_set(mut self, flags: crate::ViewportFlags) -> Self {
119        self.viewport_flags_override_set = flags;
120        self
121    }
122
123    /// Clears viewport flags when a window of this class owns a viewport.
124    pub fn viewport_flags_override_clear(mut self, flags: crate::ViewportFlags) -> Self {
125        self.viewport_flags_override_clear = flags;
126        self
127    }
128
129    /// Sets and clears viewport flags when a window of this class owns a viewport.
130    pub fn viewport_flags_overrides(
131        mut self,
132        set: crate::ViewportFlags,
133        clear: crate::ViewportFlags,
134    ) -> Self {
135        self.viewport_flags_override_set = set;
136        self.viewport_flags_override_clear = clear;
137        self
138    }
139
140    /// Sets tab item flags when a window of this class is submitted into a dock node tab bar.
141    pub fn tab_item_flags_override_set(
142        mut self,
143        options: impl Into<crate::widget::TabItemOptions>,
144    ) -> Self {
145        self.tab_item_flags_override_set = options.into();
146        self
147    }
148
149    /// Sets dock node flags when a window of this class is hosted by a dock node.
150    pub fn dock_node_flags_override_set(mut self, flags: DockNodeFlags) -> Self {
151        self.dock_node_flags_override_set = flags;
152        self
153    }
154
155    /// Enables always showing tab bar for single floating windows
156    pub fn docking_always_tab_bar(mut self, enabled: bool) -> Self {
157        self.docking_always_tab_bar = enabled;
158        self
159    }
160
161    /// Allows docking with unclassed windows
162    pub fn docking_allow_unclassed(mut self, enabled: bool) -> Self {
163        self.docking_allow_unclassed = enabled;
164        self
165    }
166
167    /// Sets opaque icon data consumed by the platform backend.
168    ///
169    /// # Safety
170    ///
171    /// `data` must remain valid for as long as the platform backend may read it, and it must point
172    /// to the representation expected by that backend.
173    pub unsafe fn platform_icon_data_raw(mut self, data: *mut std::ffi::c_void) -> Self {
174        self.platform_icon_data = ptr::NonNull::new(data);
175        self
176    }
177
178    fn validate(&self, caller: &str) {
179        crate::io::validate_viewport_flags(
180            caller,
181            self.viewport_flags_override_set | self.viewport_flags_override_clear,
182        );
183        let overlap =
184            self.viewport_flags_override_set.bits() & self.viewport_flags_override_clear.bits();
185        assert!(
186            overlap == 0,
187            "{caller} cannot set and clear the same ImGuiViewportFlags bits: 0x{overlap:X}"
188        );
189        self.tab_item_flags_override_set
190            .validate_for_tab_item(caller);
191        validate_dock_node_flags(caller, self.dock_node_flags_override_set);
192    }
193
194    /// Converts to ImGui's internal representation
195    pub(super) fn to_imgui(&self, caller: &str) -> sys::ImGuiWindowClass {
196        self.validate(caller);
197        sys::ImGuiWindowClass {
198            ClassId: optional_nonzero_id_raw(caller, "class_id", self.class_id),
199            ParentViewportId: self.parent_viewport.raw(caller),
200            FocusRouteParentWindowId: optional_nonzero_id_raw(
201                caller,
202                "focus_route_parent_window_id",
203                self.focus_route_parent_window_id,
204            ),
205            ViewportFlagsOverrideSet: self.viewport_flags_override_set.bits(),
206            ViewportFlagsOverrideClear: self.viewport_flags_override_clear.bits(),
207            TabItemFlagsOverrideSet: self.tab_item_flags_override_set.bits(),
208            DockNodeFlagsOverrideSet: self.dock_node_flags_override_set.bits(),
209            DockingAlwaysTabBar: self.docking_always_tab_bar,
210            DockingAllowUnclassed: self.docking_allow_unclassed,
211            PlatformIconData: self
212                .platform_icon_data
213                .map_or(ptr::null_mut(), ptr::NonNull::as_ptr),
214        }
215    }
216}