egui_macview/controls/
thumbnail_cell.rs1use crate::theme::MacTheme;
7use egui::{CornerRadius, Painter, Rect, Response, Stroke, StrokeKind, Ui, Vec2, Widget};
8
9pub type ThumbnailDrawer<'a> = Box<dyn FnOnce(&Painter, Rect) + 'a>;
11
12#[derive(Default)]
37pub struct MacThumbnailCell<'a> {
38 selected: bool,
39 theme: Option<&'a MacTheme>,
40 size: Option<Vec2>,
41 corner_radius: Option<f32>,
42 border_width: Option<f32>,
43 drawer: Option<ThumbnailDrawer<'a>>,
44}
45
46impl<'a> MacThumbnailCell<'a> {
47 pub fn new() -> Self {
49 Self::default()
50 }
51
52 pub fn selected(mut self, selected: bool) -> Self {
54 self.selected = selected;
55 self
56 }
57
58 pub fn theme(mut self, theme: &'a MacTheme) -> Self {
60 self.theme = Some(theme);
61 self
62 }
63
64 pub fn size(mut self, size: Vec2) -> Self {
66 self.size = Some(size);
67 self
68 }
69
70 pub fn square(mut self, side: f32) -> Self {
72 self.size = Some(Vec2::splat(side));
73 self
74 }
75
76 pub fn corner_radius(mut self, radius: f32) -> Self {
78 self.corner_radius = Some(radius);
79 self
80 }
81
82 pub fn border_width(mut self, width: f32) -> Self {
84 self.border_width = Some(width);
85 self
86 }
87
88 pub fn custom_draw(mut self, drawer: impl FnOnce(&Painter, Rect) + 'a) -> Self {
90 self.drawer = Some(Box::new(drawer));
91 self
92 }
93
94 pub fn show(self, ui: &mut Ui) -> Response {
96 self.ui(ui)
97 }
98
99 pub fn paint_in_rect(self, painter: &Painter, rect: Rect, hovered: bool) {
101 let theme_cow = MacTheme::resolve(self.theme, painter.ctx());
102 let theme: &MacTheme = &theme_cow;
103
104 let metrics = theme.thumbnail();
105 let corner_radius = self
106 .corner_radius
107 .unwrap_or_else(|| metrics.corner_radius.points());
108 let border_width = self
109 .border_width
110 .unwrap_or_else(|| metrics.border_width.points());
111
112 let bg_color = if self.selected {
113 theme.selected_control()
114 } else if hovered {
115 theme.control()
116 } else {
117 theme.control_background()
118 };
119
120 let stroke_color = if self.selected {
121 theme.control_accent()
122 } else {
123 theme.separator()
124 };
125
126 let border_stroke = Stroke::new(border_width, stroke_color);
127
128 painter.rect(
129 rect,
130 CornerRadius::same(corner_radius as u8),
131 bg_color,
132 border_stroke,
133 StrokeKind::Inside,
134 );
135
136 if let Some(drawer) = self.drawer {
137 let inner_rect = rect.shrink(border_width);
138 drawer(painter, inner_rect);
139 }
140 }
141}
142
143impl<'a> Widget for MacThumbnailCell<'a> {
144 fn ui(self, ui: &mut Ui) -> Response {
145 let theme_cow = MacTheme::resolve(self.theme, ui.ctx());
146 let theme: &MacTheme = &theme_cow;
147
148 let metrics = theme.thumbnail();
149 let default_side = metrics.size.points();
150 let size = self.size.unwrap_or_else(|| Vec2::splat(default_side));
151
152 let (rect, response) = ui.allocate_exact_size(size, egui::Sense::click());
153 let painter = ui.painter_at(rect);
154 let hovered = response.hovered();
155
156 self.paint_in_rect(&painter, rect, hovered);
157
158 response
159 }
160}