1use crate::{
2 elements::*,
3 fonts::TextStyle,
4 geometry::{rect::RectF, vector::Vector2F},
5 Action, ElementBox, 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(keystroke.to_string(), self.text_style.clone())
44 .contained()
45 .with_style(self.container_style)
46 .boxed()
47 }))
48 .boxed()
49 } else {
50 Empty::new().collapsed().boxed()
51 };
52
53 let size = element.layout(constraint, cx);
54 (size, element)
55 }
56
57 fn paint(
58 &mut self,
59 bounds: RectF,
60 visible_bounds: RectF,
61 element: &mut ElementBox,
62 cx: &mut PaintContext,
63 ) {
64 element.paint(bounds.origin(), visible_bounds, cx);
65 }
66
67 fn rect_for_text_range(
68 &self,
69 _: Range<usize>,
70 _: RectF,
71 _: RectF,
72 _: &Self::LayoutState,
73 _: &Self::PaintState,
74 _: &MeasurementContext,
75 ) -> Option<RectF> {
76 None
77 }
78
79 fn debug(
80 &self,
81 _: RectF,
82 element: &ElementBox,
83 _: &(),
84 cx: &crate::DebugContext,
85 ) -> serde_json::Value {
86 json!({
87 "type": "KeystrokeLabel",
88 "action": self.action.name(),
89 "child": element.debug(cx)
90 })
91 }
92}