1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! A native Rust GUI library with a retained widget tree, fine-grained
//! reactive signals and damage-tracked repainting, built to stay fast on
//! machines without a usable GPU.
//!
//! # Quick start
//!
//! A counter: a button and a label bound to one signal. Each press writes the
//! signal, the label's text closure reruns, and the next frame repaints only
//! the label.
//!
//! ```no_run
//! use smudge::prelude::*;
//!
//! fn main() -> Result<(), PlatformError> {
//! let count = RwSignal::new(0_u32);
//! let press = count.clone();
//! let shown = count.clone();
//!
//! run_with(
//! WindowOptions {
//! title: String::from("Counter"),
//! size: Size {
//! width: 280.0,
//! height: 140.0,
//! },
//! clear_color: Color::rgb(16, 17, 21),
//! ..WindowOptions::default()
//! },
//! move || {
//! column()
//! .padding(px(24.0))
//! .gap(Size {
//! width: 0.0,
//! height: 12.0,
//! })
//! .align_items(Align::Center)
//! .child(
//! button("Count up")
//! .primary()
//! .on_press(move || press.update(|count| *count += 1)),
//! )
//! .child(label(move || format!("Clicked {} times", shown.get())))
//! },
//! |app| app.set_theme(Theme::dark()),
//! )
//! }
//! ```
//!
//! The runnable versions of this and two larger applications live in
//! `crates/smudge/examples`. The same application also runs headless:
//! [`core::App`] takes the build closure, and its `frame` method advances it
//! one frame at a time, which is what tests and benchmarks drive.
//!
//! # The frame model
//!
//! Application state lives in signals ([`core::reactive::RwSignal`]). Styling
//! a widget with a closure, or handing a closure to [`text::label`], binds
//! that part of the widget to the signals the closure reads. A write to a
//! signal touches no widget directly. At the next `App::frame`, the rerun
//! bindings queue their updates, layout reruns for the nodes the updates
//! marked, the changed widgets regenerate their paint operations, and the
//! pipeline subtracts what stayed the same. What is left is the frame's
//! damage, the physical-pixel rectangles the frame changed, and the renderer
//! repaints exactly that onto the previous frame's pixels. A frame that
//! changes one small box rasterizes and presents one small box;
//! [`core::RepaintMode::Full`] turns the subtraction off when a
//! whole-surface redraw is wanted instead.
//!
//! # Platform support
//!
//! - **Desktop:** the CPU renderer presents through the window's buffer. With
//! the `gpu` feature, a vello renderer draws the same display list on the
//! GPU, and [`window::RendererChoice::Auto`], the default, uses the GPU
//! only when the adapter is a real GPU, falling back to the CPU renderer on
//! a software rasterizer.
//! - **Web:** the CPU renderer runs in a browser on `wasm32-unknown-unknown`;
//! `crates/smudge-platform/examples/web` holds a buildable web example.
//! - **Accessibility:** the AccessKit projection runs on desktop only. The
//! web target has no accessibility backend in this version.
//! - **Text:** Chinese, Japanese, Thai, Lao, Khmer and Burmese break by word
//! only with the `complex-scripts` feature, which compiles in the break
//! dictionaries at about 3 MB per binary.
pub use smudge_core as core;
pub use smudge_text as text;
pub use smudge_widgets as widgets;
/// The commands an application sends to its window from a handler, the
/// window state it reads, and the pointer cursors.
///
/// This is the core's window module under a name that does not clash with
/// [`window`], the windowing layer that applies the commands.
///
/// ```
/// use smudge::commands::{self, ResizeEdge};
/// use smudge::prelude::*;
///
/// let header = row()
/// .height(px(36.0))
/// .on_pointer_down(|_| commands::start_move())
/// .child(
/// panel()
/// .width(px(6.0))
/// .cursor(Cursor::Resize(ResizeEdge::East))
/// .hidden(commands::maximized)
/// .on_pointer_down(|_| commands::start_resize(ResizeEdge::East)),
/// )
/// .child(button("Close").on_press(commands::close));
/// ```
pub use window as commands;
pub use smudge_platform as window;
pub use smudge_gpu as gpu;