1use egui::{
2 Color32, CursorIcon, Painter, Pos2, Rect, Response, Sense, Stroke, StrokeKind, Ui, Vec2,
3};
4
5use crate::TitleBar;
6
7#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum WindowControlIcon {
10 Close,
12 Maximize,
14 Restore,
16 Minimize,
18}
19
20impl TitleBar {
21 fn draw_close_icon(&self, painter: &egui::Painter, rect: Rect, color: Color32) {
30 let center = rect.center();
31 let size = rect.width().min(rect.height()) * 0.6;
32 let half_size = size / 2.0;
33
34 let stroke = Stroke::new(1.5, color);
35 painter.line_segment(
36 [
37 center + Vec2::new(-half_size, -half_size),
38 center + Vec2::new(half_size, half_size),
39 ],
40 stroke,
41 );
42 painter.line_segment(
43 [
44 center + Vec2::new(half_size, -half_size),
45 center + Vec2::new(-half_size, half_size),
46 ],
47 stroke,
48 );
49 }
50
51 fn draw_maximize_icon(&self, painter: &Painter, rect: egui::Rect, color: Color32) {
60 let center = rect.center();
61 let size = rect.width().min(rect.height()) * 0.75;
62 let stroke = Stroke::new(1.5, color);
63 let square_rect = Rect::from_center_size(center, Vec2::new(size, size));
64 painter.rect_stroke(square_rect, 0.0, stroke, StrokeKind::Inside);
65 }
66
67 fn draw_restore_icon(&self, painter: &Painter, rect: Rect, color: Color32) {
77 let button_size = rect.width().min(rect.height());
78 let square_size = button_size * 0.85;
79 let icon_rect = Rect::from_center_size(rect.center(), Vec2::new(square_size, square_size));
80
81 let center = icon_rect.center();
82 let half_size = square_size / 2.0;
83
84 let stroke = Stroke::new(1.5, color);
85
86 let main_square_size = square_size * 0.7;
87 let main_square_center = center + Vec2::new(-half_size * 0.2, 0.0);
88 let main_square = Rect::from_center_size(
89 main_square_center,
90 Vec2::new(main_square_size, main_square_size),
91 );
92 painter.rect_stroke(main_square, 0.0, stroke, StrokeKind::Inside);
93
94 let spacing = half_size * 0.12;
95
96 let horizontal_start = center + Vec2::new(-half_size * 0.3, -half_size + spacing);
97 let horizontal_end = center + Vec2::new(half_size - spacing, -half_size + spacing);
98
99 let vertical_start = center + Vec2::new(half_size - spacing, -half_size + spacing);
100 let vertical_end = center + Vec2::new(half_size - spacing, half_size * 0.2);
101
102 painter.line_segment([horizontal_start, horizontal_end], stroke);
103 painter.line_segment([vertical_start, vertical_end], stroke);
104 }
105
106 fn draw_minimize_icon(&self, painter: &Painter, rect: Rect, color: Color32) {
115 let center = rect.center();
116 let size = rect.width().min(rect.height()) * 0.8;
117 let half_size = size / 2.0;
118
119 let stroke = Stroke::new(2.0, color);
120 painter.line_segment(
121 [
122 center + Vec2::new(-half_size, 0.0),
123 center + Vec2::new(half_size, 0.0),
124 ],
125 stroke,
126 );
127 }
128
129 pub fn render_traffic_light(&self, ui: &mut Ui, color: Color32, size: f32) -> egui::Response {
131 let button_size = Vec2::new(size, size);
132 let (button_id, button_rect) = ui.allocate_space(button_size);
133
134 let y_center = 14.0;
135 let centered_pos = Pos2::new(button_rect.center().x, y_center);
136
137 ui.painter().circle_filled(centered_pos, size / 2.0, color);
138 ui.painter().circle_stroke(
139 centered_pos,
140 size / 2.0,
141 Stroke::new(0.5, Color32::from_rgba_premultiplied(0, 0, 0, 30)),
142 );
143
144 let centered_rect = Rect::from_center_size(centered_pos, button_size);
145 let response = ui.interact(centered_rect, button_id, Sense::click());
146
147 if response.hovered() {
148 ui.ctx().set_cursor_icon(CursorIcon::PointingHand);
149 }
150
151 response
152 }
153
154 pub fn render_window_control_button_with_drawn_icon(
169 &self,
170 ui: &mut Ui,
171 icon_type: WindowControlIcon,
172 hover_color: Color32,
173 icon_color: Color32,
174 icon_size: f32,
175 ) -> Response {
176 let desired_size = Vec2::new(46.0, 32.0);
177 let (rect, response) = ui.allocate_exact_size(desired_size, Sense::click());
178
179 if response.hovered() {
180 ui.painter().rect_filled(rect, 2.0, hover_color);
181 ui.ctx().set_cursor_icon(egui::CursorIcon::PointingHand);
182 }
183
184 let icon_rect = Rect::from_center_size(rect.center(), Vec2::new(icon_size, icon_size));
185
186 let final_icon_color = if response.hovered() && hover_color == self.close_hover_color {
187 Color32::WHITE
188 } else {
189 icon_color
190 };
191
192 match icon_type {
193 WindowControlIcon::Close => {
194 self.draw_close_icon(ui.painter(), icon_rect, final_icon_color)
195 }
196 WindowControlIcon::Maximize => {
197 self.draw_maximize_icon(ui.painter(), icon_rect, final_icon_color)
198 }
199 WindowControlIcon::Restore => {
200 self.draw_restore_icon(ui.painter(), icon_rect, final_icon_color)
201 }
202 WindowControlIcon::Minimize => {
203 self.draw_minimize_icon(ui.painter(), icon_rect, final_icon_color)
204 }
205 }
206
207 response
208 }
209}