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;
37pub mod plugins;
38pub mod renderer;
39pub mod style;
40pub mod theme;
41pub mod widget;
42
43#[cfg(feature = "canvas")]
44#[cfg_attr(docsrs, doc(cfg(feature = "canvas")))]
45pub use plugins::canvas;
46
47#[cfg(feature = "fatfs")]
48#[cfg_attr(docsrs, doc(cfg(feature = "fatfs")))]
49pub use plugins::fatfs;
50
51#[cfg(feature = "fontdue")]
52#[cfg_attr(docsrs, doc(cfg(feature = "fontdue")))]
53pub use plugins::fontdue;
54
55#[cfg(feature = "gif")]
56#[cfg_attr(docsrs, doc(cfg(feature = "gif")))]
57pub use plugins::gif;
58
59#[cfg(feature = "apng")]
60#[cfg_attr(docsrs, doc(cfg(feature = "apng")))]
61pub use plugins::apng;
62
63#[cfg(feature = "jpeg")]
64#[cfg_attr(docsrs, doc(cfg(feature = "jpeg")))]
65#[cfg_attr(docsrs, doc(cfg(feature = "jpeg")))]
66pub use plugins::jpeg;
67#[cfg(feature = "lottie")]
68#[cfg_attr(docsrs, doc(cfg(feature = "lottie")))]
69pub use plugins::lottie;
70
71#[cfg(feature = "nes")]
72#[cfg_attr(docsrs, doc(cfg(feature = "nes")))]
73pub use plugins::nes;
74
75#[cfg(feature = "pinyin")]
76#[cfg_attr(docsrs, doc(cfg(feature = "pinyin")))]
77pub use plugins::pinyin;
78
79#[cfg(feature = "png")]
80#[cfg_attr(docsrs, doc(cfg(feature = "png")))]
81pub use plugins::png;
82
83#[cfg(feature = "qrcode")]
84#[cfg_attr(docsrs, doc(cfg(feature = "qrcode")))]
85pub use plugins::qrcode;
86
87// Pull doc tests from the workspace README
88#[cfg(doctest)]
89doc_comment::doctest!("../../README.md");
90
91use alloc::rc::Rc;
92use alloc::vec::Vec;
93use core::cell::RefCell;
94
95/// Node in the widget hierarchy.
96///
97/// A `WidgetNode` owns a concrete widget instance and zero or more child nodes.
98/// Events are dispatched depth‑first and drawing occurs in the same order.
99/// This mirrors the behaviour of common retained‑mode UI frameworks.
100pub struct WidgetNode {
101    /// The widget instance held by this node.
102    pub widget: Rc<RefCell<dyn widget::Widget>>,
103    /// Child nodes that make up this widget's hierarchy.
104    pub children: Vec<WidgetNode>,
105}
106
107impl WidgetNode {
108    /// Propagate an event to this node and its children.
109    ///
110    /// Returns `true` if any widget handled the event.
111    pub fn dispatch_event(&mut self, event: &event::Event) -> bool {
112        if self.widget.borrow_mut().handle_event(event) {
113            return true;
114        }
115        for child in &mut self.children {
116            if child.dispatch_event(event) {
117                return true;
118            }
119        }
120        false
121    }
122
123    /// Recursively draw this node and all child nodes using the given renderer.
124    pub fn draw(&self, renderer: &mut dyn renderer::Renderer) {
125        self.widget.borrow().draw(renderer);
126        for child in &self.children {
127            child.draw(renderer);
128        }
129    }
130}