1pub mod component;
22pub mod event;
23pub mod image;
24pub mod layout;
25mod render;
26pub mod rich;
27pub mod scroll;
28#[cfg(test)]
29mod state_tests;
30pub mod surface;
31pub mod theme;
32pub mod text;
33pub mod textbox;
34pub mod widget;
35
36pub use event::UiEvent;
37pub use layout::{Align, FlexDir, GridLines, LayoutNode, Rect, hit_path, node_at, set_focus};
38pub use yog_gfx::{Color, Vec2};
39pub use scroll::ScrollState;
40pub use surface::{Pointer, Surface};
41pub use textbox::{TextBoxEvent, TextBoxState};
42pub use render::{ICON_SIZE, INV_SLOT_FACE, INV_SLOT_LIGHT, INV_SLOT_SHADOW};
43pub use widget::{
44 Action, Cell, Dock, FocusStyle, GridLength, GridSpec, HAlign, StateFlags, StateStyles, Stretch,
45 StylePatch, Track, Units, VAlign, Widget,
46};
47
48use yog_gfx::GfxContext;
49
50pub struct UiRoot {
52 pub id: String,
53 pub root: Widget,
54 pub layout_root: LayoutNode,
55 pub needs_layout: bool,
56}
57
58impl UiRoot {
59 pub fn new(id: impl Into<String>, root: Widget) -> Self {
60 Self {
61 id: id.into(),
62 root,
63 layout_root: LayoutNode::default(),
64 needs_layout: true,
65 }
66 }
67
68 pub fn layout(&mut self, screen_w: f32, screen_h: f32) {
70 self.layout_root = layout::compute(&self.root, screen_w, screen_h);
71 self.needs_layout = false;
72 }
73
74 pub fn render(&self, ctx: &GfxContext) {
77 text::use_host_metrics(ctx);
78 image::use_host_images(ctx);
79 let d2d = ctx.draw2d();
80 render::render_node(ctx, &d2d, &self.root, &self.layout_root);
81 }
82
83 pub fn tooltip_at(&self, mx: f32, my: f32) -> Option<&str> {
86 let path = layout::deepest_path(&self.layout_root, mx, my)?;
87 let mut w = &self.root;
88 let mut found = w.tooltip.as_deref();
89 for &i in &path {
90 let Some(c) = w.children.get(i as usize) else { break };
91 w = c;
92 found = w.tooltip.as_deref().or(found);
93 }
94 found
95 }
96
97 pub fn render_tooltip(ctx: &GfxContext, text: &str, mx: f32, my: f32) {
100 text::use_host_metrics(ctx);
101 let (sw, sh) = ctx.screen_size();
102 render::tooltip(&ctx.draw2d(), text, mx, my, sw as f32, sh as f32);
103 }
104
105 pub fn hit_test(&self, mx: f32, my: f32) -> Option<&LayoutNode> {
107 layout::hit_test(&self.layout_root, mx, my)
108 }
109
110 pub fn find_rect(&self, id: &str) -> Option<Rect> {
113 layout::find_by_id(&self.layout_root, id)
114 }
115
116 pub fn find_node(&self, id: &str) -> Option<&LayoutNode> {
119 layout::find_node(&self.layout_root, id)
120 }
121}