Rust · 3486 bytes Raw Blame History
1 //! Static text label widget
2
3 use anyhow::Result;
4 use gartk_core::{Color, Rect, Theme};
5 use gartk_render::{Renderer, TextStyle};
6
7 /// A static text label with optional key-value display
8 pub struct Label {
9 pub label: String,
10 pub text: String,
11 pub bounds: Rect,
12 pub color: Option<Color>,
13 pub font_size_multiplier: f64,
14 }
15
16 impl Label {
17 /// Create a new label
18 pub fn new(label: impl Into<String>, text: impl Into<String>) -> Self {
19 Self {
20 label: label.into(),
21 text: text.into(),
22 bounds: Rect::new(0, 0, 0, 0),
23 color: None,
24 font_size_multiplier: 1.0,
25 }
26 }
27
28 /// Create a label with just text (no key)
29 pub fn text_only(text: impl Into<String>) -> Self {
30 Self {
31 label: String::new(),
32 text: text.into(),
33 bounds: Rect::new(0, 0, 0, 0),
34 color: None,
35 font_size_multiplier: 1.0,
36 }
37 }
38
39 /// Set custom color
40 pub fn with_color(mut self, color: Color) -> Self {
41 self.color = Some(color);
42 self
43 }
44
45 /// Set font size multiplier
46 pub fn with_size(mut self, multiplier: f64) -> Self {
47 self.font_size_multiplier = multiplier;
48 self
49 }
50
51 /// Render the label at a specific position
52 pub fn render_at(&self, renderer: &mut Renderer, x: i32, y: i32, theme: &Theme) -> Result<()> {
53 let style = TextStyle::new()
54 .font_family(&theme.font_family)
55 .font_size(theme.font_size * self.font_size_multiplier)
56 .color(self.color.unwrap_or(theme.foreground));
57
58 renderer.text(&self.text, x as f64, y as f64, &style)?;
59 Ok(())
60 }
61
62 /// Render the label using its bounds (with optional label prefix)
63 pub fn render(&self, renderer: &mut Renderer, theme: &Theme) -> Result<()> {
64 let y = self.bounds.y + (self.bounds.height as i32 - theme.font_size as i32) / 2;
65
66 // Draw label if present
67 if !self.label.is_empty() {
68 let label_style = TextStyle::new()
69 .font_family(&theme.font_family)
70 .font_size(theme.font_size * self.font_size_multiplier)
71 .color(theme.foreground);
72
73 renderer.text(&self.label, self.bounds.x as f64, y as f64, &label_style)?;
74
75 // Draw value on the right side
76 let value_style = TextStyle::new()
77 .font_family(&theme.font_family)
78 .font_size(theme.font_size * self.font_size_multiplier)
79 .color(self.color.unwrap_or(theme.item_description));
80
81 let value_x = self.bounds.x + self.bounds.width as i32 / 2;
82 renderer.text(&self.text, value_x as f64, y as f64, &value_style)?;
83 } else {
84 let style = TextStyle::new()
85 .font_family(&theme.font_family)
86 .font_size(theme.font_size * self.font_size_multiplier)
87 .color(self.color.unwrap_or(theme.foreground));
88
89 renderer.text(&self.text, self.bounds.x as f64, y as f64, &style)?;
90 }
91
92 Ok(())
93 }
94
95 /// Measure the label size
96 pub fn measure(&self, renderer: &Renderer, theme: &Theme) -> Result<(u32, u32)> {
97 let style = TextStyle::new()
98 .font_family(&theme.font_family)
99 .font_size(theme.font_size * self.font_size_multiplier);
100
101 let size = renderer.measure_text(&self.text, &style)?;
102 Ok((size.width, size.height))
103 }
104 }
105