rust_widgets 2.1.0

Pure Rust cross-platform native GUI library with hardware-adaptive rendering, 60+ widgets, touch/gesture support, i18n, and SVG-pipeline-accurate output
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
// SPDX-FileCopyrightText: Copyright (c) 2026 Mike Li/Mikewolfli/Wei Li(mikewolfli@163.com)
// SPDX-License-Identifier: MIT

//! Widget models, their capabilities, and the runtime that drives them.
//!
//! # Layering
//!
//! The module is organised in three layers on top of the core types:
//!
//! 1. **Widget models** — the control types re-exported at the bottom of this
//!    file ([`Button`], [`Slider`], `MenuBar`, ...). Each is a plain Rust
//!    struct holding its own state and a [`BaseWidget`]. They implement
//!    [`Widget`] by delegating the shared fields to the base, and describe
//!    themselves for accessibility through [`Widget::accessible_role`].
//! 2. **Capability** ([`capability`]) — a uniform, name-addressed view over
//!    those models: a property schema per kind, a get/set dispatch
//!    ([`capability::WidgetProperties`], surfaced as
//!    [`Widget::properties_dyn`]), and the factory that constructs controls by
//!    kind. This is what lets generic tooling (property editors, serialisers,
//!    FFI bindings) manipulate a widget without knowing its concrete type.
//! 3. **Runtime** (`runtime`) — the owner of the live widget tree. It holds
//!    widgets behind `dyn Widget`, delivers events, and resolves
//!    [`ObjectId`](crate::core::ObjectId)s back to widgets. Only compiled when
//!    widgets are not stripped.
//!
//! The layering is one-way: models do not know about the runtime, and the
//! capability layer reaches models only through [`Widget`].
//!
//! # Profile gating
//!
//! Types are gated by profile so that the mini and embedded builds stay small.
//! [`Widget`], [`BaseWidget`], [`WidgetKind`], and the property contract exist
//! in every profile; concrete controls and the factory are gated behind
//! `widgets_unstripped` / `full_widgets`, and the most advanced controls behind
//! `full_widgets` alone. Code that must build everywhere should depend only on
//! [`Widget`] plus the capability layer, and refer to concrete kinds by name at
//! the factory instead of by type.

// Base widget types
/// The shared state block every widget embeds: id, kind, geometry, visibility,
/// enabled flag, style, parent/child links, and the standard signal set.
pub mod base;
/// Widget capability metadata, the runtime factory, and the property contract.
///
/// The module is compiled in **every** profile, not only device ones: the
/// property contract ([`capability::WidgetProperties`]) is what
/// `Widget::properties_dyn` returns, and `Widget` exists everywhere. Only the
/// profile-specific *parts* — the property schema tables, the legacy centralised
/// access layer, the factory and its registration — are gated, below.
pub mod capability;
pub mod draw;
/// The bridge that connects a self-painting widget to `dyn Widget`.
///
/// Declared with `#[macro_use]` so `impl_draw_bridge!` is in scope in every
/// widget module without each one adding an import — the macro is meant to be
/// called from the widget's own `impl Widget` block, wherever that block lives.
#[macro_use]
pub mod draw_bridge;
pub mod kind;

#[cfg(not(alloc_frugal))]
pub mod runtime;
/// Byte-index helpers shared by the text-editing controls.
pub mod text_utils;
pub mod widget_trait;
// Widget subfolders
#[cfg(full_widgets)]
pub mod advanced_widgets;
pub mod base_widgets;
#[cfg(full_widgets)]
pub mod chart_widgets;
pub mod container_widgets;
#[cfg(full_widgets)]
pub mod cupertino;
#[cfg(full_widgets)]
pub mod dialog;
pub mod display_widgets;
pub mod input_widgets;
#[cfg(full_widgets)]
pub mod media_widgets;
#[cfg(full_widgets)]
pub mod menu_toolbar;
#[cfg(full_widgets)]
pub mod misc_widgets;
#[cfg(full_widgets)]
pub mod nav_widgets;
#[cfg(full_widgets)]
pub mod overlay_widgets;
pub mod registry;
#[cfg(full_widgets)]
pub mod special_widgets;
#[cfg(full_widgets)]
pub mod view_widgets;
#[cfg(full_widgets)]
pub mod web_widgets;
// Individual widget files (not in subfolders)
pub mod svg;
pub mod window;
pub use window::Window;

// Re-export base types
pub use base::BaseWidget;
// The value/error types and the property contract exist in every profile; the
// factory and its metadata do not, because they enumerate concrete controls.
#[cfg(widgets_unstripped)]
pub use capability::WidgetFactory;
pub use capability::{
    base_property_get, base_property_set, widget_property_get, widget_property_names,
    widget_property_set, CapabilityAccessError, CapabilityValue, PropertySchema, PropertyValueKind,
    WidgetCapability, WidgetProperties, BASE_PROPERTY_NAMES,
};
// The id-level accessors only exist where the capability layer does; the alloc-frugal
// profile compiles them out, so the re-export carries the same gate.
#[cfg(widgets_unstripped)]
pub use capability::{read_widget_property_by_id, write_widget_property_by_id};
pub use draw::Draw;
// The canonical types live in `crate::image`; re-exported here so a caller that
// already has `crate::widget` in scope does not need the second path.
#[cfg(feature = "image")]
pub use crate::image::Image;
#[cfg(feature = "image")]
pub use crate::image::ImageFormat;
pub use kind::WidgetKind;
pub use registry::SimpleRegistry;
pub use widget_trait::Widget;
// Re-export widget types from subfolders
#[cfg(widgets_unstripped)]
pub use base_widgets::toggle_button::{ToggleButton, ToggleButtonState};
pub use base_widgets::{
    button::{Button, ButtonState},
    checkbox::{CheckBox, CheckState},
    label::Label,
    radiobutton::RadioButton,
};
#[cfg(widgets_unstripped)]
pub use input_widgets::{
    auto_complete_edit::AutoCompleteEdit,
    command_link::CommandLink,
    editable_combo_box::EditableComboBox,
    font_combo_box::FontComboBox,
    ime_preedit::ImePreedit,
    inplace_editor::InplaceEditor,
    masked_edit::MaskedEdit,
    multi_select_combo_box::{MultiSelectComboBox, MultiSelectItem},
    range_slider::{RangeSlider, RangeSliderOrientation},
    rich_edit::RichEdit,
    search_bar::SearchBar,
    search_box::SearchBox,
    shortcut_editor::{ShortcutEditor, ShortcutEntry},
    tag_input::TagInput,
    textedit::TextEdit,
};
pub use input_widgets::{
    combobox::ComboBox,
    dropdown::Dropdown,
    keyboard::Keyboard,
    lineedit::{EchoMode, LineEdit},
    listbox::{ListBox, SelectionMode},
    spinbox::SpinBox,
    textarea::TextArea,
};
// Re-export container widgets
#[cfg(widgets_unstripped)]
pub use container_widgets::collapsible_pane::CollapsiblePane;
#[cfg(widgets_unstripped)]
pub use container_widgets::dockwidget::DockWidget;
pub use container_widgets::groupbox::GroupBox;
#[cfg(widgets_unstripped)]
pub use container_widgets::mdiarea::MdiArea;
pub use container_widgets::scrollarea::ScrollArea;
#[cfg(widgets_unstripped)]
pub use container_widgets::splitter::Splitter;
#[cfg(widgets_unstripped)]
pub use container_widgets::stackedwidget::StackedWidget;
#[cfg(widgets_unstripped)]
pub use container_widgets::tabwidget::TabWidget;
pub use container_widgets::tile_view::TileView;
#[cfg(widgets_unstripped)]
pub use container_widgets::toolbox::ToolBox;
/// Alias for [`GroupBox`], for callers that name the container a "panel".
/// Interchangeable with `GroupBox`; only the spelling differs.
pub type Panel = GroupBox;
pub use base_widgets::frame::Frame;
/// Alias for [`DockWidget`], for callers that think of a dockable region as a
/// panel. Used only when widgets are not stripped.
#[cfg(widgets_unstripped)]
pub type DockPanel = DockWidget;
// Re-export container widgets from new additions
#[cfg(widgets_unstripped)]
pub use container_widgets::carousel::Carousel;
#[cfg(widgets_unstripped)]
pub use container_widgets::masonry_layout::{MasonryItem, MasonryLayout};
#[cfg(widgets_unstripped)]
pub use container_widgets::pager_page_view::PagerPageView;
#[cfg(widgets_unstripped)]
pub use container_widgets::safe_area::{SafeArea, SafeAreaInsets};
#[cfg(widgets_unstripped)]
pub use container_widgets::stepper::Stepper;
// Re-export display widgets
pub use display_widgets::arc::Arc;
#[cfg(feature = "image")]
pub use display_widgets::image_view::ImageView;
#[cfg(widgets_unstripped)]
pub use display_widgets::lcd_number::LCDNumber;
pub use display_widgets::line::{Line, LineOrientation};
pub use display_widgets::meter::Meter;
pub use display_widgets::mini_canvas::MiniCanvas;
pub use display_widgets::mini_chart::MiniChart;
pub use display_widgets::progressbar::ProgressBar;
pub use display_widgets::roller::Roller;
pub use display_widgets::scrollbar::ScrollBar;
pub use display_widgets::slider::Slider;
pub use display_widgets::spinner::Spinner;
// Re-export display widgets from new additions
#[cfg(widgets_unstripped)]
pub use display_widgets::badge::Badge;
#[cfg(widgets_unstripped)]
pub use display_widgets::color_history::ColorHistory;
#[cfg(widgets_unstripped)]
pub use display_widgets::color_well::ColorWell;
#[cfg(widgets_unstripped)]
pub use display_widgets::divider::Divider;
#[cfg(widgets_unstripped)]
pub use display_widgets::empty_state::EmptyState;
#[cfg(widgets_unstripped)]
pub use display_widgets::floating_label::FloatingLabel;
#[cfg(widgets_unstripped)]
pub use display_widgets::font_preview::FontPreview;
#[cfg(widgets_unstripped)]
pub use display_widgets::icon::{Icon, IconName};
#[cfg(widgets_unstripped)]
pub use display_widgets::progress_circle::ProgressCircle;
#[cfg(widgets_unstripped)]
pub use display_widgets::rating::Rating;
#[cfg(widgets_unstripped)]
pub use display_widgets::skeleton_loader::SkeletonLoader;
pub use display_widgets::switch::Switch;
// Re-export nav widgets
#[cfg(full_widgets)]
pub use nav_widgets::adaptive_scaffold::AdaptiveScaffold;
#[cfg(full_widgets)]
pub use nav_widgets::app_bar::AppBar;
#[cfg(full_widgets)]
pub use nav_widgets::bottom_navigation_bar::BottomNavigationBar;
#[cfg(full_widgets)]
pub use nav_widgets::bottom_navigation_bar::NavItem;
#[cfg(full_widgets)]
pub use nav_widgets::navigation_drawer::NavigationDrawer;
#[cfg(full_widgets)]
pub use nav_widgets::navigation_stack::NavigationEvent;
#[cfg(full_widgets)]
pub use nav_widgets::navigation_stack::NavigationStack;
#[cfg(full_widgets)]
pub use nav_widgets::tab_view::TabPage;
#[cfg(full_widgets)]
pub use nav_widgets::tab_view::TabView;
// Re-export chart widgets
#[cfg(full_widgets)]
pub use chart_widgets::bar_chart::{BarChart, BarEntry};
#[cfg(full_widgets)]
pub use chart_widgets::line_chart::LineChart;
#[cfg(full_widgets)]
pub use chart_widgets::pie_chart::{PieChart, PieSlice};
#[cfg(full_widgets)]
pub use chart_widgets::sparkline::Sparkline;
// Re-export media widgets
#[cfg(full_widgets)]
pub use media_widgets::animated_image::{AnimatedFrame, AnimatedImage, AnimatedImageFormat};
#[cfg(full_widgets)]
pub use media_widgets::audio_visualizer::AudioVisualizer;
#[cfg(full_widgets)]
pub use media_widgets::camera_preview::CameraPreview;
#[cfg(full_widgets)]
pub use media_widgets::hero_animation::HeroAnimation;
#[cfg(full_widgets)]
pub use media_widgets::lottie_widget::LottieWidget;
#[cfg(full_widgets)]
pub use media_widgets::rive_widget::{RiveInput, RiveInputValue, RiveWidget};
#[cfg(full_widgets)]
pub use media_widgets::video_player::VideoPlayer;
// Re-export overlay widgets
#[cfg(full_widgets)]
pub use overlay_widgets::fab::FAB;
#[cfg(full_widgets)]
pub use overlay_widgets::refresh_control::RefreshControl;
/// Alias for [`RefreshControl`], naming it after the gesture it implements.
#[cfg(full_widgets)]
pub type PullToRefresh = RefreshControl;
#[cfg(full_widgets)]
pub use overlay_widgets::swipe_to_dismiss::SwipeToDismiss;
// Re-export cupertino widgets
#[cfg(full_widgets)]
pub use cupertino::{
    core::CupertinoAlertDialog, core::CupertinoSlider, core::CupertinoSwitch,
    core::MaterialNavigationRail, core::MaterialSnackbar, core::RailItem, CupertinoDatePicker,
    CupertinoNavigationBar, CupertinoSegmentedControl,
};
// Re-export misc widgets
#[cfg(full_widgets)]
pub use misc_widgets::avatar::Avatar;
#[cfg(full_widgets)]
pub use misc_widgets::barcode_scanner::{BarcodeFormat, BarcodeResult, BarcodeScanner};
#[cfg(full_widgets)]
pub use misc_widgets::bezier_curve_editor::BezierCurveEditor;
#[cfg(full_widgets)]
pub use misc_widgets::date_range_picker::DateRangePicker;
#[cfg(full_widgets)]
pub use misc_widgets::mobile_date_picker::MobileDatePicker;
#[cfg(full_widgets)]
pub use misc_widgets::qr_code::QRCode;
#[cfg(full_widgets)]
pub use misc_widgets::segmented_button::{Segment, SegmentedButton};
// Re-export web widgets
#[cfg(full_widgets)]
pub use web_widgets::web_engine::WebEngine;
/// Type alias for backward compatibility — `WebView` is now `WebEngineView`.
#[cfg(full_widgets)]
pub type WebView = WebEngineView;
#[cfg(full_widgets)]
pub use web_widgets::{
    WebEngineContextMenuRequest, WebEngineCookieStore, WebEngineDownloadItem,
    WebEngineFindTextResult, WebEngineNotification, WebEnginePage, WebEngineScriptDialog,
    WebEngineSettings, WebEngineView, WebEngineWebChannel,
};
// Re-export advanced widgets
#[cfg(full_widgets)]
pub use advanced_widgets::{
    calendar::Calendar, date_edit::DateEdit, date_time_edit::DateTimeEdit, dial::Dial,
    key_sequence_edit::KeySequenceEdit, pie_menu::PieMenu, pie_menu::PieMenuItem,
    ribbon_bar::RibbonBar, ribbon_bar::RibbonGroup, ribbon_bar::RibbonItem, tab_bar::TabBar,
    tab_bar::TabBarTab, time_edit::TimeEdit,
};
// Re-export dialog widgets
#[cfg(full_widgets)]
pub use dialog::{
    bottom_sheet::BottomSheet,
    color_dialog::ColorDialog,
    file_dialog::FileDialog,
    find_replace_dialog::FindReplaceDialog,
    font_dialog::FontDialog,
    input_dialog::InputDialog,
    message_box::MessageBox,
    modal_bottom_sheet::ModalBottomSheet,
    popover::Popover,
    popup_window::PopupWindow,
    progress_dialog::ProgressDialog,
    tooltip::Tooltip,
    wizard::{WizardDialog, WizardStep},
};
/// Generic dialog alias, currently resolving to [`PopupWindow`].
/// Not a distinct type: code that needs a dialog-specific API must name the
/// concrete dialog.
#[cfg(full_widgets)]
pub type Dialog = PopupWindow;
/// Alias for [`FileDialog`], for callers that only ever select directories.
/// Selecting files is not prevented by this alias — it is unchecked.
#[cfg(full_widgets)]
pub type DirectoryDialog = FileDialog;
// Re-export menu and toolbar widgets
#[cfg(full_widgets)]
pub use menu_toolbar::{
    action::Action,
    dropdown_menu::{DropdownItem, DropdownMenu},
    menu::Menu,
    menu_bar::MenuBar,
    menu_button::{MenuButton, MenuItem},
    status_bar::StatusBar,
    tool_bar::ToolBar,
    tool_button::ToolButton,
};
/// Alias for [`Menu`], naming the role rather than the control.
/// Context menus are ordinary menus shown at the pointer; the difference is
/// in how the caller shows them, not in the type.
#[cfg(full_widgets)]
pub type ContextMenu = Menu;
// Re-export view widgets
#[cfg(full_widgets)]
pub use view_widgets::table_widget::TableModel;
#[cfg(full_widgets)]
pub use view_widgets::tree_view::TreeModel;
#[cfg(full_widgets)]
pub use view_widgets::{
    data_grid::{ColumnFilter, DataGrid, SortSpec},
    grid_table::GridTableWidget,
    image_gallery::{GalleryImage, ImageGallery},
    list_view::{ListModel, ListView, VecListModel},
    properties_panel::{PropertiesPanel, PropertyEntry, PropertyValue},
    property_grid::{PropertyGrid, PropertyItem},
    table_widget::TableWidget,
    tree_table::{TreeTable, TreeTableModel},
    tree_view::TreeView,
    virtual_list::VirtualList,
    virtual_table::VirtualTable,
};
// Re-export special widgets
#[cfg(full_widgets)]
pub use special_widgets::{
    Breadcrumb, BreadcrumbSegment, Canvas, ChartWidget, Chip, ChipItem, CodeEditor, ColorPicker,
    CommandEntry, CommandPalette, DiagnosticMarker, DiffKind, DiffLine, DiffViewer,
    FreeformShapeWidget, GanttTask, GanttWidget, GridWidget, MapMarker, MapView, MarkdownEditor,
    MarkerSeverity, MediaPlayer, NotificationCenter, NotificationItem, NotificationLevel,
    SegmentItem, SegmentedControl, Snackbar, SplitAction, SplitButton, TerminalView, TimelineItem,
    TimelineWidget, ToastItem, ToastLevel, ToastStack,
};
/// Alias for [`ProgressBar`], naming an indicator use case.
/// This is a plain progress bar: it does not animate on its own.
#[cfg(full_widgets)]
pub type ActivityIndicator = ProgressBar;
/// Alias for [`ListBox`], naming the checklist use case.
/// Per-item checkboxes are **not** implied — this is a selectable list.
#[cfg(full_widgets)]
pub type CheckListBox = ListBox;
/// Alias for [`ToolBox`] declared here as well as re-exported above, so it
/// remains reachable under every gate. Identical to the `ToolBox` re-export.
#[cfg(full_widgets)]
pub type Toolbox = ToolBox;
/// Alias for [`SpinBox`] intended for floating-point input.
/// It is the same integer spin box: no decimal support is added by the alias.
#[cfg(full_widgets)]
pub type DoubleSpinBox = SpinBox;
/// Alias for [`WizardDialog`]; the `WidgetKind::Wizard` spelling.
#[cfg(full_widgets)]
pub type Wizard = WizardDialog;
// ── P3-6: WidgetKind variant type aliases ──
//
// Each alias renames a concrete control after the `WidgetKind` variant it
// corresponds to. They are pure renames: none adds behaviour, and none is a
// distinct type from its target, so they can be used interchangeably.

/// Alias for [`VirtualList`]; the `WidgetKind::DataView` spelling.
#[cfg(full_widgets)]
pub type DataView = VirtualList;
/// Alias for [`TreeView`]; the `WidgetKind::ColumnView` spelling. Despite the
/// name, this is a tree, not a column layout.
#[cfg(full_widgets)]
pub type ColumnView = TreeView;
/// Alias for [`ListView`]; the `WidgetKind::UndoView` spelling. Undo has to be
/// wired up by the caller — this is not an undo-aware view.
#[cfg(full_widgets)]
pub type UndoView = ListView;
/// Alias for [`DateEdit`]; the `WidgetKind::DatePicker` spelling.
#[cfg(full_widgets)]
pub type DatePicker = DateEdit;
/// Alias for [`TimeEdit`]; the `WidgetKind::TimePicker` spelling.
#[cfg(full_widgets)]
pub type TimePicker = TimeEdit;
/// Alias for [`DateTimeEdit`]; the `WidgetKind::DateTimePicker` spelling.
#[cfg(full_widgets)]
pub type DateTimePicker = DateTimeEdit;
/// Alias for [`GridWidget`]; the `WidgetKind::Grid` spelling.
#[cfg(full_widgets)]
pub type Grid = GridWidget;
/// Alias for [`ChartWidget`]; the `WidgetKind::Chart` spelling.
#[cfg(full_widgets)]
pub type Chart = ChartWidget;
/// Alias for [`GridTableWidget`]; the `WidgetKind::GridTable` spelling.
#[cfg(full_widgets)]
pub type GridTable = GridTableWidget;
/// Alias for [`TableWidget`]; the `WidgetKind::Table` spelling.
#[cfg(full_widgets)]
pub type Table = TableWidget;
/// Alias for [`FreeformShapeWidget`]; the `WidgetKind::FreeformShape` spelling.
#[cfg(full_widgets)]
pub type FreeformShape = FreeformShapeWidget;