cadmus_core/view/calculator/
bottom_bar.rs

1use crate::color::WHITE;
2use crate::context::Context;
3use crate::font::Fonts;
4use crate::framebuffer::Framebuffer;
5use crate::geom::{divide, Rectangle};
6use crate::gesture::GestureEvent;
7use crate::input::DeviceEvent;
8use crate::view::filler::Filler;
9use crate::view::labeled_icon::LabeledIcon;
10use crate::view::{Bus, Event, Hub, Id, RenderQueue, View, ViewId, ID_FEEDER};
11
12pub struct BottomBar {
13    id: Id,
14    rect: Rectangle,
15    children: Vec<Box<dyn View>>,
16}
17
18impl BottomBar {
19    pub fn new(rect: Rectangle, margin_width: i32, font_size: f32) -> BottomBar {
20        let id = ID_FEEDER.next();
21        let mut children = Vec::new();
22        let labelled_icon_width = 5 * rect.height() as i32 / 2;
23        let paddings = divide(rect.width() as i32 - 2 * labelled_icon_width, 3);
24
25        let mut x_offset = rect.min.x;
26        let filler = Filler::new(
27            rect![x_offset, rect.min.y, x_offset + paddings[0], rect.max.y],
28            WHITE,
29        );
30        x_offset += paddings[0];
31        children.push(Box::new(filler) as Box<dyn View>);
32
33        let margin_width_rect = rect![
34            x_offset,
35            rect.min.y,
36            x_offset + labelled_icon_width,
37            rect.max.y
38        ];
39        let margin_width_icon = LabeledIcon::new(
40            "margin",
41            margin_width_rect,
42            Event::ToggleNear(ViewId::MarginWidthMenu, margin_width_rect),
43            format!("{} mm", margin_width),
44        );
45        children.push(Box::new(margin_width_icon) as Box<dyn View>);
46        x_offset += labelled_icon_width;
47
48        let filler = Filler::new(
49            rect![x_offset, rect.min.y, x_offset + paddings[1], rect.max.y],
50            WHITE,
51        );
52        children.push(Box::new(filler) as Box<dyn View>);
53        x_offset += paddings[1];
54
55        let font_size_rect = rect![
56            x_offset,
57            rect.min.y,
58            x_offset + labelled_icon_width,
59            rect.max.y
60        ];
61        let font_size_icon = LabeledIcon::new(
62            "font_size",
63            font_size_rect,
64            Event::ToggleNear(ViewId::FontSizeMenu, font_size_rect),
65            format!("{:.1} pt", font_size),
66        );
67        children.push(Box::new(font_size_icon) as Box<dyn View>);
68        x_offset += labelled_icon_width;
69
70        let filler = Filler::new(
71            rect![x_offset, rect.min.y, x_offset + paddings[2], rect.max.y],
72            WHITE,
73        );
74        children.push(Box::new(filler) as Box<dyn View>);
75
76        BottomBar { id, rect, children }
77    }
78
79    pub fn update_font_size(&mut self, font_size: f32, rq: &mut RenderQueue) {
80        if let Some(labeled_icon) = self.children[3].downcast_mut::<LabeledIcon>() {
81            labeled_icon.update(&format!("{:.1} pt", font_size), rq);
82        }
83    }
84
85    pub fn update_margin_width(&mut self, margin_width: i32, rq: &mut RenderQueue) {
86        if let Some(labeled_icon) = self.children[1].downcast_mut::<LabeledIcon>() {
87            labeled_icon.update(&format!("{} mm", margin_width), rq);
88        }
89    }
90}
91
92impl View for BottomBar {
93    #[cfg_attr(feature = "otel", tracing::instrument(skip(self, _hub, _bus, _rq, _context), fields(event = ?evt), ret(level=tracing::Level::TRACE)))]
94    fn handle_event(
95        &mut self,
96        evt: &Event,
97        _hub: &Hub,
98        _bus: &mut Bus,
99        _rq: &mut RenderQueue,
100        _context: &mut Context,
101    ) -> bool {
102        match *evt {
103            Event::Gesture(GestureEvent::Tap(center))
104            | Event::Gesture(GestureEvent::HoldFingerShort(center, ..))
105                if self.rect.includes(center) =>
106            {
107                true
108            }
109            Event::Gesture(GestureEvent::Swipe { start, .. }) if self.rect.includes(start) => true,
110            Event::Device(DeviceEvent::Finger { position, .. }) if self.rect.includes(position) => {
111                true
112            }
113            _ => false,
114        }
115    }
116
117    #[cfg_attr(feature = "otel", tracing::instrument(skip(self, _fb, _fonts, _rect), fields(rect = ?_rect)))]
118    fn render(&self, _fb: &mut dyn Framebuffer, _rect: Rectangle, _fonts: &mut Fonts) {}
119
120    fn resize(&mut self, rect: Rectangle, hub: &Hub, rq: &mut RenderQueue, context: &mut Context) {
121        let labelled_icon_width = 5 * rect.height() as i32 / 2;
122        let paddings = divide(rect.width() as i32 - 2 * labelled_icon_width, 3);
123
124        let mut x_offset = rect.min.x;
125
126        let filr_rect = rect![x_offset, rect.min.y, x_offset + paddings[0], rect.max.y];
127        self.children[0].resize(filr_rect, hub, rq, context);
128        x_offset += paddings[0];
129
130        let margin_width_rect = rect![
131            x_offset,
132            rect.min.y,
133            x_offset + labelled_icon_width,
134            rect.max.y
135        ];
136        self.children[1].resize(margin_width_rect, hub, rq, context);
137        x_offset += labelled_icon_width;
138
139        let filr_rect = rect![x_offset, rect.min.y, x_offset + paddings[1], rect.max.y];
140        self.children[2].resize(filr_rect, hub, rq, context);
141        x_offset += paddings[1];
142
143        let font_size_rect = rect![
144            x_offset,
145            rect.min.y,
146            x_offset + labelled_icon_width,
147            rect.max.y
148        ];
149        self.children[3].resize(font_size_rect, hub, rq, context);
150        x_offset += labelled_icon_width;
151
152        let filr_rect = rect![x_offset, rect.min.y, x_offset + paddings[2], rect.max.y];
153        self.children[4].resize(filr_rect, hub, rq, context);
154
155        self.rect = rect;
156    }
157
158    fn rect(&self) -> &Rectangle {
159        &self.rect
160    }
161
162    fn rect_mut(&mut self) -> &mut Rectangle {
163        &mut self.rect
164    }
165
166    fn children(&self) -> &Vec<Box<dyn View>> {
167        &self.children
168    }
169
170    fn children_mut(&mut self) -> &mut Vec<Box<dyn View>> {
171        &mut self.children
172    }
173
174    fn id(&self) -> Id {
175        self.id
176    }
177}