Rust · 5250 bytes Raw Blame History
1 //! Custom SVG-style icons rendered with Cairo
2 //!
3 //! Clean, minimal icon designs for power controls.
4
5 use cairo::Context;
6 use std::f64::consts::PI;
7
8 /// Icon size (icons are designed for this size and scale proportionally)
9 pub const ICON_SIZE: f64 = 24.0;
10
11 /// Draw a power/shutdown icon
12 /// A circle with a vertical line at the top (power symbol)
13 pub fn draw_power(ctx: &Context, x: f64, y: f64, size: f64) {
14 let scale = size / ICON_SIZE;
15 let cx = x + size / 2.0;
16 let cy = y + size / 2.0;
17 let radius = 9.0 * scale;
18 let stroke_width = 2.0 * scale;
19
20 ctx.set_line_width(stroke_width);
21 ctx.set_line_cap(cairo::LineCap::Round);
22
23 // Circle (arc from ~60° to ~300°, leaving gap at top)
24 let gap_angle = PI / 6.0; // 30 degrees gap on each side of top
25 ctx.arc(cx, cy, radius, PI / 2.0 + gap_angle, 5.0 * PI / 2.0 - gap_angle);
26 ctx.stroke().ok();
27
28 // Vertical line from top (outside) going down toward center
29 ctx.move_to(cx, cy - radius - stroke_width); // Start above the circle gap
30 ctx.line_to(cx, cy); // Go down to center
31 ctx.stroke().ok();
32 }
33
34 /// Draw a reboot/restart icon
35 /// Two curved arrows forming a circle
36 pub fn draw_reboot(ctx: &Context, x: f64, y: f64, size: f64) {
37 let scale = size / ICON_SIZE;
38 let cx = x + size / 2.0;
39 let cy = y + size / 2.0;
40 let radius = 8.0 * scale;
41 let stroke_width = 2.0 * scale;
42 let arrow_size = 4.0 * scale;
43
44 ctx.set_line_width(stroke_width);
45 ctx.set_line_cap(cairo::LineCap::Round);
46 ctx.set_line_join(cairo::LineJoin::Round);
47
48 // Top arc (right side, going clockwise)
49 ctx.arc(cx, cy, radius, -PI * 0.75, PI * 0.1);
50 ctx.stroke().ok();
51
52 // Top arrow head (pointing right/down)
53 let arrow_x = cx + radius * (PI * 0.1).cos();
54 let arrow_y = cy + radius * (PI * 0.1).sin();
55 ctx.move_to(arrow_x - arrow_size, arrow_y - arrow_size * 0.5);
56 ctx.line_to(arrow_x, arrow_y);
57 ctx.line_to(arrow_x - arrow_size * 0.5, arrow_y + arrow_size);
58 ctx.stroke().ok();
59
60 // Bottom arc (left side, going clockwise)
61 ctx.arc(cx, cy, radius, PI * 0.25, PI * 1.1);
62 ctx.stroke().ok();
63
64 // Bottom arrow head (pointing left/up)
65 let arrow_x = cx + radius * (PI * 1.1).cos();
66 let arrow_y = cy + radius * (PI * 1.1).sin();
67 ctx.move_to(arrow_x + arrow_size, arrow_y + arrow_size * 0.5);
68 ctx.line_to(arrow_x, arrow_y);
69 ctx.line_to(arrow_x + arrow_size * 0.5, arrow_y - arrow_size);
70 ctx.stroke().ok();
71 }
72
73 /// Draw a suspend/sleep icon
74 /// A crescent moon
75 pub fn draw_suspend(ctx: &Context, x: f64, y: f64, size: f64) {
76 let scale = size / ICON_SIZE;
77 let cx = x + size / 2.0;
78 let cy = y + size / 2.0;
79 let outer_radius = 9.0 * scale;
80 let inner_radius = 7.0 * scale;
81 let offset = 4.0 * scale; // How much the inner circle is offset
82
83 // Create crescent by subtracting inner circle from outer
84 // Outer circle (full moon)
85 ctx.arc(cx, cy, outer_radius, 0.0, 2.0 * PI);
86
87 // Inner circle (shadow) - offset to create crescent
88 ctx.arc_negative(cx + offset, cy - offset * 0.3, inner_radius, 2.0 * PI, 0.0);
89
90 ctx.fill().ok();
91 }
92
93 /// Draw a dropdown/chevron icon
94 /// A simple downward-pointing chevron
95 pub fn draw_chevron_down(ctx: &Context, x: f64, y: f64, size: f64) {
96 let scale = size / ICON_SIZE;
97 let cx = x + size / 2.0;
98 let cy = y + size / 2.0;
99 let half_width = 5.0 * scale;
100 let half_height = 3.0 * scale;
101 let stroke_width = 2.0 * scale;
102
103 ctx.set_line_width(stroke_width);
104 ctx.set_line_cap(cairo::LineCap::Round);
105 ctx.set_line_join(cairo::LineJoin::Round);
106
107 ctx.move_to(cx - half_width, cy - half_height);
108 ctx.line_to(cx, cy + half_height);
109 ctx.line_to(cx + half_width, cy - half_height);
110 ctx.stroke().ok();
111 }
112
113 /// Draw a checkmark icon (for selected session)
114 pub fn draw_checkmark(ctx: &Context, x: f64, y: f64, size: f64) {
115 let scale = size / ICON_SIZE;
116 let stroke_width = 2.5 * scale;
117
118 ctx.set_line_width(stroke_width);
119 ctx.set_line_cap(cairo::LineCap::Round);
120 ctx.set_line_join(cairo::LineJoin::Round);
121
122 // Checkmark shape
123 ctx.move_to(x + 4.0 * scale, y + 12.0 * scale);
124 ctx.line_to(x + 9.0 * scale, y + 17.0 * scale);
125 ctx.line_to(x + 20.0 * scale, y + 6.0 * scale);
126 ctx.stroke().ok();
127 }
128
129 /// Draw a user/person icon
130 pub fn draw_user(ctx: &Context, x: f64, y: f64, size: f64) {
131 let scale = size / ICON_SIZE;
132 let cx = x + size / 2.0;
133 let cy = y + size / 2.0;
134
135 // Head (circle)
136 let head_radius = 5.0 * scale;
137 let head_y = cy - 3.0 * scale;
138 ctx.arc(cx, head_y, head_radius, 0.0, 2.0 * PI);
139 ctx.fill().ok();
140
141 // Body (rounded rectangle / shoulders)
142 let body_width = 14.0 * scale;
143 let body_height = 8.0 * scale;
144 let body_y = cy + 4.0 * scale;
145 let body_radius = 4.0 * scale;
146
147 ctx.new_sub_path();
148 ctx.arc(cx - body_width / 2.0 + body_radius, body_y + body_radius, body_radius, PI, 1.5 * PI);
149 ctx.arc(cx + body_width / 2.0 - body_radius, body_y + body_radius, body_radius, 1.5 * PI, 2.0 * PI);
150 ctx.line_to(cx + body_width / 2.0, body_y + body_height);
151 ctx.line_to(cx - body_width / 2.0, body_y + body_height);
152 ctx.close_path();
153 ctx.fill().ok();
154 }
155