egui_macview/controls/
toggle.rs1use crate::theme::MacTheme;
6use egui::{Color32, CornerRadius, Pos2, Response, Stroke, StrokeKind, Ui, Vec2, Widget};
7
8pub struct MacToggle<'a> {
28 value: &'a mut bool,
29 theme: Option<&'a MacTheme>,
30}
31
32impl<'a> MacToggle<'a> {
33 pub fn new(value: &'a mut bool) -> Self {
35 Self { value, theme: None }
36 }
37
38 pub fn theme(mut self, theme: &'a MacTheme) -> Self {
40 self.theme = Some(theme);
41 self
42 }
43}
44
45impl<'a> Widget for MacToggle<'a> {
46 fn ui(self, ui: &mut Ui) -> Response {
47 let fallback_theme;
48 let theme = match self.theme {
49 Some(t) => t,
50 None => {
51 fallback_theme = MacTheme::default();
52 &fallback_theme
53 }
54 };
55
56 let metrics = theme.toggle();
57 let height = metrics.height.points();
58 let width = metrics.width.points();
59 let radius = metrics.corner_radius.points() as u8;
60
61 let desired_size = Vec2::new(width, height);
62 let (rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click());
63 if response.clicked() {
64 *self.value = !*self.value;
65 response.mark_changed();
66 }
67
68 let anim_progress = ui.ctx().animate_bool_with_time(
69 response.id.with("toggle_anim"),
70 *self.value,
71 metrics.animation_duration.points(),
72 );
73
74 let painter = ui.painter_at(rect);
75 let bg_color = theme
76 .control()
77 .lerp_to_gamma(theme.system_green(), anim_progress);
78
79 painter.rect(
80 rect,
81 CornerRadius::same(radius),
82 bg_color,
83 Stroke::new(metrics.border_width.points(), theme.separator()),
84 StrokeKind::Inside,
85 );
86
87 let knob_radius = metrics.knob_size.points() * 0.5;
88 let x_off = rect.min.x + metrics.knob_offset_off.points() + knob_radius;
89 let x_on = rect.min.x + metrics.knob_offset_on.points() + knob_radius;
90 let knob_x = x_off + (x_on - x_off) * anim_progress;
91 let knob_center = Pos2::new(knob_x, rect.center().y);
92
93 painter.circle_filled(
95 knob_center + Vec2::new(0.0, 1.0),
96 knob_radius,
97 Color32::from_black_alpha(30),
98 );
99 painter.circle_filled(knob_center, knob_radius, Color32::WHITE);
100
101 response
102 }
103}