pixels_graphics_lib/ui/
tooltip.rs1use crate::ui::prelude::*;
2use crate::ui::styles::TooltipStyle;
3use crate::Timing;
4use buffer_graphics_lib::prelude::DrawType::Fill;
5use buffer_graphics_lib::prelude::*;
6
7#[derive(Debug)]
8pub struct Tooltip {
9 label: String,
10 text: Text,
11 background: Drawable<Rect>,
12 border: Polyline,
13 shadow: Polyline,
14 style: TooltipStyle,
15}
16
17impl Tooltip {
18 pub fn new<P: Into<Coord>>(
19 anchor: P,
20 text: &str,
21 positioning: Positioning,
22 style: &TooltipStyle,
23 ) -> Self {
24 let bounds = Self::calc_bounds(anchor.into(), positioning, text, style.font);
25 let bounds = Rect::new_with_size(
26 bounds.top_left(),
27 bounds.width() + (style.padding),
28 bounds.height() + (style.padding),
29 );
30 let label = text;
31 let (border, shadow, background, text) = Self::layout(&bounds, label, style);
32 Self {
33 label: label.to_string(),
34 text,
35 background,
36 border,
37 shadow,
38 style: style.clone(),
39 }
40 }
41
42 fn layout(
43 bounds: &Rect,
44 label: &str,
45 style: &TooltipStyle,
46 ) -> (Polyline, Polyline, Drawable<Rect>, Text) {
47 let border = Polyline::rounded_rect(
48 bounds.left(),
49 bounds.top(),
50 bounds.right(),
51 bounds.bottom(),
52 0,
53 WHITE,
54 )
55 .unwrap();
56 let shadow = Polyline::rounded_rect(
57 bounds.left() + 1,
58 bounds.top() + 1,
59 bounds.right() + 1,
60 bounds.bottom() + 1,
61 0,
62 WHITE,
63 )
64 .unwrap();
65 let background = Drawable::from_obj(
66 Rect::new(bounds.top_left(), bounds.bottom_right()),
67 Fill(BLACK),
68 );
69 let text = Text::new(
70 label,
71 TextPos::px(bounds.top_left() + (style.padding, style.padding)),
72 (WHITE, style.font, WrappingStrategy::SpaceBeforeCol(20)),
73 );
74 (border, shadow, background, text)
75 }
76}
77
78impl Tooltip {
79 pub fn calc_bounds(xy: Coord, positioning: Positioning, text: &str, font: PixelFont) -> Rect {
80 let (w, h) = font.measure(&WrappingStrategy::SpaceBeforeCol(20).wrap(text).join("\n"));
81 let anchor = positioning.calc((xy.x, xy.y), w, h);
82 Rect::new_with_size(Coord::new(anchor.0, anchor.1), w, h)
83 }
84}
85
86impl PixelView for Tooltip {
87 fn set_position(&mut self, top_left: Coord) {
88 self.background = self.background.with_move(top_left);
89 let (border, shadow, _, text) =
90 Self::layout(self.background.obj(), &self.label, &self.style);
91 self.border = border;
92 self.shadow = shadow;
93 self.text = text;
94 }
95
96 fn bounds(&self) -> &Rect {
97 self.background.obj()
98 }
99
100 fn render(&self, graphics: &mut Graphics, _: &MouseData) {
101 if let Some(color) = self.style.shadow.get(false, false, false) {
102 self.shadow.with_color(color).render(graphics);
103 }
104 if let Some(color) = self.style.background.get(false, false, false) {
105 self.background.with_draw_type(Fill(color)).render(graphics);
106 }
107 if let Some(color) = self.style.border.get(false, false, false) {
108 self.border.with_color(color).render(graphics);
109 }
110 if let Some(color) = self.style.text.get(false, false, false) {
111 self.text.with_color(color).render(graphics);
112 }
113 }
114
115 fn update(&mut self, _: &Timing) {}
116
117 fn set_state(&mut self, _: ViewState) {
118 unimplemented!("Tooltip doesn't have state")
119 }
120
121 fn get_state(&self) -> ViewState {
122 unimplemented!("Tooltip doesn't have state")
123 }
124}