1use crate::{
2 elements::*,
3 fonts::TextStyle,
4 geometry::{rect::RectF, vector::Vector2F},
5 Action, ElementBox, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
6};
7use serde_json::json;
8
9use super::ContainerStyle;
10
11pub struct KeystrokeLabel {
12 action: Box<dyn Action>,
13 container_style: ContainerStyle,
14 text_style: TextStyle,
15}
16
17impl KeystrokeLabel {
18 pub fn new(
19 action: Box<dyn Action>,
20 container_style: ContainerStyle,
21 text_style: TextStyle,
22 ) -> Self {
23 Self {
24 action,
25 container_style,
26 text_style,
27 }
28 }
29}
30
31impl Element for KeystrokeLabel {
32 type LayoutState = ElementBox;
33 type PaintState = ();
34
35 fn layout(
36 &mut self,
37 constraint: SizeConstraint,
38 cx: &mut LayoutContext,
39 ) -> (Vector2F, ElementBox) {
40 let mut element = if let Some(keystrokes) = cx.keystrokes_for_action(self.action.as_ref()) {
41 Flex::row()
42 .with_children(keystrokes.iter().map(|keystroke| {
43 Label::new(
44 keystroke.to_string().to_uppercase(),
45 self.text_style.clone(),
46 )
47 .contained()
48 .with_style(self.container_style)
49 .boxed()
50 }))
51 .boxed()
52 } else {
53 Empty::new().collapsed().boxed()
54 };
55
56 let size = element.layout(constraint, cx);
57 (size, element)
58 }
59
60 fn paint(
61 &mut self,
62 bounds: RectF,
63 visible_bounds: RectF,
64 element: &mut ElementBox,
65 cx: &mut PaintContext,
66 ) {
67 element.paint(bounds.origin(), visible_bounds, cx);
68 }
69
70 fn dispatch_event(
71 &mut self,
72 event: &Event,
73 _: RectF,
74 _: RectF,
75 element: &mut ElementBox,
76 _: &mut (),
77 cx: &mut EventContext,
78 ) -> bool {
79 element.dispatch_event(event, cx)
80 }
81
82 fn debug(
83 &self,
84 _: RectF,
85 element: &ElementBox,
86 _: &(),
87 cx: &crate::DebugContext,
88 ) -> serde_json::Value {
89 json!({
90 "type": "KeystrokeLabel",
91 "action": self.action.name(),
92 "child": element.debug(cx)
93 })
94 }
95}