cadmus_core/view/touch_events/
mod.rs

1use crate::color::{BLACK, GRAY05, GRAY10, WHITE};
2use crate::context::Context;
3use crate::device::CURRENT_DEVICE;
4use crate::font::Fonts;
5use crate::framebuffer::{Framebuffer, UpdateMode};
6use crate::geom::{CornerSpec, Dir, Rectangle, Region};
7use crate::unit::scale_by_dpi;
8use crate::view::icon::Icon;
9use crate::view::notification::Notification;
10use crate::view::SMALL_BAR_HEIGHT;
11use crate::view::{Bus, Event, Hub, RenderData, RenderQueue, View};
12use crate::view::{Id, ID_FEEDER};
13
14pub struct TouchEvents {
15    id: Id,
16    rect: Rectangle,
17    children: Vec<Box<dyn View>>,
18    strip_width: f32,
19    corner_width: f32,
20}
21
22impl TouchEvents {
23    pub fn new(rect: Rectangle, rq: &mut RenderQueue, context: &mut Context) -> TouchEvents {
24        let id = ID_FEEDER.next();
25        let mut children = Vec::new();
26        let dpi = CURRENT_DEVICE.dpi;
27        let small_height = scale_by_dpi(SMALL_BAR_HEIGHT, dpi) as i32;
28        let dx = (rect.width() as i32 - small_height) / 2;
29        let dy = (rect.height() as i32 - small_height) / 3;
30        let icon_rect = rect![
31            rect.min.x + dx,
32            rect.min.y + dy,
33            rect.min.x + dx + small_height,
34            rect.min.y + dy + small_height
35        ];
36        let icon = Icon::new("back", icon_rect, Event::Back)
37            .corners(Some(CornerSpec::Uniform(small_height / 2)));
38        children.push(Box::new(icon) as Box<dyn View>);
39        rq.add(RenderData::new(id, rect, UpdateMode::Full));
40        let strip_width = context.settings.reader.strip_width;
41        let corner_width = context.settings.reader.corner_width;
42        TouchEvents {
43            id,
44            rect,
45            children,
46            strip_width,
47            corner_width,
48        }
49    }
50}
51
52impl View for TouchEvents {
53    #[cfg_attr(feature = "otel", tracing::instrument(skip(self, hub, _bus, rq, context), fields(event = ?evt), ret(level=tracing::Level::TRACE)))]
54    fn handle_event(
55        &mut self,
56        evt: &Event,
57        hub: &Hub,
58        _bus: &mut Bus,
59        rq: &mut RenderQueue,
60        context: &mut Context,
61    ) -> bool {
62        match *evt {
63            Event::Gesture(ge) => {
64                let notif = Notification::new(None, ge.to_string(), false, hub, rq, context);
65                self.children.push(Box::new(notif) as Box<dyn View>);
66                true
67            }
68            _ => false,
69        }
70    }
71
72    #[cfg_attr(feature = "otel", tracing::instrument(skip(self, fb, _fonts), fields(rect = ?rect)))]
73    fn render(&self, fb: &mut dyn Framebuffer, rect: Rectangle, _fonts: &mut Fonts) {
74        for x in rect.min.x..rect.max.x {
75            for y in rect.min.y..rect.max.y {
76                let color = match Region::from_point(
77                    pt!(x, y),
78                    self.rect,
79                    self.strip_width,
80                    self.corner_width,
81                ) {
82                    Region::Corner(..) => BLACK,
83                    Region::Strip(Dir::West) | Region::Strip(Dir::East) => GRAY05,
84                    Region::Strip(Dir::South) | Region::Strip(Dir::North) => GRAY10,
85                    Region::Center => WHITE,
86                };
87                fb.set_pixel(x as u32, y as u32, color);
88            }
89        }
90    }
91
92    fn render_rect(&self, rect: &Rectangle) -> Rectangle {
93        rect.intersection(&self.rect).unwrap_or(self.rect)
94    }
95
96    fn is_background(&self) -> bool {
97        true
98    }
99
100    fn resize(&mut self, rect: Rectangle, hub: &Hub, rq: &mut RenderQueue, context: &mut Context) {
101        let dpi = CURRENT_DEVICE.dpi;
102        let small_height = scale_by_dpi(SMALL_BAR_HEIGHT, dpi) as i32;
103        let dx = (rect.width() as i32 - small_height) / 2;
104        let dy = (rect.height() as i32 - small_height) / 3;
105        let icon_rect = rect![
106            rect.min.x + dx,
107            rect.min.y + dy,
108            rect.min.x + dx + small_height,
109            rect.min.y + dy + small_height
110        ];
111        self.children[0].resize(icon_rect, hub, rq, context);
112
113        // Floating windows.
114        for i in 1..self.children.len() {
115            self.children[i].resize(rect, hub, rq, context);
116        }
117
118        self.rect = rect;
119        rq.add(RenderData::new(self.id, self.rect, UpdateMode::Full));
120    }
121
122    fn rect(&self) -> &Rectangle {
123        &self.rect
124    }
125
126    fn rect_mut(&mut self) -> &mut Rectangle {
127        &mut self.rect
128    }
129
130    fn children(&self) -> &Vec<Box<dyn View>> {
131        &self.children
132    }
133
134    fn children_mut(&mut self) -> &mut Vec<Box<dyn View>> {
135        &mut self.children
136    }
137
138    fn id(&self) -> Id {
139        self.id
140    }
141}