cadmus_core/view/reader/
results_label.rs

1use crate::color::TEXT_NORMAL;
2use crate::context::Context;
3use crate::device::CURRENT_DEVICE;
4use crate::font::{font_from_style, Fonts, NORMAL_STYLE};
5use crate::framebuffer::{Framebuffer, UpdateMode};
6use crate::geom::Rectangle;
7use crate::view::{Bus, Event, Hub, Id, RenderData, RenderQueue, View, ID_FEEDER};
8
9pub struct ResultsLabel {
10    id: Id,
11    rect: Rectangle,
12    children: Vec<Box<dyn View>>,
13    count: usize,
14    completed: bool,
15}
16
17impl ResultsLabel {
18    pub fn new(rect: Rectangle, count: usize, completed: bool) -> ResultsLabel {
19        ResultsLabel {
20            id: ID_FEEDER.next(),
21            rect,
22            children: Vec::new(),
23            count,
24            completed,
25        }
26    }
27
28    pub fn update(&mut self, count: usize, rq: &mut RenderQueue) {
29        self.count = count;
30        rq.add(RenderData::new(self.id, self.rect, UpdateMode::Gui));
31    }
32
33    fn text(&self) -> String {
34        let qualifier = if self.count != 1 { "results" } else { "result" };
35
36        if self.count == 0 {
37            format!("No {}", qualifier)
38        } else {
39            format!("{} {}", self.count, qualifier)
40        }
41    }
42}
43
44impl View for ResultsLabel {
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::EndOfSearch => {
56                self.completed = true;
57                rq.add(RenderData::new(self.id, self.rect, UpdateMode::Gui));
58                false
59            }
60            _ => false,
61        }
62    }
63
64    #[cfg_attr(feature = "otel", tracing::instrument(skip(self, fb, fonts, _rect), fields(rect = ?_rect)))]
65    fn render(&self, fb: &mut dyn Framebuffer, _rect: Rectangle, fonts: &mut Fonts) {
66        let dpi = CURRENT_DEVICE.dpi;
67        let font = font_from_style(fonts, &NORMAL_STYLE, dpi);
68        let padding = font.em() as i32 / 2;
69        let max_width = self.rect.width().saturating_sub(2 * padding as u32) as i32;
70        let plan = font.plan(&self.text(), Some(max_width), None);
71        let dx = padding + (max_width - plan.width) / 2;
72        let dy = (self.rect.height() as i32 - font.x_heights.0 as i32) / 2;
73        let pt = pt!(self.rect.min.x + dx, self.rect.max.y - dy);
74        fb.draw_rectangle(&self.rect, TEXT_NORMAL[0]);
75        let color = if self.completed {
76            TEXT_NORMAL[1]
77        } else {
78            TEXT_NORMAL[2]
79        };
80        font.render(fb, color, &plan, pt);
81    }
82
83    fn rect(&self) -> &Rectangle {
84        &self.rect
85    }
86
87    fn rect_mut(&mut self) -> &mut Rectangle {
88        &mut self.rect
89    }
90
91    fn children(&self) -> &Vec<Box<dyn View>> {
92        &self.children
93    }
94
95    fn children_mut(&mut self) -> &mut Vec<Box<dyn View>> {
96        &mut self.children
97    }
98
99    fn id(&self) -> Id {
100        self.id
101    }
102}