Skip to main content

yog_ui/
widget.rs

1//! Widget types and styling.
2
3use crate::layout::{Align, FlexDir};
4
5/// A single widget in the UI tree.
6#[derive(Debug, Clone)]
7pub struct Widget {
8    pub kind:     WidgetKind,
9    pub id:       Option<String>,
10    pub style:    Style,
11    pub flex_dir: FlexDir,
12    pub children: Vec<Widget>,
13    pub on_click: Option<String>,
14}
15
16#[derive(Debug, Clone)]
17pub enum WidgetKind {
18    /// Container — arranges children according to `flex_dir`.
19    Panel,
20    /// Static or dynamic text label.
21    Label(String),
22    /// Clickable button with text.
23    Button(String),
24    /// Minecraft item icon.
25    ItemSlot(String),
26    /// Invisible spacer.
27    Spacer,
28}
29
30/// Visual and layout style for a widget.
31#[derive(Debug, Clone)]
32pub struct Style {
33    pub w:      f32,   // explicit width; 0 = auto
34    pub h:      f32,   // explicit height; 0 = auto
35    pub min_w:  f32,
36    pub min_h:  f32,
37    pub flex:   f32,   // grow factor inside flex container
38    pub gap:    f32,   // spacing between children
39    pub pad:    [f32; 4],  // top, right, bottom, left
40    pub margin: [f32; 4],
41    pub bg:     u32,   // background colour 0xAARRGGBB; 0 = transparent
42    pub color:  u32,   // text colour
43    pub align:  Align,
44    pub font_scale: f32,
45}
46
47impl Default for Style {
48    fn default() -> Self {
49        Self {
50            w: 0.0, h: 0.0, min_w: 4.0, min_h: 4.0, flex: 0.0, gap: 2.0,
51            pad: [0.0; 4], margin: [0.0; 4], bg: 0, color: 0xFF_CCCCAA,
52            align: Align::Start, font_scale: 1.0,
53        }
54    }
55}
56
57// ── Builder API ───────────────────────────────────────────────────────────────
58
59impl Widget {
60    fn new(kind: WidgetKind) -> Self {
61        Self { kind, id: None, style: Style::default(), flex_dir: FlexDir::Column,
62               children: Vec::new(), on_click: None }
63    }
64
65    pub fn id(mut self, id: impl Into<String>) -> Self { self.id = Some(id.into()); self }
66    pub fn on_click(mut self, ev: impl Into<String>) -> Self { self.on_click = Some(ev.into()); self }
67    pub fn child(mut self, w: Widget) -> Self { self.children.push(w); self }
68
69    pub fn w(mut self, w: f32) -> Self { self.style.w = w; self }
70    pub fn h(mut self, h: f32) -> Self { self.style.h = h; self }
71    pub fn min_w(mut self, v: f32) -> Self { self.style.min_w = v; self }
72    pub fn min_h(mut self, v: f32) -> Self { self.style.min_h = v; self }
73    pub fn flex(mut self, v: f32) -> Self { self.style.flex = v; self }
74    pub fn flex_dir(mut self, v: FlexDir) -> Self { self.flex_dir = v; self }
75    pub fn gap(mut self, v: f32) -> Self { self.style.gap = v; self }
76    pub fn bg(mut self, v: u32) -> Self { self.style.bg = v; self }
77    pub fn color(mut self, v: u32) -> Self { self.style.color = v; self }
78    pub fn align(mut self, v: Align) -> Self { self.style.align = v; self }
79    pub fn font_scale(mut self, v: f32) -> Self { self.style.font_scale = v; self }
80    pub fn padding(mut self, top: f32, right: f32, bottom: f32, left: f32) -> Self {
81        self.style.pad = [top, right, bottom, left]; self
82    }
83    pub fn margin(mut self, top: f32, right: f32, bottom: f32, left: f32) -> Self {
84        self.style.margin = [top, right, bottom, left]; self
85    }
86}
87
88// ── Widget constructors ───────────────────────────────────────────────────────
89
90pub fn panel(dir: FlexDir) -> Widget { Widget::new(WidgetKind::Panel).flex_dir(dir) }
91pub fn label(text: impl Into<String>) -> Widget { Widget::new(WidgetKind::Label(text.into())) }
92pub fn button(text: impl Into<String>) -> Widget { Widget::new(WidgetKind::Button(text.into())) }
93pub fn item_slot(item_id: impl Into<String>) -> Widget { Widget::new(WidgetKind::ItemSlot(item_id.into())) }
94pub fn spacer() -> Widget { Widget::new(WidgetKind::Spacer) }