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