git.lucas.co / cce-designer
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 }