dear_imgui_rs/dock_layout/
model.rs1use crate::{DockNodeFlags, Id, WindowClass, WindowClassError, WindowKey};
2use thiserror::Error;
3
4#[derive(Clone, Debug, PartialEq)]
6pub enum DockLayout {
7 Tabs(Vec<WindowKey>),
12 Split {
14 direction: DockSplit,
16 ratio: f32,
18 first: Box<DockLayout>,
20 second: Box<DockLayout>,
22 },
23}
24
25impl DockLayout {
26 pub fn tabs(windows: impl IntoIterator<Item = impl Into<WindowKey>>) -> Self {
28 Self::Tabs(windows.into_iter().map(Into::into).collect())
29 }
30
31 pub fn split(direction: DockSplit, ratio: f32, first: DockLayout, second: DockLayout) -> Self {
33 Self::Split {
34 direction,
35 ratio,
36 first: Box::new(first),
37 second: Box::new(second),
38 }
39 }
40
41 pub fn validate(&self) -> Result<(), DockspaceError> {
43 super::compile::compile_layout(self).map(|_| ())
44 }
45}
46
47#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
49pub enum DockSplit {
50 Left,
51 Right,
52 Up,
53 Down,
54}
55
56#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
58pub enum DockLayoutApply {
59 #[default]
61 IfMissing,
62 Replace,
70}
71
72#[derive(Clone, Debug)]
73pub(crate) struct DockspaceConfig {
74 root_id: Id,
75 flags: DockNodeFlags,
76 window_class: Option<WindowClass>,
77}
78
79impl DockspaceConfig {
80 pub(crate) fn new(
81 root_id: Id,
82 flags: DockNodeFlags,
83 window_class: Option<WindowClass>,
84 ) -> Self {
85 Self {
86 root_id,
87 flags,
88 window_class,
89 }
90 }
91
92 pub(crate) fn root_id(&self) -> Id {
93 self.root_id
94 }
95
96 pub(crate) fn dock_flags(&self) -> DockNodeFlags {
97 self.flags
98 }
99
100 pub(crate) fn window_class_ref(&self) -> Option<&WindowClass> {
101 self.window_class.as_ref()
102 }
103
104 pub(crate) fn validate(&self) -> Result<(), DockspaceError> {
105 if self.root_id.raw() == 0 {
106 return Err(DockspaceError::ZeroRootId);
107 }
108
109 let unsupported = self.flags.bits() & !DockNodeFlags::all().bits();
110 if unsupported != 0 {
111 return Err(DockspaceError::UnsupportedDockNodeFlags { bits: unsupported });
112 }
113
114 if let Some(window_class) = &self.window_class {
115 window_class.validate()?;
116 }
117
118 Ok(())
119 }
120}
121
122#[derive(Clone, Debug, Error, PartialEq)]
124#[non_exhaustive]
125pub enum DockspaceError {
126 #[error("a dockspace in the current window requires an explicit non-zero root ID")]
127 MissingRootId,
128 #[error("dockspace root ID must be non-zero")]
129 ZeroRootId,
130 #[error("dockspace flags contain unsupported ImGuiDockNodeFlags bits: 0x{bits:X}")]
131 UnsupportedDockNodeFlags { bits: i32 },
132 #[error("dockspace host position must contain finite values: {position:?}")]
133 InvalidHostPosition { position: [f32; 2] },
134 #[error(
135 "dockspace host size must be positive, finite, and safely truncatable to i32: {size:?}"
136 )]
137 InvalidHostSize { size: [f32; 2] },
138 #[error("dockspace host window name is {bytes} bytes; at most {max_bytes} bytes are supported")]
139 HostWindowNameTooLong { bytes: usize, max_bytes: usize },
140 #[error("invalid dockspace window class: {0}")]
141 InvalidWindowClass(#[from] WindowClassError),
142 #[error("dock split ratio must be finite and strictly between 0 and 1: {ratio}")]
143 InvalidSplitRatio { ratio: f32 },
144 #[error(
145 "dock window keys {first_key:?} and {second_key:?} resolve to the same Dear ImGui ID {id:?}"
146 )]
147 DuplicateWindowKey {
148 first_key: String,
149 second_key: String,
150 id: Id,
151 },
152 #[error("dock layout contains too many nodes")]
153 LayoutTooLarge,
154 #[error("docking is not enabled in ConfigFlags")]
155 DockingDisabled,
156 #[error("dockspace {root_id:?} was already submitted during this frame")]
157 DuplicateDockspaceSubmission { root_id: Id },
158 #[error("existing dock node {id:?} is not an explicit dockspace root")]
159 ExistingNodeIsNotDockspaceRoot { id: Id },
160 #[error("dockspace {root_id:?} must be submitted before any window hosted by its dock tree")]
161 WindowSubmittedBeforeDockspace { root_id: Id },
162 #[error("Dear ImGui could not create dock node {id:?}")]
163 NodeCreationFailed { id: Id },
164 #[error("Dear ImGui failed to split a docking node {direction:?} at ratio {ratio}")]
165 SplitFailed { direction: DockSplit, ratio: f32 },
166}