Skip to main content

danceinterpreter_rs/ui/widget/
power_button.rs

1use iced::mouse::Cursor;
2use iced::widget::canvas;
3use iced::widget::canvas::{Frame, LineCap, Path, Stroke};
4use iced::{Point, Radians, Rectangle, Theme};
5use std::f32::consts::PI;
6
7pub fn draw(theme: &Theme, frame: &mut Frame, _bounds: Rectangle, _cursor: Cursor, enabled: bool) {
8    let size = frame.size();
9    let cx = size.width / 2.0;
10    let cy = size.height / 2.0;
11    let center = Point::new(cx, cy);
12
13    // Scale everything relative to the smaller dimension
14    let dim = size.width.min(size.height);
15    let bg_r = dim * 0.46; // background circle radius
16    let arc_r = dim * 0.30; // power arc radius
17    let stroke_w = dim * 0.07;
18
19    // Colors
20    let (icon_color, bg_color) = if enabled {
21        (
22            theme.extended_palette().primary.base.color,
23            theme.extended_palette().background.weaker.color,
24        )
25    } else {
26        (
27            theme.extended_palette().secondary.base.color,
28            theme.extended_palette().background.weaker.color,
29        )
30    };
31
32    let bg_path = Path::new(|b| b.circle(center, bg_r));
33    frame.fill(
34        &bg_path,
35        canvas::Fill {
36            style: canvas::Style::Solid(bg_color),
37            ..canvas::Fill::default()
38        },
39    );
40
41    // Power arc
42    // Gap of 70° centered at the top (-π/2 in screen coords).
43    // Arc drawn from right edge of gap → clockwise around → left edge of gap.
44    let gap_half = 35.0_f32.to_radians(); // half the gap angle
45    let top = -PI / 2.0; // top of circle (-90°)
46    let start = top + gap_half; // right side of gap  ≈ -55°
47    let end = top - gap_half + 2.0 * PI; // left side of gap   ≈ 235° (going all the way around)
48
49    let arc = Path::new(|b| {
50        b.arc(canvas::path::Arc {
51            center,
52            radius: arc_r,
53            start_angle: Radians(start),
54            end_angle: Radians(end),
55        });
56    });
57
58    frame.stroke(
59        &arc,
60        Stroke::default()
61            .with_color(icon_color)
62            .with_width(stroke_w)
63            .with_line_cap(LineCap::Butt),
64    );
65
66    // Power line (vertical, through the gap)
67    // Runs from ~20% inside the radius up to the circumference.
68    let line = Path::new(|b| {
69        b.move_to(Point::new(cx, cy - arc_r * 0.18));
70        b.line_to(Point::new(cx, cy - arc_r));
71    });
72
73    frame.stroke(
74        &line,
75        Stroke::default()
76            .with_color(icon_color)
77            .with_width(stroke_w)
78            .with_line_cap(LineCap::Butt),
79    );
80}