cadmus_core/view/
clock.rs1use super::{Bus, Event, Hub, Id, RenderData, RenderQueue, View, ViewId, ID_FEEDER};
2use crate::color::{BLACK, WHITE};
3use crate::context::Context;
4use crate::device::CURRENT_DEVICE;
5use crate::font::{font_from_style, Fonts, NORMAL_STYLE};
6use crate::framebuffer::{Framebuffer, UpdateMode};
7use crate::geom::Rectangle;
8use crate::gesture::GestureEvent;
9use chrono::{DateTime, Local};
10
11pub struct Clock {
12 id: Id,
13 rect: Rectangle,
14 children: Vec<Box<dyn View>>,
15 format: String,
16 time: DateTime<Local>,
17}
18
19impl Clock {
20 pub fn new(rect: &mut Rectangle, context: &mut Context) -> Clock {
21 let time = Local::now();
22 let format = context.settings.time_format.clone();
23 let font = font_from_style(&mut context.fonts, &NORMAL_STYLE, CURRENT_DEVICE.dpi);
24 let width = font
25 .plan(&time.format(&format).to_string(), None, None)
26 .width
27 + font.em() as i32;
28 rect.min.x = rect.max.x - width;
29 Clock {
30 id: ID_FEEDER.next(),
31 rect: *rect,
32 children: Vec::new(),
33 format,
34 time,
35 }
36 }
37
38 pub fn update(&mut self, rq: &mut RenderQueue) {
39 self.time = Local::now();
40 rq.add(RenderData::new(self.id, self.rect, UpdateMode::Gui));
41 }
42}
43
44impl View for Clock {
45 #[cfg_attr(feature = "otel", tracing::instrument(skip(self, _hub, bus, rq, _context), fields(event = ?evt), ret(level=tracing::Level::TRACE)))]
46 fn handle_event(
47 &mut self,
48 evt: &Event,
49 _hub: &Hub,
50 bus: &mut Bus,
51 rq: &mut RenderQueue,
52 _context: &mut Context,
53 ) -> bool {
54 match *evt {
55 Event::ClockTick => {
56 self.update(rq);
57 true
58 }
59 Event::Gesture(GestureEvent::Tap(center)) if self.rect.includes(center) => {
60 bus.push_back(Event::ToggleNear(ViewId::ClockMenu, self.rect));
61 true
62 }
63 _ => false,
64 }
65 }
66
67 #[cfg_attr(feature = "otel", tracing::instrument(skip(self, fb, fonts, _rect), fields(rect = ?_rect)))]
68 fn render(&self, fb: &mut dyn Framebuffer, _rect: Rectangle, fonts: &mut Fonts) {
69 let dpi = CURRENT_DEVICE.dpi;
70 let font = font_from_style(fonts, &NORMAL_STYLE, dpi);
71 let plan = font.plan(&self.time.format(&self.format).to_string(), None, None);
72 let dx = (self.rect.width() as i32 - plan.width) / 2;
73 let dy = (self.rect.height() as i32 - font.x_heights.0 as i32) / 2;
74 let pt = pt!(self.rect.min.x + dx, self.rect.max.y - dy);
75
76 fb.draw_rectangle(&self.rect, WHITE);
77 font.render(fb, BLACK, &plan, pt);
78 }
79
80 fn rect(&self) -> &Rectangle {
81 &self.rect
82 }
83
84 fn rect_mut(&mut self) -> &mut Rectangle {
85 &mut self.rect
86 }
87
88 fn children(&self) -> &Vec<Box<dyn View>> {
89 &self.children
90 }
91
92 fn children_mut(&mut self) -> &mut Vec<Box<dyn View>> {
93 &mut self.children
94 }
95
96 fn id(&self) -> Id {
97 self.id
98 }
99}