graphic design tool
git clone https://git.lucas.co/cce-designer.git
src/panes.rs (3.5K)
1 //! The window's pane geometry: the three resizable columns and their splitters
2 //! (`SplitterLayout`), and the circular network pane's hit zones
3 //! (`CircularPaneLayout`). Plain arithmetic over rects and points. Moved from
4 //! cce-ui's `layout` (2026-10-08), where the designer was its only user.
5
6 pub struct SplitterLayout {
7 pub splitter1_x: f32,
8 pub splitter2_x: f32,
9 pub splitter_width: f32,
10 pub min_column_width: f32,
11 }
12
13 impl SplitterLayout {
14 pub fn new(width: f32, splitter_width: f32, min_column_width: f32) -> Self {
15 let s1 = (width - 2.0 * splitter_width) / 3.0;
16 let s2 = s1 + splitter_width + (width - 2.0 * splitter_width) / 3.0;
17 Self {
18 splitter1_x: s1,
19 splitter2_x: s2,
20 splitter_width,
21 min_column_width,
22 }
23 }
24
25 pub fn clamp(&mut self, total_width: f32, detached_circular_network: bool) {
26 if detached_circular_network {
27 let min_s2 = self.min_column_width;
28 let max_s2 = (total_width - self.min_column_width).max(min_s2);
29 self.splitter2_x = self.splitter2_x.clamp(min_s2, max_s2);
30 } else {
31 let min_s1 = self.min_column_width;
32 let max_s1 = (self.splitter2_x - self.splitter_width - self.min_column_width).max(min_s1);
33 self.splitter1_x = self.splitter1_x.clamp(min_s1, max_s1);
34 let min_s2 = self.splitter1_x + self.splitter_width + self.min_column_width;
35 let max_s2 = (total_width - self.min_column_width).max(min_s2);
36 self.splitter2_x = self.splitter2_x.clamp(min_s2, max_s2);
37 }
38 }
39
40 pub fn scale(&mut self, factor: f32) {
41 self.splitter1_x *= factor;
42 self.splitter2_x *= factor;
43 }
44
45 pub fn left_col(&self) -> (f32, f32) { // (x, width)
46 (0.0, self.splitter1_x)
47 }
48
49 pub fn center_col(&self) -> (f32, f32) { // (x, width)
50 let x = self.splitter1_x + self.splitter_width;
51 (x, self.splitter2_x - x)
52 }
53
54 pub fn right_col(&self, total_width: f32) -> (f32, f32) { // (x, width)
55 let x = self.splitter2_x + self.splitter_width;
56 (x, (total_width - x).max(0.0))
57 }
58 }
59
60 pub struct CircularPaneLayout {
61 pub x: f32,
62 pub y: f32,
63 pub r: f32,
64 }
65
66 impl CircularPaneLayout {
67 pub fn new(x: f32, y: f32, r: f32) -> Self {
68 Self { x, y, r }
69 }
70
71 pub fn hit_test_content(&self, cx: f32, cy: f32, menubar_h: f32, breadcrumb_h: f32) -> bool {
72 let dx = cx - self.x;
73 let dy = cy - self.y;
74 let dist_sq = dx * dx + dy * dy;
75 dist_sq <= self.r * self.r && cy >= self.y - self.r + 45.0 + menubar_h + breadcrumb_h
76 }
77
78 pub fn hit_test_menubar(&self, cx: f32, cy: f32, menubar_h: f32) -> bool {
79 let dx = cx - self.x;
80 let dy = cy - self.y;
81 let dist = (dx * dx + dy * dy).sqrt();
82 dist >= self.r - menubar_h && dist <= self.r && cy < self.y
83 }
84
85 pub fn hit_test_breadcrumb(&self, cx: f32, cy: f32, menubar_h: f32, breadcrumb_h: f32) -> bool {
86 let dx = cx - self.x;
87 let dy = cy - self.y;
88 let dist_sq = dx * dx + dy * dy;
89 dist_sq <= self.r * self.r && cy >= self.y - self.r + menubar_h && cy < self.y - self.r + 45.0 + menubar_h + breadcrumb_h
90 }
91
92 pub fn hit_test_border(&self, cx: f32, cy: f32, border_thickness: f32) -> bool {
93 let dx = cx - self.x;
94 let dy = cy - self.y;
95 let dist = (dx * dx + dy * dy).sqrt();
96 dist >= self.r - border_thickness && dist <= self.r
97 }
98 }