cadmus_core/view/touch_events/
mod.rs1use 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 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}