pfx_editor_style/widgets/
keycap.rs1use egui::{Align2, CornerRadius, Response, Sense, Stroke, StrokeKind, Ui, Vec2, Widget};
2
3use super::State;
4use crate::theme::Theme;
5
6pub struct KeyCap<'a> {
7 key: &'a str,
8 lit: bool,
9 button: bool,
10}
11
12impl<'a> KeyCap<'a> {
13 pub fn new(key: &'a str) -> KeyCap<'a> {
14 KeyCap {
15 key,
16 lit: false,
17 button: false,
18 }
19 }
20
21 pub fn lit(mut self, lit: bool) -> KeyCap<'a> {
22 self.lit = lit;
23 self
24 }
25
26 pub fn button(mut self) -> KeyCap<'a> {
27 self.button = true;
28 self
29 }
30}
31
32impl Widget for KeyCap<'_> {
33 fn ui(self, ui: &mut Ui) -> Response {
34 let theme = Theme::of(ui.ctx());
35 let key_font = theme.font(theme.size_code);
36 let width = ui
37 .painter()
38 .layout_no_wrap(self.key.into(), key_font.clone(), theme.text)
39 .size()
40 .x;
41 let size = Vec2::new((width + 10.0).round().max(18.0), 17.0);
42 let sense = if self.button {
43 Sense::click()
44 } else {
45 Sense::hover()
46 };
47 let (rect, response) = ui.allocate_exact_size(size, sense);
48 if !ui.is_rect_visible(rect) {
49 return response;
50 }
51 let state = if self.button {
52 State::of(&response, self.lit)
53 } else if self.lit {
54 State::Active
55 } else {
56 State::Rest
57 };
58 let (fill, border, text) = match state {
59 State::Rest if !ui.is_enabled() => (theme.surface, theme.line, theme.dim),
60 State::Rest => (theme.surface, theme.line, theme.text),
61 State::Hovered => (theme.accent_deep, theme.accent, theme.text),
62 State::Active => (theme.accent_bright, theme.accent_bright, theme.on_accent),
63 };
64 let painter = ui.painter();
65 painter.rect(
66 rect,
67 CornerRadius::same(theme.radius),
68 fill,
69 Stroke::new(theme.stroke, border),
70 StrokeKind::Inside,
71 );
72 painter.hline(
73 rect.x_range().shrink(1.0),
74 rect.bottom() - 1.5,
75 Stroke::new(
76 theme.stroke,
77 if state == State::Active {
78 theme.accent_bright
79 } else {
80 border
81 },
82 ),
83 );
84 painter.text(
85 rect.center() - Vec2::new(0.0, 0.5),
86 Align2::CENTER_CENTER,
87 self.key,
88 key_font,
89 text,
90 );
91 response
92 }
93}