astrelis_ui/widgets/docking/
context.rs1use super::DockTabs;
9use super::splitter::{
10 DEFAULT_SEPARATOR_SIZE, default_separator_color, default_separator_hover_color,
11};
12use super::tabs::{
13 DEFAULT_TAB_BAR_HEIGHT, default_active_tab_color, default_inactive_tab_color,
14 default_tab_bar_color, default_tab_hover_color, default_tab_text_color,
15};
16use crate::tree::{LayoutRect, NodeId, UiTree};
17use astrelis_core::alloc::HashMap;
18use astrelis_render::Color;
19
20#[derive(Debug, Clone)]
26pub struct DockingStyle {
27 pub separator_size: f32,
29 pub separator_color: Color,
31 pub separator_hover_color: Color,
33 pub tab_bar_height: f32,
35 pub tab_bar_color: Color,
37 pub active_tab_color: Color,
39 pub inactive_tab_color: Color,
41 pub tab_text_color: Color,
43 pub tab_hover_color: Color,
45 pub tab_font_size: f32,
47 pub closable: bool,
49 pub content_padding: f32,
51 pub separator_tolerance: f32,
56}
57
58impl Default for DockingStyle {
59 fn default() -> Self {
60 Self {
61 separator_size: DEFAULT_SEPARATOR_SIZE,
62 separator_color: default_separator_color(),
63 separator_hover_color: default_separator_hover_color(),
64 tab_bar_height: DEFAULT_TAB_BAR_HEIGHT,
65 tab_bar_color: default_tab_bar_color(),
66 active_tab_color: default_active_tab_color(),
67 inactive_tab_color: default_inactive_tab_color(),
68 tab_text_color: default_tab_text_color(),
69 tab_hover_color: default_tab_hover_color(),
70 tab_font_size: 11.0,
71 closable: false,
72 content_padding: 4.0,
73 separator_tolerance: 4.0,
74 }
75 }
76}
77
78impl DockingStyle {
79 pub fn separator_size(mut self, size: f32) -> Self {
81 self.separator_size = size;
82 self
83 }
84
85 pub fn separator_colors(mut self, normal: Color, hover: Color) -> Self {
87 self.separator_color = normal;
88 self.separator_hover_color = hover;
89 self
90 }
91
92 pub fn tab_bar_height(mut self, height: f32) -> Self {
94 self.tab_bar_height = height;
95 self
96 }
97
98 pub fn tab_bar_color(mut self, color: Color) -> Self {
100 self.tab_bar_color = color;
101 self
102 }
103
104 pub fn active_tab_color(mut self, color: Color) -> Self {
106 self.active_tab_color = color;
107 self
108 }
109
110 pub fn inactive_tab_color(mut self, color: Color) -> Self {
112 self.inactive_tab_color = color;
113 self
114 }
115
116 pub fn tab_text_color(mut self, color: Color) -> Self {
118 self.tab_text_color = color;
119 self
120 }
121
122 pub fn tab_hover_color(mut self, color: Color) -> Self {
124 self.tab_hover_color = color;
125 self
126 }
127
128 pub fn tab_font_size(mut self, size: f32) -> Self {
130 self.tab_font_size = size;
131 self
132 }
133
134 pub fn closable(mut self, closable: bool) -> Self {
136 self.closable = closable;
137 self
138 }
139
140 pub fn content_padding(mut self, padding: f32) -> Self {
142 self.content_padding = padding;
143 self
144 }
145
146 pub fn separator_tolerance(mut self, tolerance: f32) -> Self {
148 self.separator_tolerance = tolerance;
149 self
150 }
151}
152
153#[derive(Debug, Clone)]
155pub struct CachedContainerInfo {
156 pub layout: LayoutRect,
158 pub tab_count: usize,
160}
161
162pub struct DockingContext {
168 tab_containers: HashMap<NodeId, CachedContainerInfo>,
170 cache_dirty: bool,
172 style: DockingStyle,
174}
175
176impl DockingContext {
177 pub fn new() -> Self {
179 Self {
180 tab_containers: HashMap::new(),
181 cache_dirty: true,
182 style: DockingStyle::default(),
183 }
184 }
185
186 pub fn style(&self) -> &DockingStyle {
188 &self.style
189 }
190
191 pub fn style_mut(&mut self) -> &mut DockingStyle {
193 &mut self.style
194 }
195
196 pub fn set_style(&mut self, style: DockingStyle) {
198 self.style = style;
199 }
200
201 pub fn invalidate(&mut self) {
205 self.cache_dirty = true;
206 }
207
208 pub fn rebuild_cache(&mut self, tree: &UiTree) {
212 self.tab_containers.clear();
213
214 let all_tabs = tree.find_widgets_with_layout::<DockTabs>();
215 for (node_id, layout) in all_tabs {
216 let tab_count = tree
217 .get_widget(node_id)
218 .and_then(|w| w.as_any().downcast_ref::<DockTabs>())
219 .map(|t| t.tab_count())
220 .unwrap_or(0);
221
222 self.tab_containers
223 .insert(node_id, CachedContainerInfo { layout, tab_count });
224 }
225
226 self.cache_dirty = false;
227 }
228
229 pub fn find_tab_containers(&mut self, tree: &UiTree) -> &HashMap<NodeId, CachedContainerInfo> {
231 if self.cache_dirty {
232 self.rebuild_cache(tree);
233 }
234 &self.tab_containers
235 }
236
237 pub fn is_dirty(&self) -> bool {
239 self.cache_dirty
240 }
241
242 pub fn container_count(&self) -> usize {
244 self.tab_containers.len()
245 }
246}
247
248impl Default for DockingContext {
249 fn default() -> Self {
250 Self::new()
251 }
252}