1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use std::any::Any;

use crate::{
    assets::{AssetOrPath, LoadedAsset},
    canvas::Canvas,
    font::Font,
};

use super::{Widget, WidgetRef};

use taffy::NodeId;
use vek::{Extent2, Vec2};

/// A simple text label widget.
#[derive(Debug)]
pub struct Label {
    /// Top-left position of the widget in pixels.
    pub offset: Vec2<f64>,
    /// Size of the label area in pixels.
    pub size: Extent2<f64>,
    /// The text to draw.
    pub label: String,
    /// Taffy layout node.
    pub node: NodeId,
    /// Where to load the font asset.
    pub font_asset: AssetOrPath<Font>,
}

impl Label {
    /// Render the label.
    pub fn render(&self, canvas: &mut Canvas) {
        let font: LoadedAsset<Font> = (&self.font_asset).into();
        font.render_centered(
            &self.label,
            self.offset + (self.size.w / 2.0, self.size.h / 2.0),
            canvas,
        );
    }
}

impl Widget for Label {
    fn update_layout(&mut self, location: Vec2<f64>, size: Extent2<f64>) {
        self.offset = location;
        self.size = size;
    }

    fn as_any(&self) -> &dyn Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}

impl Default for Label {
    fn default() -> Self {
        Self {
            offset: Vec2::zero(),
            label: String::new(),
            node: NodeId::new(0),
            size: Extent2::default(),
            #[cfg(feature = "default-font")]
            font_asset: AssetOrPath::Owned(Font::default()),
            #[cfg(not(feature = "default-font"))]
            font_asset: "font".into(),
        }
    }
}

/// Gui reference for retrieving constructed labels.
///
/// See [`WidgetRef`].
#[derive(Copy, Clone)]
pub struct LabelRef(NodeId);

impl WidgetRef for LabelRef {
    type Widget = Label;
}

impl From<LabelRef> for NodeId {
    fn from(val: LabelRef) -> Self {
        val.0
    }
}

impl From<NodeId> for LabelRef {
    fn from(value: NodeId) -> Self {
        Self(value)
    }
}