yakui_core/
state.rs

1use crate::context;
2use crate::dom::Dom;
3use crate::event::{Event, EventResponse};
4use crate::geometry::{Rect, Vec2};
5use crate::id::ManagedTextureId;
6use crate::input::InputState;
7use crate::layout::LayoutDom;
8use crate::paint::{PaintDom, Texture};
9
10/// The entrypoint for yakui.
11#[derive(Debug)]
12pub struct Yakui {
13    dom: Dom,
14    layout: LayoutDom,
15    paint: PaintDom,
16    input: InputState,
17}
18
19impl Yakui {
20    /// Creates a new yakui State.
21    #[allow(clippy::new_without_default)]
22    pub fn new() -> Self {
23        Self {
24            dom: Dom::new(),
25            layout: LayoutDom::new(),
26            paint: PaintDom::new(),
27            input: InputState::new(),
28        }
29    }
30
31    /// Handles the given event. Returns `true` if the event was sunk by yakui
32    /// and should not be processed by the application.
33    pub fn handle_event(&mut self, event: Event) -> bool {
34        log::debug!("State::handle_event({event:?})");
35
36        context::bind_dom(&self.dom);
37
38        let response = self.input.handle_event(&self.dom, &self.layout, &event);
39
40        if let Event::ViewportChanged(viewport) = event {
41            self.layout.set_unscaled_viewport(viewport);
42        }
43
44        context::unbind_dom();
45        response == EventResponse::Sink
46    }
47
48    /// Creates a texture for use within yakui.
49    pub fn add_texture(&mut self, texture: Texture) -> ManagedTextureId {
50        self.paint.add_texture(texture)
51    }
52
53    /// Returns an iterator of all textures managed by yakui.
54    pub fn textures(&self) -> impl Iterator<Item = (ManagedTextureId, &Texture)> {
55        self.paint.textures()
56    }
57
58    /// Set the size of the surface the yakui is being rendered onto.
59    pub fn set_surface_size(&mut self, size: Vec2) {
60        self.paint.set_surface_size(size);
61    }
62
63    /// Set the size and position of the viewport in physical units.
64    pub fn set_unscaled_viewport(&mut self, view: Rect) {
65        self.layout.set_unscaled_viewport(view);
66        self.paint.set_unscaled_viewport(view);
67    }
68
69    /// Manually sets the scale factor used for laying out widgets.
70    ///
71    /// Platform integrations will usually do this automatically. If you'd like
72    /// to override that value, like to enable the user to set their own UI
73    /// scale, this is the method to use.
74    pub fn set_scale_factor(&mut self, factor: f32) {
75        self.layout.set_scale_factor(factor);
76        self.paint.set_scale_factor(factor);
77    }
78
79    /// Starts building the DOM on this thread.
80    ///
81    /// Once this method is called, widgets can be created on this thread and
82    /// they will automatically be linked to this State.
83    ///
84    /// When finished, call [`Dom::finish`].
85    pub fn start(&mut self) {
86        self.dom.start();
87        self.input.start(&self.dom, &self.layout);
88        self.paint.start();
89
90        context::bind_dom(&self.dom);
91    }
92
93    /// Finishes building the DOM. Must be called on a thread that previously
94    /// called [`Dom::start`].
95    ///
96    /// This method will finalize the DOM for this frame and compute layouts.
97    pub fn finish(&mut self) {
98        context::unbind_dom();
99
100        self.dom.finish(&self.input);
101        self.layout.sync_removals(&self.dom.removed_nodes());
102        self.layout.calculate_all(&self.dom, &self.input);
103        self.input.finish();
104    }
105
106    /// Calculates the geometry needed to render the current state and gives
107    /// access to the [`PaintDom`], which holds information about how to paint
108    /// widgets.
109    pub fn paint(&mut self) -> &PaintDom {
110        self.paint.paint_all(&self.dom, &self.layout);
111        &self.paint
112    }
113
114    /// Returns access to the state's DOM.
115    pub fn dom(&self) -> &Dom {
116        &self.dom
117    }
118
119    /// Returns access to the state's Layout DOM.
120    pub fn layout_dom(&self) -> &LayoutDom {
121        &self.layout
122    }
123}