rlvgl_core/
lib.rs

1//! Core runtime types and utilities for the `rlvgl` UI toolkit.
2//!
3//! This crate exposes the building blocks used by higher-level widgets and
4//! platform backends. It is intended to be usable in `no_std` environments and
5//! therefore avoids allocations where possible.
6//!
7//! Widgets are organized into a tree of `WidgetNode` values which receive
8//! `Event`s and draw themselves via a `Renderer` implementation.
9//!
10//! **Note:** `Event` and `Renderer` are externally supplied types, not defined
11//! in this crate.
12#![cfg_attr(not(test), no_std)]
13#![deny(missing_docs)]
14#![cfg_attr(all(docsrs, nightly), feature(doc_cfg))]
15
16// When running tests, pull in the standard library so the test
17// harness can link successfully.
18#[cfg(any(
19    test,
20    feature = "png",
21    feature = "jpeg",
22    feature = "qrcode",
23    feature = "gif",
24    feature = "fontdue",
25    feature = "lottie",
26    feature = "pinyin",
27    feature = "fatfs",
28    feature = "nes",
29    feature = "apng"
30))]
31extern crate std;
32
33extern crate alloc;
34
35pub mod animation;
36pub mod event;
37#[cfg(feature = "fs")]
38pub mod fs;
39pub mod plugins;
40pub mod renderer;
41pub mod style;
42pub mod theme;
43pub mod widget;
44
45#[cfg(feature = "canvas")]
46#[cfg_attr(docsrs, doc(cfg(feature = "canvas")))]
47pub use plugins::canvas;
48
49#[cfg(feature = "fatfs")]
50#[cfg_attr(docsrs, doc(cfg(feature = "fatfs")))]
51pub use plugins::fatfs;
52
53#[cfg(feature = "fontdue")]
54#[cfg_attr(docsrs, doc(cfg(feature = "fontdue")))]
55pub use plugins::fontdue;
56
57#[cfg(feature = "gif")]
58#[cfg_attr(docsrs, doc(cfg(feature = "gif")))]
59pub use plugins::gif;
60
61#[cfg(feature = "apng")]
62#[cfg_attr(docsrs, doc(cfg(feature = "apng")))]
63pub use plugins::apng;
64
65#[cfg(feature = "jpeg")]
66#[cfg_attr(docsrs, doc(cfg(feature = "jpeg")))]
67#[cfg_attr(docsrs, doc(cfg(feature = "jpeg")))]
68pub use plugins::jpeg;
69#[cfg(feature = "lottie")]
70#[cfg_attr(docsrs, doc(cfg(feature = "lottie")))]
71pub use plugins::lottie;
72
73#[cfg(feature = "nes")]
74#[cfg_attr(docsrs, doc(cfg(feature = "nes")))]
75pub use plugins::nes;
76
77#[cfg(feature = "pinyin")]
78#[cfg_attr(docsrs, doc(cfg(feature = "pinyin")))]
79pub use plugins::pinyin;
80
81#[cfg(feature = "png")]
82#[cfg_attr(docsrs, doc(cfg(feature = "png")))]
83pub use plugins::png;
84
85#[cfg(feature = "qrcode")]
86#[cfg_attr(docsrs, doc(cfg(feature = "qrcode")))]
87pub use plugins::qrcode;
88
89// Pull doc tests from the workspace README
90#[cfg(doctest)]
91doc_comment::doctest!("../../README.md");
92
93use alloc::rc::Rc;
94use alloc::vec::Vec;
95use core::cell::RefCell;
96
97/// Node in the widget hierarchy.
98///
99/// A `WidgetNode` owns a concrete widget instance and zero or more child nodes.
100/// Events are dispatched depth‑first and drawing occurs in the same order.
101/// This mirrors the behaviour of common retained‑mode UI frameworks.
102pub struct WidgetNode {
103    /// The widget instance held by this node.
104    pub widget: Rc<RefCell<dyn widget::Widget>>,
105    /// Child nodes that make up this widget's hierarchy.
106    pub children: Vec<WidgetNode>,
107}
108
109impl WidgetNode {
110    /// Propagate an event to this node and its children.
111    ///
112    /// Returns `true` if any widget handled the event.
113    pub fn dispatch_event(&mut self, event: &event::Event) -> bool {
114        if self.widget.borrow_mut().handle_event(event) {
115            return true;
116        }
117        for child in &mut self.children {
118            if child.dispatch_event(event) {
119                return true;
120            }
121        }
122        false
123    }
124
125    /// Recursively draw this node and all child nodes using the given renderer.
126    pub fn draw(&self, renderer: &mut dyn renderer::Renderer) {
127        self.widget.borrow().draw(renderer);
128        for child in &self.children {
129            child.draw(renderer);
130        }
131    }
132}