Skip to main content

danceinterpreter_rs/ui/widget/
restart_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    let dim = size.width.min(size.height);
13    let bg_r = dim * 0.46;
14    let arc_r = dim * 0.30;
15    let stroke_w = dim * 0.07;
16    let arrow_size = dim * 0.13;
17
18    // secondary color when enabled; muted background-strong when disabled
19    let (icon_color, bg_color) = if enabled {
20        (
21            theme.extended_palette().secondary.base.color,
22            theme.extended_palette().background.weaker.color,
23        )
24    } else {
25        (
26            theme.extended_palette().background.strongest.color,
27            theme.extended_palette().background.weaker.color,
28        )
29    };
30
31    // Background circle
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    // Restart arc
42    // 300° clockwise arc, 60° gap left from the top.
43    let gap = 30.0_f32.to_radians();
44    let bot = PI / 2.0;
45    let top = -bot;
46    let arc_start = top - gap / 2.0;
47    let arc_cut_start = bot - gap / 4.0;
48    let arc_cut_end = bot + gap / 4.0;
49    let arc_end = top - 1.25 * gap + 2.0 * PI; // 300°  (clockwise, long way round)
50
51    let arc = Path::new(|b| {
52        b.arc(canvas::path::Arc {
53            center,
54            radius: arc_r,
55            start_angle: Radians(arc_start),
56            end_angle: Radians(arc_cut_start),
57        });
58        b.arc(canvas::path::Arc {
59            center,
60            radius: arc_r,
61            start_angle: Radians(arc_cut_end),
62            end_angle: Radians(arc_end),
63        });
64    });
65    frame.stroke(
66        &arc,
67        Stroke::default()
68            .with_color(icon_color)
69            .with_width(stroke_w)
70            .with_line_cap(LineCap::Butt),
71    );
72
73    let end_x = cx - gap * 16.0;
74    let end_y = cy - arc_r;
75
76    // Two wings ±45° from the back direction
77    let (s, c) = 45.0_f32.to_radians().sin_cos();
78    let w1 = (-c, -s); // rotate +45°
79    let w2 = (-c, s); // rotate -45°
80
81    let tip = Point::new(end_x, end_y);
82    let p1 = Point::new(end_x - w1.0 * arrow_size, end_y + w1.1 * arrow_size);
83    let p2 = Point::new(end_x - w2.0 * arrow_size, end_y + w2.1 * arrow_size);
84
85    let arrowhead = Path::new(|b| {
86        b.move_to(p1);
87        b.line_to(tip);
88        b.line_to(p2);
89    });
90    frame.stroke(
91        &arrowhead,
92        Stroke::default()
93            .with_color(icon_color)
94            .with_width(stroke_w * 0.75)
95            .with_line_cap(LineCap::Butt),
96    );
97}