cadmus_core/view/calculator/
input_bar.rs

1use crate::color::{SEPARATOR_NORMAL, TEXT_BUMP_SMALL};
2use crate::context::Context;
3use crate::device::CURRENT_DEVICE;
4use crate::font::Fonts;
5use crate::framebuffer::Framebuffer;
6use crate::geom::{CycleDir, Rectangle};
7use crate::gesture::GestureEvent;
8use crate::input::DeviceEvent;
9use crate::unit::scale_by_dpi;
10use crate::view::filler::Filler;
11use crate::view::icon::Icon;
12use crate::view::input_field::InputField;
13use crate::view::{Bus, Event, Hub, Id, RenderQueue, View, ViewId, ID_FEEDER, THICKNESS_MEDIUM};
14
15pub struct InputBar {
16    id: Id,
17    pub rect: Rectangle,
18    children: Vec<Box<dyn View>>,
19}
20
21impl InputBar {
22    pub fn new(rect: Rectangle, placeholder: &str, text: &str, context: &mut Context) -> InputBar {
23        let id = ID_FEEDER.next();
24        let mut children = Vec::new();
25        let dpi = CURRENT_DEVICE.dpi;
26        let thickness = scale_by_dpi(THICKNESS_MEDIUM, dpi) as i32;
27        let side = rect.height() as i32;
28
29        let prev_icon = Icon::new(
30            "angle-up",
31            rect![rect.min, rect.min + side],
32            Event::History(CycleDir::Previous, false),
33        )
34        .background(TEXT_BUMP_SMALL[0]);
35        children.push(Box::new(prev_icon) as Box<dyn View>);
36
37        let separator = Filler::new(
38            rect![
39                pt!(rect.min.x + side, rect.min.y),
40                pt!(rect.min.x + side + thickness, rect.max.y)
41            ],
42            SEPARATOR_NORMAL,
43        );
44        children.push(Box::new(separator) as Box<dyn View>);
45
46        let input_field = InputField::new(
47            rect![
48                pt!(rect.min.x + side + thickness, rect.min.y),
49                pt!(rect.max.x - side - thickness, rect.max.y)
50            ],
51            ViewId::CalculatorInput,
52        )
53        .border(false)
54        .text(text, context)
55        .placeholder(placeholder);
56        children.push(Box::new(input_field) as Box<dyn View>);
57
58        let separator = Filler::new(
59            rect![
60                pt!(rect.max.x - side - thickness, rect.min.y),
61                pt!(rect.max.x - side, rect.max.y)
62            ],
63            SEPARATOR_NORMAL,
64        );
65        children.push(Box::new(separator) as Box<dyn View>);
66
67        let next_icon = Icon::new(
68            "angle-down",
69            rect![
70                pt!(rect.max.x - side, rect.min.y),
71                pt!(rect.max.x, rect.max.y)
72            ],
73            Event::History(CycleDir::Next, false),
74        )
75        .background(TEXT_BUMP_SMALL[0]);
76        children.push(Box::new(next_icon) as Box<dyn View>);
77
78        InputBar { id, rect, children }
79    }
80
81    pub fn set_text(
82        &mut self,
83        text: &str,
84        move_cursor: bool,
85        rq: &mut RenderQueue,
86        context: &mut Context,
87    ) {
88        if let Some(input_field) = self.children[2].downcast_mut::<InputField>() {
89            input_field.set_text(text, move_cursor, rq, context);
90        }
91    }
92
93    pub fn text_before_cursor(&self) -> &str {
94        self.children[2]
95            .downcast_ref::<InputField>()
96            .unwrap()
97            .text_before_cursor()
98    }
99}
100
101impl View for InputBar {
102    #[cfg_attr(feature = "otel", tracing::instrument(skip(self, _hub, _bus, _rq, _context), fields(event = ?evt), ret(level=tracing::Level::TRACE)))]
103    fn handle_event(
104        &mut self,
105        evt: &Event,
106        _hub: &Hub,
107        _bus: &mut Bus,
108        _rq: &mut RenderQueue,
109        _context: &mut Context,
110    ) -> bool {
111        match *evt {
112            Event::Gesture(GestureEvent::Tap(center))
113            | Event::Gesture(GestureEvent::HoldFingerShort(center, ..))
114                if self.rect.includes(center) =>
115            {
116                true
117            }
118            Event::Gesture(GestureEvent::Swipe { start, .. }) if self.rect.includes(start) => true,
119            Event::Device(DeviceEvent::Finger { position, .. }) if self.rect.includes(position) => {
120                true
121            }
122            _ => false,
123        }
124    }
125
126    #[cfg_attr(feature = "otel", tracing::instrument(skip(self, _fb, _fonts, _rect), fields(rect = ?_rect)))]
127    fn render(&self, _fb: &mut dyn Framebuffer, _rect: Rectangle, _fonts: &mut Fonts) {}
128
129    fn resize(&mut self, rect: Rectangle, hub: &Hub, rq: &mut RenderQueue, context: &mut Context) {
130        let dpi = CURRENT_DEVICE.dpi;
131        let thickness = scale_by_dpi(THICKNESS_MEDIUM, dpi) as i32;
132        let side = rect.height() as i32;
133        self.children[0].resize(rect![rect.min, rect.min + side], hub, rq, context);
134        self.children[1].resize(
135            rect![
136                pt!(rect.min.x + side, rect.min.y),
137                pt!(rect.min.x + side + thickness, rect.max.y)
138            ],
139            hub,
140            rq,
141            context,
142        );
143        self.children[2].resize(
144            rect![
145                pt!(rect.min.x + side + thickness, rect.min.y),
146                pt!(rect.max.x - side - thickness, rect.max.y)
147            ],
148            hub,
149            rq,
150            context,
151        );
152        self.children[3].resize(
153            rect![
154                pt!(rect.max.x - side - thickness, rect.min.y),
155                pt!(rect.max.x - side, rect.max.y)
156            ],
157            hub,
158            rq,
159            context,
160        );
161        self.children[4].resize(
162            rect![
163                pt!(rect.max.x - side, rect.min.y),
164                pt!(rect.max.x, rect.max.y)
165            ],
166            hub,
167            rq,
168            context,
169        );
170        self.rect = rect;
171    }
172
173    fn rect(&self) -> &Rectangle {
174        &self.rect
175    }
176
177    fn rect_mut(&mut self) -> &mut Rectangle {
178        &mut self.rect
179    }
180
181    fn children(&self) -> &Vec<Box<dyn View>> {
182        &self.children
183    }
184
185    fn children_mut(&mut self) -> &mut Vec<Box<dyn View>> {
186        &mut self.children
187    }
188
189    fn id(&self) -> Id {
190        self.id
191    }
192}