#![deny(missing_docs)]
#![cfg_attr(feature = "mini", no_std)]
#![cfg_attr(test, allow(clippy::needless_pass_by_value, clippy::unwrap_used))]
extern crate alloc;
#[cfg(alloc_frugal)]
#[macro_use]
extern crate std;
pub mod compat;
pub mod action;
#[cfg(all(feature = "desktop-runtime", not(alloc_frugal)))]
pub mod asset;
#[cfg(feature = "audio")]
pub mod audio;
#[cfg(all(any(feature = "desktop", feature = "jni", feature = "mobile-api"), not(alloc_frugal)))]
pub mod bindings;
pub mod clipboard;
pub mod control_backend;
pub mod core;
pub mod data_binding;
#[cfg(designer_tooling)]
pub mod designer;
pub mod error;
pub mod event;
#[cfg(feature = "touch")]
pub mod gesture;
pub mod gpu;
#[cfg(feature = "i18n")]
pub mod i18n;
#[cfg(feature = "image")]
pub mod image;
#[cfg(full_widgets)]
pub mod json;
pub mod layout;
pub mod memory;
#[cfg(feature = "advanced-widgets")]
pub mod menu_config;
pub mod object;
pub mod performance;
pub mod platform;
pub mod quality;
pub mod render;
pub mod render_engine;
pub mod shortcut;
pub mod signal;
pub mod style;
pub mod test;
#[cfg(device_profile)]
pub mod theme;
pub mod undo;
#[cfg(feature = "video")]
pub mod video;
#[cfg(declarative_view)]
pub mod view;
#[cfg(widgets_unstripped)]
pub mod web;
#[cfg(feature = "gpu-wgpu")]
pub mod wgpu_backend;
pub mod widget;
#[cfg(not(alloc_frugal))]
pub use widget::a11y_submit;
#[cfg(full_widgets)]
pub use widget::advanced_widgets;
pub use widget::base;
pub use widget::base_property_get;
pub use widget::base_property_set;
pub use widget::base_widgets;
pub use widget::capability;
#[cfg(full_widgets)]
pub use widget::census;
#[cfg(full_widgets)]
pub use widget::chart_widgets;
#[cfg(widgets_unstripped)]
pub use widget::clear_registered_icons;
#[cfg(full_widgets)]
pub use widget::composite;
pub use widget::container_widgets;
#[cfg(full_widgets)]
pub use widget::cupertino;
pub use widget::decorations;
#[cfg(full_widgets)]
pub use widget::dialog;
pub use widget::display_widgets;
pub use widget::draw;
pub use widget::draw_bridge;
pub use widget::draw_icon_at;
pub use widget::draw_icon_centered;
#[cfg(feature = "image")]
pub use widget::draw_icon_image;
pub use widget::draw_icon_named;
pub use widget::fit_image_into;
#[cfg(widgets_unstripped)]
pub use widget::icon_registry;
pub use widget::icon_source;
pub use widget::icon_token_is_drawable;
pub use widget::input_widgets;
#[cfg(widgets_unstripped)]
pub use widget::is_registered_icon;
pub use widget::kind;
pub use widget::measure_icon;
#[cfg(full_widgets)]
pub use widget::media_widgets;
#[cfg(full_widgets)]
pub use widget::menu_toolbar;
pub use widget::metrics;
#[cfg(full_widgets)]
pub use widget::misc_widgets;
#[cfg(full_widgets)]
pub use widget::nav_widgets;
pub use widget::numeric;
#[cfg(full_widgets)]
pub use widget::overlay_widgets;
pub use widget::paint_icon;
#[cfg(widgets_unstripped)]
pub use widget::read_widget_property_by_id;
#[cfg(widgets_unstripped)]
pub use widget::register_icon;
#[cfg(widgets_unstripped)]
pub use widget::register_icon_on_grid;
#[cfg(widgets_unstripped)]
pub use widget::registered_icon;
#[cfg(widgets_unstripped)]
pub use widget::registered_icon_count;
pub use widget::registry;
#[cfg(not(alloc_frugal))]
pub use widget::runtime;
pub use widget::sample_data;
#[cfg(full_widgets)]
pub use widget::sample_fill;
#[cfg(full_widgets)]
pub use widget::special_widgets;
pub use widget::svg;
pub use widget::text_utils;
#[cfg(widgets_unstripped)]
pub use widget::try_register_icon;
#[cfg(widgets_unstripped)]
pub use widget::try_register_icon_on_grid;
pub use widget::validate_icon;
#[cfg(full_widgets)]
pub use widget::view_widgets;
#[cfg(full_widgets)]
pub use widget::web_widgets;
pub use widget::widget_property_get;
pub use widget::widget_property_names;
pub use widget::widget_property_set;
pub use widget::widget_trait;
pub use widget::window;
#[cfg(widgets_unstripped)]
pub use widget::write_widget_property_by_id;
#[cfg(full_widgets)]
pub use widget::Action;
#[cfg(full_widgets)]
pub use widget::ActivityIndicator;
#[cfg(full_widgets)]
pub use widget::AdaptiveScaffold;
#[cfg(full_widgets)]
pub use widget::AnimatedFrame;
#[cfg(full_widgets)]
pub use widget::AnimatedImage;
#[cfg(full_widgets)]
pub use widget::AnimatedImageFormat;
#[cfg(full_widgets)]
pub use widget::AppBar;
pub use widget::Arc;
#[cfg(full_widgets)]
pub use widget::AudioVisualizer;
#[cfg(widgets_unstripped)]
pub use widget::AutoCompleteEdit;
#[cfg(full_widgets)]
pub use widget::Avatar;
#[cfg(widgets_unstripped)]
pub use widget::Badge;
#[cfg(full_widgets)]
pub use widget::Banner;
#[cfg(full_widgets)]
pub use widget::BarChart;
#[cfg(full_widgets)]
pub use widget::BarEntry;
#[cfg(full_widgets)]
pub use widget::BarcodeFormat;
#[cfg(full_widgets)]
pub use widget::BarcodeResult;
#[cfg(full_widgets)]
pub use widget::BarcodeScanner;
pub use widget::BaseWidget;
#[cfg(full_widgets)]
pub use widget::BezierCurveEditor;
#[cfg(full_widgets)]
pub use widget::BottomNavigationBar;
#[cfg(full_widgets)]
pub use widget::BottomSheet;
#[cfg(full_widgets)]
pub use widget::Breadcrumb;
#[cfg(full_widgets)]
pub use widget::BreadcrumbSegment;
pub use widget::Button;
pub use widget::ButtonState;
#[cfg(full_widgets)]
pub use widget::Calendar;
#[cfg(full_widgets)]
pub use widget::CameraPreview;
#[cfg(full_widgets)]
pub use widget::Canvas;
pub use widget::CapabilityAccessError;
pub use widget::CapabilityValue;
#[cfg(widgets_unstripped)]
pub use widget::Carousel;
#[cfg(widgets_unstripped)]
pub use widget::CarouselIndicatorPosition;
#[cfg(widgets_unstripped)]
pub use widget::CarouselIndicatorStyle;
#[cfg(widgets_unstripped)]
pub use widget::CarouselPage;
#[cfg(full_widgets)]
pub use widget::Cascader;
#[cfg(full_widgets)]
pub use widget::CascaderOption;
#[cfg(full_widgets)]
pub use widget::Chart;
#[cfg(full_widgets)]
pub use widget::ChartWidget;
pub use widget::CheckBox;
#[cfg(full_widgets)]
pub use widget::CheckListBox;
pub use widget::CheckState;
#[cfg(full_widgets)]
pub use widget::Chip;
#[cfg(full_widgets)]
pub use widget::ChipItem;
#[cfg(full_widgets)]
pub use widget::CodeEditor;
#[cfg(widgets_unstripped)]
pub use widget::CollapsiblePane;
#[cfg(full_widgets)]
pub use widget::ColorDialog;
#[cfg(widgets_unstripped)]
pub use widget::ColorHistory;
#[cfg(full_widgets)]
pub use widget::ColorPicker;
#[cfg(widgets_unstripped)]
pub use widget::ColorWell;
#[cfg(full_widgets)]
pub use widget::ColumnFilter;
#[cfg(full_widgets)]
pub use widget::ColumnView;
pub use widget::ComboBox;
#[cfg(full_widgets)]
pub use widget::CommandEntry;
#[cfg(widgets_unstripped)]
pub use widget::CommandLink;
#[cfg(full_widgets)]
pub use widget::CommandPalette;
#[cfg(full_widgets)]
pub use widget::CompletedMention;
#[cfg(full_widgets)]
pub use widget::ContextMenu;
#[cfg(full_widgets)]
pub use widget::CupertinoAlertDialog;
#[cfg(full_widgets)]
pub use widget::CupertinoDatePicker;
#[cfg(full_widgets)]
pub use widget::CupertinoNavigationBar;
#[cfg(full_widgets)]
pub use widget::CupertinoSegmentedControl;
#[cfg(full_widgets)]
pub use widget::CupertinoSlider;
#[cfg(full_widgets)]
pub use widget::CupertinoSwitch;
#[cfg(full_widgets)]
pub use widget::DataGrid;
#[cfg(full_widgets)]
pub use widget::DataView;
#[cfg(full_widgets)]
pub use widget::DateEdit;
#[cfg(full_widgets)]
pub use widget::DatePicker;
#[cfg(full_widgets)]
pub use widget::DateRangePicker;
#[cfg(full_widgets)]
pub use widget::DateTimeEdit;
#[cfg(full_widgets)]
pub use widget::DateTimePicker;
#[cfg(full_widgets)]
pub use widget::DiagnosticMarker;
#[cfg(full_widgets)]
pub use widget::Dial;
#[cfg(full_widgets)]
pub use widget::Dialog;
#[cfg(full_widgets)]
pub use widget::DiffKind;
#[cfg(full_widgets)]
pub use widget::DiffLine;
#[cfg(full_widgets)]
pub use widget::DiffViewer;
#[cfg(full_widgets)]
pub use widget::DirectoryDialog;
#[cfg(widgets_unstripped)]
pub use widget::Divider;
#[cfg(widgets_unstripped)]
pub use widget::DockPanel;
#[cfg(widgets_unstripped)]
pub use widget::DockWidget;
#[cfg(full_widgets)]
pub use widget::DoubleSpinBox;
pub use widget::Draw;
#[cfg(full_widgets)]
pub use widget::DropZone;
pub use widget::Dropdown;
#[cfg(full_widgets)]
pub use widget::DropdownItem;
#[cfg(full_widgets)]
pub use widget::DropdownMenu;
pub use widget::EchoMode;
#[cfg(widgets_unstripped)]
pub use widget::EditableComboBox;
#[cfg(full_widgets)]
pub use widget::EmojiGlyph;
#[cfg(full_widgets)]
pub use widget::EmojiPicker;
#[cfg(widgets_unstripped)]
pub use widget::EmptyState;
#[cfg(full_widgets)]
pub use widget::FileDialog;
#[cfg(full_widgets)]
pub use widget::FilterCondition;
#[cfg(full_widgets)]
pub use widget::FilterConjunction;
#[cfg(full_widgets)]
pub use widget::FilterExpr;
#[cfg(full_widgets)]
pub use widget::FilterField;
#[cfg(full_widgets)]
pub use widget::FilterOperator;
#[cfg(full_widgets)]
pub use widget::FindReplaceDialog;
#[cfg(widgets_unstripped)]
pub use widget::FloatingLabel;
#[cfg(widgets_unstripped)]
pub use widget::FontComboBox;
#[cfg(full_widgets)]
pub use widget::FontDialog;
#[cfg(widgets_unstripped)]
pub use widget::FontPreview;
pub use widget::Frame;
#[cfg(full_widgets)]
pub use widget::FreeformShape;
#[cfg(full_widgets)]
pub use widget::FreeformShapeWidget;
#[cfg(full_widgets)]
pub use widget::GalleryImage;
#[cfg(full_widgets)]
pub use widget::GanttTask;
#[cfg(full_widgets)]
pub use widget::GanttWidget;
#[cfg(full_widgets)]
pub use widget::Grid;
#[cfg(full_widgets)]
pub use widget::GridTable;
#[cfg(full_widgets)]
pub use widget::GridTableWidget;
#[cfg(full_widgets)]
pub use widget::GridWidget;
pub use widget::GroupBox;
#[cfg(full_widgets)]
pub use widget::Heatmap;
#[cfg(full_widgets)]
pub use widget::HeatmapCell;
#[cfg(full_widgets)]
pub use widget::HeroAnimation;
#[cfg(widgets_unstripped)]
pub use widget::Icon;
pub use widget::IconColorMode;
pub use widget::IconData;
pub use widget::IconItemError;
pub use widget::IconMetrics;
pub use widget::IconName;
pub use widget::IconPaintError;
pub use widget::IconPaintOutcome;
pub use widget::IconRef;
#[cfg(widgets_unstripped)]
pub use widget::IconRegistrationError;
pub use widget::IconResourceResolver;
pub use widget::IconSource;
pub use widget::IconSourceMetadata;
pub use widget::IconSpec;
#[cfg(feature = "image")]
pub use widget::Image;
#[cfg(feature = "image")]
pub use widget::ImageFormat;
#[cfg(full_widgets)]
pub use widget::ImageGallery;
#[cfg(feature = "image")]
pub use widget::ImageView;
#[cfg(widgets_unstripped)]
pub use widget::ImePreedit;
#[cfg(widgets_unstripped)]
pub use widget::InplaceEditor;
#[cfg(full_widgets)]
pub use widget::InputDialog;
#[cfg(full_widgets)]
pub use widget::KanbanBoard;
#[cfg(full_widgets)]
pub use widget::KanbanCard;
#[cfg(full_widgets)]
pub use widget::KanbanColumn;
#[cfg(full_widgets)]
pub use widget::KeySequenceEdit;
pub use widget::Keyboard;
#[cfg(widgets_unstripped)]
pub use widget::LCDNumber;
pub use widget::Label;
pub use widget::Line;
#[cfg(full_widgets)]
pub use widget::LineChart;
pub use widget::LineEdit;
pub use widget::LineOrientation;
pub use widget::ListBox;
#[cfg(full_widgets)]
pub use widget::ListModel;
#[cfg(full_widgets)]
pub use widget::ListView;
#[cfg(full_widgets)]
pub use widget::LottieWidget;
#[cfg(full_widgets)]
pub use widget::MapMarker;
#[cfg(full_widgets)]
pub use widget::MapView;
#[cfg(full_widgets)]
pub use widget::MarkdownEditor;
#[cfg(full_widgets)]
pub use widget::MarkerSeverity;
#[cfg(widgets_unstripped)]
pub use widget::MaskedEdit;
#[cfg(widgets_unstripped)]
pub use widget::MasonryItem;
#[cfg(widgets_unstripped)]
pub use widget::MasonryLayout;
#[cfg(full_widgets)]
pub use widget::MaterialNavigationRail;
#[cfg(full_widgets)]
pub use widget::MaterialSnackbar;
#[cfg(widgets_unstripped)]
pub use widget::MdiArea;
#[cfg(full_widgets)]
pub use widget::MediaPlayer;
#[cfg(full_widgets)]
pub use widget::Mention;
#[cfg(full_widgets)]
pub use widget::MentionCandidate;
#[cfg(full_widgets)]
pub use widget::Menu;
#[cfg(full_widgets)]
pub use widget::MenuBar;
#[cfg(full_widgets)]
pub use widget::MenuButton;
#[cfg(full_widgets)]
pub use widget::MenuItem;
#[cfg(full_widgets)]
pub use widget::MessageBox;
pub use widget::Meter;
pub use widget::MiniCanvas;
pub use widget::MiniChart;
#[cfg(full_widgets)]
pub use widget::MobileDatePicker;
#[cfg(full_widgets)]
pub use widget::ModalBottomSheet;
#[cfg(widgets_unstripped)]
pub use widget::MultiSelectComboBox;
#[cfg(widgets_unstripped)]
pub use widget::MultiSelectItem;
#[cfg(full_widgets)]
pub use widget::NavItem;
#[cfg(full_widgets)]
pub use widget::NavigationDrawer;
#[cfg(full_widgets)]
pub use widget::NavigationEvent;
#[cfg(full_widgets)]
pub use widget::NavigationStack;
#[cfg(full_widgets)]
pub use widget::NotificationCenter;
#[cfg(full_widgets)]
pub use widget::NotificationItem;
#[cfg(full_widgets)]
pub use widget::NotificationLevel;
#[cfg(widgets_unstripped)]
pub use widget::NumberPicker;
#[cfg(widgets_unstripped)]
pub use widget::OtpInput;
#[cfg(full_widgets)]
pub use widget::Pagination;
pub use widget::Panel;
#[cfg(full_widgets)]
pub use widget::PieChart;
#[cfg(full_widgets)]
pub use widget::PieMenu;
#[cfg(full_widgets)]
pub use widget::PieMenuItem;
#[cfg(full_widgets)]
pub use widget::PieSlice;
#[cfg(full_widgets)]
pub use widget::Popover;
#[cfg(full_widgets)]
pub use widget::PopupWindow;
pub use widget::ProgressBar;
#[cfg(widgets_unstripped)]
pub use widget::ProgressCircle;
#[cfg(full_widgets)]
pub use widget::ProgressDialog;
#[cfg(full_widgets)]
pub use widget::PropertiesPanel;
#[cfg(full_widgets)]
pub use widget::PropertyEntry;
#[cfg(full_widgets)]
pub use widget::PropertyGrid;
#[cfg(full_widgets)]
pub use widget::PropertyItem;
pub use widget::PropertySchema;
#[cfg(full_widgets)]
pub use widget::PropertyValue;
pub use widget::PropertyValueKind;
#[cfg(full_widgets)]
pub use widget::PullToRefresh;
#[cfg(full_widgets)]
pub use widget::QRCode;
#[cfg(full_widgets)]
pub use widget::QueryBuilder;
#[cfg(full_widgets)]
pub use widget::QueryBuilderRow;
#[cfg(full_widgets)]
pub use widget::RadarChart;
pub use widget::RadioButton;
#[cfg(full_widgets)]
pub use widget::RailItem;
#[cfg(widgets_unstripped)]
pub use widget::RangeSlider;
#[cfg(widgets_unstripped)]
pub use widget::RangeSliderOrientation;
#[cfg(widgets_unstripped)]
pub use widget::Rating;
#[cfg(full_widgets)]
pub use widget::RefreshControl;
#[cfg(widgets_unstripped)]
pub use widget::RegisteredIcon;
#[cfg(full_widgets)]
pub use widget::RibbonBar;
#[cfg(full_widgets)]
pub use widget::RibbonGroup;
#[cfg(full_widgets)]
pub use widget::RibbonItem;
#[cfg(widgets_unstripped)]
pub use widget::RichEdit;
#[cfg(full_widgets)]
pub use widget::RiveInput;
#[cfg(full_widgets)]
pub use widget::RiveInputValue;
#[cfg(full_widgets)]
pub use widget::RiveWidget;
pub use widget::Roller;
#[cfg(widgets_unstripped)]
pub use widget::SafeArea;
#[cfg(widgets_unstripped)]
pub use widget::SafeAreaInsets;
pub use widget::ScrollArea;
pub use widget::ScrollBar;
#[cfg(widgets_unstripped)]
pub use widget::SearchBar;
#[cfg(widgets_unstripped)]
pub use widget::SearchBox;
#[cfg(full_widgets)]
pub use widget::Segment;
#[cfg(full_widgets)]
pub use widget::SegmentItem;
#[cfg(full_widgets)]
pub use widget::SegmentedButton;
#[cfg(full_widgets)]
pub use widget::SegmentedControl;
pub use widget::SelectionMode;
#[cfg(all(feature = "image", not(alloc_frugal)))]
pub use widget::SharedIconPixels;
#[cfg(widgets_unstripped)]
pub use widget::ShortcutEditor;
#[cfg(widgets_unstripped)]
pub use widget::ShortcutEntry;
#[cfg(full_widgets)]
pub use widget::SignaturePad;
#[cfg(full_widgets)]
pub use widget::SignatureStroke;
pub use widget::SimpleRegistry;
#[cfg(widgets_unstripped)]
pub use widget::SkeletonLoader;
pub use widget::Slider;
#[cfg(full_widgets)]
pub use widget::Snackbar;
#[cfg(full_widgets)]
pub use widget::SortSpec;
#[cfg(full_widgets)]
pub use widget::Sparkline;
pub use widget::SpinBox;
pub use widget::Spinner;
#[cfg(full_widgets)]
pub use widget::SplashScreen;
#[cfg(full_widgets)]
pub use widget::SplitAction;
#[cfg(full_widgets)]
pub use widget::SplitButton;
#[cfg(widgets_unstripped)]
pub use widget::Splitter;
#[cfg(widgets_unstripped)]
pub use widget::StackedWidget;
#[cfg(full_widgets)]
pub use widget::StatusBar;
#[cfg(widgets_unstripped)]
pub use widget::Stepper;
pub use widget::StickyRegion;
#[cfg(full_widgets)]
pub use widget::SwipeToDismiss;
pub use widget::Switch;
#[cfg(full_widgets)]
pub use widget::TabBar;
#[cfg(full_widgets)]
pub use widget::TabBarTab;
#[cfg(full_widgets)]
pub use widget::TabPage;
#[cfg(full_widgets)]
pub use widget::TabView;
#[cfg(widgets_unstripped)]
pub use widget::TabWidget;
#[cfg(full_widgets)]
pub use widget::Table;
#[cfg(full_widgets)]
pub use widget::TableModel;
#[cfg(full_widgets)]
pub use widget::TableWidget;
#[cfg(widgets_unstripped)]
pub use widget::TagInput;
#[cfg(full_widgets)]
pub use widget::TerminalView;
pub use widget::TextArea;
#[cfg(widgets_unstripped)]
pub use widget::TextEdit;
#[cfg(full_widgets)]
pub use widget::TimeEdit;
#[cfg(full_widgets)]
pub use widget::TimePicker;
#[cfg(full_widgets)]
pub use widget::TimelineItem;
#[cfg(full_widgets)]
pub use widget::TimelineWidget;
#[cfg(full_widgets)]
pub use widget::Toast;
#[cfg(full_widgets)]
pub use widget::ToastItem;
#[cfg(full_widgets)]
pub use widget::ToastLevel;
#[cfg(full_widgets)]
pub use widget::ToastStack;
#[cfg(widgets_unstripped)]
pub use widget::ToggleButton;
#[cfg(widgets_unstripped)]
pub use widget::ToggleButtonState;
#[cfg(full_widgets)]
pub use widget::ToolBar;
#[cfg(widgets_unstripped)]
pub use widget::ToolBox;
#[cfg(full_widgets)]
pub use widget::ToolButton;
#[cfg(widgets_unstripped)]
pub use widget::Toolbox;
#[cfg(full_widgets)]
pub use widget::Tooltip;
#[cfg(full_widgets)]
pub use widget::TreeModel;
#[cfg(full_widgets)]
pub use widget::TreeTable;
#[cfg(full_widgets)]
pub use widget::TreeTableModel;
#[cfg(full_widgets)]
pub use widget::TreeView;
#[cfg(full_widgets)]
pub use widget::UndoView;
#[cfg(full_widgets)]
pub use widget::VecListModel;
#[cfg(full_widgets)]
pub use widget::VideoPlayer;
#[cfg(full_widgets)]
pub use widget::VirtualList;
#[cfg(full_widgets)]
pub use widget::VirtualTable;
#[cfg(full_widgets)]
pub use widget::WebEngine;
#[cfg(full_widgets)]
pub use widget::WebEngineContextMenuRequest;
#[cfg(full_widgets)]
pub use widget::WebEngineCookieStore;
#[cfg(full_widgets)]
pub use widget::WebEngineDownloadItem;
#[cfg(full_widgets)]
pub use widget::WebEngineFindTextResult;
#[cfg(full_widgets)]
pub use widget::WebEngineNotification;
#[cfg(full_widgets)]
pub use widget::WebEnginePage;
#[cfg(full_widgets)]
pub use widget::WebEngineScriptDialog;
#[cfg(full_widgets)]
pub use widget::WebEngineSettings;
#[cfg(full_widgets)]
pub use widget::WebEngineView;
#[cfg(full_widgets)]
pub use widget::WebEngineWebChannel;
#[cfg(full_widgets)]
pub use widget::WebView;
pub use widget::Widget;
#[cfg(widgets_unstripped)]
pub use widget::WidgetAndDraw;
pub use widget::WidgetCapability;
#[cfg(widgets_unstripped)]
pub use widget::WidgetFactory;
pub use widget::WidgetKind;
pub use widget::WidgetProperties;
pub use widget::Window;
#[cfg(full_widgets)]
pub use widget::Wizard;
#[cfg(full_widgets)]
pub use widget::WizardDialog;
#[cfg(full_widgets)]
pub use widget::WizardStep;
pub use widget::BASE_PROPERTY_NAMES;
#[cfg(full_widgets)]
pub use widget::FAB;
#[cfg(widgets_unstripped)]
pub use widget::MAX_REGISTERED_ICONS;
#[cfg(not(alloc_frugal))]
pub use widget::runtime::{
animation_suspended, drive_frame, last_frame_stats, notify_native_redraw, report_state,
request_repaint_because, set_animation_suspended, FrameOutcome, FrameStats, RepaintReason,
StateFact,
};
#[cfg(alloc_frugal)]
pub fn set_animation_suspended(_suspended: bool) {}
#[cfg(alloc_frugal)]
pub fn animation_suspended() -> bool {
false
}
#[cfg(alloc_frugal)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct FrameOutcome {
pub events_dispatched: usize,
pub controls_ticked: usize,
pub repaints_submitted: usize,
pub needs_another_frame: bool,
}
#[cfg(alloc_frugal)]
pub fn drive_frame(_delta_ms: u32) -> FrameOutcome {
FrameOutcome::default()
}
#[cfg(feature = "i18n")]
pub fn translate_key(key: &str) -> crate::compat::String {
crate::i18n::translate(key)
}
#[cfg(not(feature = "i18n"))]
pub fn translate_key(key: &str) -> crate::compat::String {
log::warn!("i18n translate_key called but the i18n feature is disabled, key={key}");
crate::compat::String::from(key)
}
#[cfg(not(feature = "i18n"))]
#[macro_export]
macro_rules! tr {
($key:expr) => {{
log::warn!("i18n tr! called but the i18n feature is disabled, key={}", $key);
$key.to_string()
}};
($key:expr, $count:expr) => {{
log::warn!("i18n tr! called but the i18n feature is disabled, key={}", $key);
$key.to_string()
}};
($key:expr, $context:expr, $count:expr) => {{
log::warn!("i18n tr! called but the i18n feature is disabled, key={}", $key);
$key.to_string()
}};
}
#[cfg(not(feature = "i18n"))]
#[macro_export]
macro_rules! tr_into {
($key:expr, $out:expr) => {{
log::warn!("i18n tr_into! called but the i18n feature is disabled, key={}", $key);
$out.push_str($key);
}};
($key:expr, $count:expr, $out:expr) => {{
log::warn!("i18n tr_into! called but the i18n feature is disabled, key={}", $key);
let _ = $count;
$out.push_str($key);
}};
($key:expr, $context:expr, $count:expr, $out:expr) => {{
log::warn!("i18n tr_into! called but the i18n feature is disabled, key={}", $key);
let _ = ($context, $count);
$out.push_str($key);
}};
}
#[cfg(full_widgets)]
pub mod app;
pub mod index;
#[cfg(feature = "pdf")]
pub mod pdf;
#[cfg(feature = "print")]
pub mod print;
pub fn init() {
trace_runtime_route("init");
platform::profile::runtime_init();
platform::profile::init_optional_subsystems();
#[cfg(feature = "advanced-widgets")]
crate::menu_config::init();
}
pub fn run() {
trace_runtime_route("run");
platform::profile::runtime_run();
}
pub fn quit() -> bool {
trace_runtime_route("quit");
platform::profile::runtime_quit()
}
pub(crate) fn trace_runtime_route(stage: &str) {
if std::env::var("RUST_WIDGETS_TRACE_RUNTIME").ok().as_deref() != Some("1") {
return;
}
let line = format!(
"[rust_widgets.runtime] stage={} profile={} backend={} route={} host={}",
stage,
platform::profile::profile_name(),
platform::platform_facts().backend_name(),
platform::profile::route_name(),
platform::profile::host_name()
);
log::info!("{line}");
eprintln!("{line}");
}
#[cfg(not(alloc_frugal))]
fn backend_for_kind(kind: widget::WidgetKind) -> &'static dyn control_backend::ControlBackend {
control_backend::get_control_backend_for_widget(kind)
}
#[cfg(all(not(alloc_frugal), not(widgets_unstripped)))]
const NO_SUCH_CONTROL: crate::core::ObjectId = 0;
#[cfg(not(alloc_frugal))]
pub fn create_window(
title: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::Window).create_window(title, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_button(
parent: crate::core::ObjectId,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::Button).create_button(parent, text, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_checkbox(
parent: crate::core::ObjectId,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::CheckBox)
.create_checkbox(parent, text, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_line_edit(
parent: crate::core::ObjectId,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::LineEdit)
.create_line_edit(parent, text, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_label(
parent: crate::core::ObjectId,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::Label).create_label(parent, text, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_radio_button(
parent: crate::core::ObjectId,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::RadioButton)
.create_radio_button(parent, text, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_slider(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::Slider).create_slider(parent, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_progress_bar(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::ProgressBar)
.create_progress_bar(parent, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_combo_box(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::ComboBox).create_combo_box(parent, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_list_box(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::ListBox).create_list_box(parent, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_panel(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::Panel).create_panel(parent, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_message_box(
parent: crate::core::ObjectId,
title: &str,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
#[cfg(widgets_unstripped)]
{
backend_for_kind(widget::WidgetKind::MessageBox)
.create_message_box(parent, title, text, x, y, width, height)
}
#[cfg(not(widgets_unstripped))]
{
let _ = (parent, title, text, x, y, width, height);
NO_SUCH_CONTROL
}
}
#[cfg(not(alloc_frugal))]
pub fn create_file_dialog(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
#[cfg(widgets_unstripped)]
{
backend_for_kind(widget::WidgetKind::FileDialog)
.create_file_dialog(parent, "", x, y, width, height)
}
#[cfg(not(widgets_unstripped))]
{
let _ = (parent, x, y, width, height);
NO_SUCH_CONTROL
}
}
#[cfg(not(alloc_frugal))]
pub fn create_color_dialog(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
#[cfg(widgets_unstripped)]
{
backend_for_kind(widget::WidgetKind::ColorDialog)
.create_color_dialog(parent, "", x, y, width, height)
}
#[cfg(not(widgets_unstripped))]
{
let _ = (parent, x, y, width, height);
NO_SUCH_CONTROL
}
}
#[cfg(not(alloc_frugal))]
pub fn create_font_dialog(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
#[cfg(widgets_unstripped)]
{
backend_for_kind(widget::WidgetKind::FontDialog)
.create_font_dialog(parent, "", x, y, width, height)
}
#[cfg(not(widgets_unstripped))]
{
let _ = (parent, x, y, width, height);
NO_SUCH_CONTROL
}
}
#[cfg(not(alloc_frugal))]
pub fn create_spin_box(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::SpinBox).create_spin_box(parent, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn create_list_view(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
#[cfg(widgets_unstripped)]
{
backend_for_kind(widget::WidgetKind::ListView).create_list_view(parent, x, y, width, height)
}
#[cfg(not(widgets_unstripped))]
{
let _ = (parent, x, y, width, height);
NO_SUCH_CONTROL
}
}
#[cfg(not(alloc_frugal))]
pub fn create_scroll_area(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::ScrollArea).create_scroll_area(parent, x, y, width, height)
}
#[cfg(widgets_unstripped)]
pub fn create_tab_widget(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::TabWidget).create_tab_widget(parent, x, y, width, height)
}
#[cfg(widgets_unstripped)]
pub fn create_splitter(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::Splitter).create_splitter(parent, x, y, width, height)
}
#[cfg(widgets_unstripped)]
pub fn create_grid_widget(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::Grid).create_grid(parent, x, y, width, height)
}
#[cfg(widgets_unstripped)]
pub fn create_dialog(
parent: crate::core::ObjectId,
title: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
backend_for_kind(widget::WidgetKind::Dialog).create_dialog(parent, title, x, y, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn mount_surface(
parent: crate::core::ObjectId,
id: crate::core::ObjectId,
rect: crate::core::Rect,
) -> bool {
platform::get_platform().mount_surface(parent, id, rect)
}
#[cfg(not(alloc_frugal))]
pub fn resize_surface(id: crate::core::ObjectId, rect: crate::core::Rect) -> bool {
platform::get_platform().resize_surface(id, rect)
}
#[cfg(not(alloc_frugal))]
pub fn unmount_surface(id: crate::core::ObjectId) -> bool {
platform::get_platform().unmount_surface(id)
}
#[cfg(not(alloc_frugal))]
pub fn invalidate_surface(id: crate::core::ObjectId) -> bool {
platform::get_platform().invalidate_surface(id)
}
#[cfg(not(alloc_frugal))]
pub fn invalidate_surface_rect(id: crate::core::ObjectId, rect: crate::core::Rect) -> bool {
platform::get_platform().invalidate_surface_rect(id, rect)
}
#[cfg(alloc_frugal)]
pub fn invalidate_surface_rect(_id: crate::core::ObjectId, _rect: crate::core::Rect) -> bool {
false
}
#[cfg(not(alloc_frugal))]
pub fn take_pending_repaint() -> Option<crate::core::ObjectId> {
platform::get_platform().take_pending_repaint()
}
#[cfg(alloc_frugal)]
pub fn take_pending_repaint() -> Option<crate::core::ObjectId> {
None
}
#[cfg(not(alloc_frugal))]
pub fn supports_surfaces() -> bool {
platform::get_platform().supports_surfaces()
}
#[cfg(not(alloc_frugal))]
pub fn dispatch_pointer_event(
root: crate::core::ObjectId,
event: &crate::event::Event,
point: crate::core::Point,
) -> bool {
platform::get_platform().route_pointer_event(root, event, point)
}
#[cfg(alloc_frugal)]
pub fn dispatch_pointer_event(
_root: crate::core::ObjectId,
_event: &crate::event::Event,
_point: crate::core::Point,
) -> bool {
false
}
#[cfg(not(alloc_frugal))]
pub fn dispatch_event(widget_id: crate::core::ObjectId, event: &crate::event::Event) -> bool {
crate::widget::runtime::dispatch_event(widget_id, event)
}
#[cfg(alloc_frugal)]
pub fn dispatch_event(_widget_id: crate::core::ObjectId, _event: &crate::event::Event) -> bool {
false
}
#[cfg(not(alloc_frugal))]
fn apply_active_theme(widget: &mut Box<dyn widget::Widget>) {
#[cfg(device_profile)]
{
crate::theme::apply_active_theme(&mut **widget);
}
#[cfg(not(device_profile))]
{
let _ = widget;
}
}
#[cfg(not(alloc_frugal))]
pub fn reapply_active_theme() {
#[cfg(device_profile)]
{
widget::runtime::for_each_mounted_widget(|_id, widget| {
crate::theme::apply_active_theme(widget);
});
}
}
#[cfg(not(alloc_frugal))]
pub fn apply_environment_appearance() -> bool {
#[cfg(device_profile)]
{
let changed = crate::theme::global_theme_manager().follow_environment_appearance();
if changed {
reapply_active_theme();
}
changed
}
#[cfg(not(device_profile))]
{
false
}
}
#[cfg(not(alloc_frugal))]
fn mount_widget_object(
parent: crate::core::ObjectId,
mut widget: Box<dyn widget::Widget>,
rect: crate::core::Rect,
) -> Result<crate::core::ObjectId, widget::runtime::SurfaceMountError> {
use widget::runtime::SurfaceMountError;
apply_active_theme(&mut widget);
let id = widget::runtime::register(widget).ok_or(SurfaceMountError::NoRegistryOnThread)?;
widget::runtime::set_geometry(id, rect);
widget::runtime::set_surface_window(id, parent);
let host_parent = widget::runtime::host_window_for(parent).unwrap_or(parent);
if !platform::get_platform().mount_surface(host_parent, id, rect) {
widget::runtime::unregister(id);
if !supports_surfaces() {
return Err(SurfaceMountError::UnsupportedByBackend(backend_name()));
}
return Err(SurfaceMountError::RejectedByBackend(backend_name()));
}
Ok(id)
}
#[cfg(not(alloc_frugal))]
pub fn create_widget_of_kind(
kind: widget::WidgetKind,
parent: crate::core::ObjectId,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
widget: Option<Box<dyn widget::Widget>>,
) -> crate::core::ObjectId {
let rect = crate::core::Rect::new(x, y, width, height);
let widget = widget.or_else(|| {
#[cfg(all(device_profile, full_widgets))]
{
let factory = widget::WidgetFactory::shared();
factory.create_by_kind(kind, rect, text).or_else(|| {
let name = widget::capability::factory_name_for_kind(kind)?;
factory.create(name, rect, text)
})
}
#[cfg(not(all(device_profile, full_widgets)))]
{
let _ = (text, rect);
None
}
});
let Some(widget) = widget else {
log::warn!(
"create_widget_of_kind: no constructor for {kind:?} and no widget object was \
supplied; returning 0"
);
return 0;
};
if !supports_surfaces() {
if kind != widget::WidgetKind::Window
&& (parent == 0 || !widget::runtime::is_mounted(parent))
{
log::warn!(
"create_widget_of_kind: refusing to create {kind:?} under parent {parent}, which \
addresses no live container; returning 0"
);
return 0;
}
let id = control_backend::get_control_backend().mount_widget_box(widget, Some(parent), 0);
if id == 0 {
log::warn!(
"create_widget_of_kind: {kind:?} could neither be hosted on a platform \
surface nor adopted by the widget-tree backend; returning 0"
);
}
return id;
}
match mount_widget_object(parent, widget, rect) {
Ok(id) => id,
Err(error) => {
log::warn!("create_widget_of_kind: cannot host {kind:?}: {error}");
0
}
}
}
#[cfg(alloc_frugal)]
pub fn mount_surface(
_parent: crate::core::ObjectId,
_id: crate::core::ObjectId,
_rect: crate::core::Rect,
) -> bool {
false
}
#[cfg(alloc_frugal)]
pub fn resize_surface(_id: crate::core::ObjectId, _rect: crate::core::Rect) -> bool {
false
}
#[cfg(alloc_frugal)]
pub fn unmount_surface(_id: crate::core::ObjectId) -> bool {
false
}
#[cfg(alloc_frugal)]
pub fn invalidate_surface(_id: crate::core::ObjectId) -> bool {
false
}
#[cfg(alloc_frugal)]
pub fn supports_surfaces() -> bool {
false
}
#[cfg(not(alloc_frugal))]
pub fn show_widget(widget_id: crate::core::ObjectId) {
control_backend::get_control_backend().set_widget_visible(widget_id, true);
}
#[cfg(not(alloc_frugal))]
pub fn hide_widget(widget_id: crate::core::ObjectId) {
control_backend::get_control_backend().set_widget_visible(widget_id, false);
}
#[cfg(not(alloc_frugal))]
pub fn close_widget(widget_id: crate::core::ObjectId) -> bool {
crate::widget::runtime::with_widget_mut(widget_id, |widget| {
widget.base().closed.emit();
if let Some(reference) = widget.event_signal_dyn("closed") {
reference.emit_unit();
}
})
.is_some()
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_geometry(
widget_id: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) {
control_backend::get_control_backend().set_widget_geometry(widget_id, x, y, width, height);
}
#[cfg(not(alloc_frugal))]
pub fn widget_geometry(widget_id: crate::core::ObjectId) -> Option<(i32, i32, u32, u32)> {
control_backend::get_control_backend().get_widget_geometry(widget_id)
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_text(widget_id: crate::core::ObjectId, text: &str) {
control_backend::get_control_backend().set_widget_text(widget_id, text);
}
#[cfg(not(alloc_frugal))]
pub fn get_widget_text(widget_id: crate::core::ObjectId) -> String {
control_backend::get_control_backend().get_widget_text(widget_id)
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_enabled(widget_id: crate::core::ObjectId, enabled: bool) {
control_backend::get_control_backend().set_widget_enabled(widget_id, enabled);
}
#[cfg(not(alloc_frugal))]
pub fn is_widget_enabled(widget_id: crate::core::ObjectId) -> bool {
control_backend::get_control_backend().is_widget_enabled(widget_id)
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_visible(widget_id: crate::core::ObjectId, visible: bool) {
control_backend::get_control_backend().set_widget_visible(widget_id, visible);
}
#[cfg(not(alloc_frugal))]
pub fn is_widget_visible(widget_id: crate::core::ObjectId) -> bool {
control_backend::get_control_backend().is_widget_visible(widget_id)
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_value(widget_id: crate::core::ObjectId, value: f64) -> bool {
widget::capability::widget_access::write_number(widget_id, &["value"], value)
}
#[cfg(not(alloc_frugal))]
pub fn widget_value(widget_id: crate::core::ObjectId) -> Option<f64> {
widget::capability::widget_access::read_number(widget_id, &["value"])
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_range(widget_id: crate::core::ObjectId, min: f64, max: f64) -> bool {
let names: &[&str] = &["minimum", "min", "min_value"];
let max_names: &[&str] = &["maximum", "max", "max_value"];
widget::capability::widget_access::write_number(widget_id, names, min)
&& widget::capability::widget_access::write_number(widget_id, max_names, max)
}
#[cfg(not(alloc_frugal))]
pub fn widget_range(widget_id: crate::core::ObjectId) -> Option<(f64, f64)> {
let min = widget::capability::widget_access::read_number(
widget_id,
&["minimum", "min", "min_value"],
)?;
let max = widget::capability::widget_access::read_number(
widget_id,
&["maximum", "max", "max_value"],
)?;
Some((min, max))
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_selected_index(widget_id: crate::core::ObjectId, index: Option<usize>) -> bool {
let names: &[&str] = &["selected_index", "current_index", "current_row", "active_index"];
let value = match index {
Some(index) => crate::widget::capability::CapabilityValue::UInt(index as u64),
None => crate::widget::capability::CapabilityValue::Null,
};
widget::capability::widget_access::write_first(widget_id, names, &value)
}
#[cfg(not(alloc_frugal))]
pub fn widget_selected_index(widget_id: crate::core::ObjectId) -> Option<usize> {
widget::capability::widget_access::read_index(
widget_id,
&["selected_index", "current_index", "current_row", "active_index"],
)
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_checked(widget_id: crate::core::ObjectId, checked: bool) -> bool {
widget::capability::widget_access::write_first(
widget_id,
&["checked"],
&crate::widget::capability::CapabilityValue::Bool(checked),
)
}
#[cfg(not(alloc_frugal))]
pub fn is_widget_checked(widget_id: crate::core::ObjectId) -> Option<bool> {
widget::capability::widget_access::read_flag(widget_id, &["checked"])
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_step(widget_id: crate::core::ObjectId, step: f64) -> bool {
widget::capability::widget_access::write_number(widget_id, &["single_step", "step"], step)
}
#[cfg(not(alloc_frugal))]
pub fn widget_step(widget_id: crate::core::ObjectId) -> Option<f64> {
widget::capability::widget_access::read_number(widget_id, &["single_step", "step"])
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_indeterminate(widget_id: crate::core::ObjectId, indeterminate: bool) -> bool {
widget::capability::widget_access::write_first(
widget_id,
&["indeterminate"],
&crate::widget::capability::CapabilityValue::Bool(indeterminate),
)
}
#[cfg(not(alloc_frugal))]
pub fn is_widget_indeterminate(widget_id: crate::core::ObjectId) -> Option<bool> {
widget::capability::widget_access::read_flag(widget_id, &["indeterminate"])
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_read_only(widget_id: crate::core::ObjectId, read_only: bool) -> bool {
widget::capability::widget_access::write_first(
widget_id,
&["read_only"],
&crate::widget::capability::CapabilityValue::Bool(read_only),
)
}
#[cfg(not(alloc_frugal))]
pub fn is_widget_read_only(widget_id: crate::core::ObjectId) -> Option<bool> {
widget::capability::widget_access::read_flag(widget_id, &["read_only"])
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_max_length(widget_id: crate::core::ObjectId, max_length: u32) -> bool {
widget::capability::widget_access::write_first(
widget_id,
&["max_length"],
&crate::widget::capability::CapabilityValue::UInt(max_length as u64),
)
}
#[cfg(not(alloc_frugal))]
pub fn widget_max_length(widget_id: crate::core::ObjectId) -> Option<u32> {
widget::capability::widget_access::read_index(widget_id, &["max_length"])
.and_then(|v| u32::try_from(v).ok())
}
#[cfg(not(alloc_frugal))]
pub fn set_window_state(
widget_id: crate::core::ObjectId,
flag: platform::WindowStateFlag,
on: bool,
) -> bool {
platform::get_platform().set_window_state(widget_id, flag, on)
}
#[cfg(not(alloc_frugal))]
pub fn is_window_in_state(
widget_id: crate::core::ObjectId,
flag: platform::WindowStateFlag,
) -> Option<bool> {
platform::get_platform().is_window_in_state(widget_id, flag)
}
#[cfg(not(alloc_frugal))]
pub fn set_window_min_size(widget_id: crate::core::ObjectId, width: u32, height: u32) -> bool {
platform::get_platform().set_window_min_size(widget_id, width, height)
}
#[cfg(not(alloc_frugal))]
pub fn window_min_size(widget_id: crate::core::ObjectId) -> Option<(u32, u32)> {
platform::get_platform().window_min_size(widget_id)
}
#[cfg(not(alloc_frugal))]
pub fn set_window_icon(widget_id: crate::core::ObjectId, path: &str) -> bool {
platform::get_platform().set_window_icon(widget_id, path)
}
#[cfg(not(alloc_frugal))]
pub fn window_icon(widget_id: crate::core::ObjectId) -> Option<String> {
platform::get_platform().window_icon(widget_id)
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_selection(widget_id: crate::core::ObjectId, start: u32, end: u32) -> bool {
let names: &[&str] = &["selection"];
widget::capability::widget_access::write_first(
widget_id,
names,
&crate::widget::capability::CapabilityValue::String(format!("{start},{end}")),
)
}
#[cfg(not(alloc_frugal))]
pub fn widget_selection(widget_id: crate::core::ObjectId) -> Option<(u32, u32)> {
let raw = widget::capability::widget_access::read_text(widget_id, &["selection"])?;
let (start, end) = raw.split_once(',')?;
Some((start.trim().parse().ok()?, end.trim().parse().ok()?))
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_placeholder(widget_id: crate::core::ObjectId, text: &str) -> bool {
widget::capability::widget_access::write_first(
widget_id,
&["placeholder_text", "placeholder"],
&crate::widget::capability::CapabilityValue::String(text.to_string()),
)
}
#[cfg(not(alloc_frugal))]
pub fn widget_placeholder(widget_id: crate::core::ObjectId) -> Option<String> {
widget::capability::widget_access::read_text(widget_id, &["placeholder_text", "placeholder"])
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_echo_mode(widget_id: crate::core::ObjectId, mode: platform::EchoMode) -> bool {
let token = match mode {
platform::EchoMode::Normal => "normal",
platform::EchoMode::Password => "password",
platform::EchoMode::NoEcho => "no_echo",
};
widget::capability::widget_access::write_first(
widget_id,
&["echo_mode"],
&crate::widget::capability::CapabilityValue::String(token.to_string()),
)
}
#[cfg(not(alloc_frugal))]
pub fn widget_echo_mode(widget_id: crate::core::ObjectId) -> Option<platform::EchoMode> {
match widget::capability::widget_access::read_text(widget_id, &["echo_mode"])?.as_str() {
"normal" => Some(platform::EchoMode::Normal),
"password" => Some(platform::EchoMode::Password),
"no_echo" => Some(platform::EchoMode::NoEcho),
_ => None,
}
}
#[cfg(not(alloc_frugal))]
pub fn set_slider_orientation(
widget_id: crate::core::ObjectId,
orientation: crate::core::Orientation,
) -> bool {
widget::capability::widget_access::write_first(
widget_id,
&["orientation"],
&crate::widget::capability::CapabilityValue::String(
widget::capability::orientation_to_str(orientation).to_string(),
),
)
}
#[cfg(not(alloc_frugal))]
pub fn slider_orientation(widget_id: crate::core::ObjectId) -> Option<crate::core::Orientation> {
let token = widget::capability::widget_access::read_text(widget_id, &["orientation"])?;
widget::capability::expect_orientation(crate::widget::capability::CapabilityValue::String(
token,
))
.ok()
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_tristate(widget_id: crate::core::ObjectId, enabled: bool) -> bool {
widget::capability::widget_access::write_first(
widget_id,
&["tristate_enabled"],
&crate::widget::capability::CapabilityValue::Bool(enabled),
)
}
#[cfg(not(alloc_frugal))]
pub fn is_widget_tristate(widget_id: crate::core::ObjectId) -> Option<bool> {
widget::capability::widget_access::read_flag(widget_id, &["tristate_enabled"])
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_group(widget_id: crate::core::ObjectId, group: &str) -> bool {
let value = if group.is_empty() {
crate::widget::capability::CapabilityValue::Null
} else {
crate::widget::capability::CapabilityValue::String(group.to_string())
};
widget::capability::widget_access::write_first(widget_id, &["group_id", "group"], &value)
}
#[cfg(not(alloc_frugal))]
pub fn widget_group(widget_id: crate::core::ObjectId) -> Option<String> {
widget::capability::widget_access::read_text(widget_id, &["group_id", "group"])
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_scroll_position(widget_id: crate::core::ObjectId, x: i32, y: i32) -> bool {
let x_ok = widget::capability::widget_access::write_number(
widget_id,
&["scroll_position_x"],
x as f64,
);
let y_ok = widget::capability::widget_access::write_number(
widget_id,
&["scroll_position_y"],
y as f64,
);
x_ok && y_ok
}
#[cfg(not(alloc_frugal))]
pub fn widget_scroll_position(widget_id: crate::core::ObjectId) -> Option<(i32, i32)> {
let x = widget::capability::widget_access::read_number(widget_id, &["scroll_position_x"])?;
let y = widget::capability::widget_access::read_number(widget_id, &["scroll_position_y"])?;
Some((x as i32, y as i32))
}
#[cfg(not(alloc_frugal))]
pub fn combo_box_add_item(combo_box: crate::core::ObjectId, text: &str) -> bool {
control_backend::get_control_backend().combo_box_add_item(combo_box, text)
}
#[cfg(not(alloc_frugal))]
pub fn combo_box_clear_items(combo_box: crate::core::ObjectId) -> bool {
control_backend::get_control_backend().combo_box_clear_items(combo_box)
}
#[cfg(not(alloc_frugal))]
pub fn combo_box_set_current_index(combo_box: crate::core::ObjectId, index: usize) -> bool {
widget::capability::widget_access::write_first(
combo_box,
&["current_index"],
&crate::widget::capability::CapabilityValue::UInt(index as u64),
)
}
#[cfg(not(alloc_frugal))]
pub fn combo_box_current_index(combo_box: crate::core::ObjectId) -> Option<usize> {
widget::capability::widget_access::read_index(combo_box, &["current_index"])
}
#[cfg(not(alloc_frugal))]
pub fn combo_box_item_count(combo_box: crate::core::ObjectId) -> usize {
widget::capability::widget_access::read_index(combo_box, &["item_count"]).unwrap_or(0)
}
#[cfg(not(alloc_frugal))]
pub fn combo_box_item_text(combo_box: crate::core::ObjectId, index: usize) -> Option<String> {
control_backend::get_control_backend().combo_box_item_text(combo_box, index)
}
#[cfg(not(alloc_frugal))]
pub fn list_box_add_item(list_box: crate::core::ObjectId, text: &str) -> bool {
control_backend::get_control_backend().list_box_add_item(list_box, text)
}
#[cfg(not(alloc_frugal))]
pub fn list_box_remove_item(list_box: crate::core::ObjectId, index: usize) -> bool {
control_backend::get_control_backend().list_box_remove_item(list_box, index)
}
#[cfg(not(alloc_frugal))]
pub fn list_box_clear_items(list_box: crate::core::ObjectId) -> bool {
control_backend::get_control_backend().list_box_clear_items(list_box)
}
#[cfg(not(alloc_frugal))]
pub fn list_box_set_current_index(list_box: crate::core::ObjectId, index: usize) -> bool {
widget::capability::widget_access::write_first(
list_box,
&["current_row", "current_index"],
&crate::widget::capability::CapabilityValue::UInt(index as u64),
)
}
#[cfg(not(alloc_frugal))]
pub fn list_box_current_index(list_box: crate::core::ObjectId) -> Option<usize> {
widget::capability::widget_access::read_index(list_box, &["current_row", "current_index"])
}
#[cfg(not(alloc_frugal))]
pub fn list_box_item_count(list_box: crate::core::ObjectId) -> usize {
widget::capability::widget_access::read_index(list_box, &["item_count"]).unwrap_or(0)
}
#[cfg(not(alloc_frugal))]
pub fn list_box_item_text(list_box: crate::core::ObjectId, index: usize) -> Option<String> {
control_backend::get_control_backend().list_box_item_text(list_box, index)
}
#[cfg(not(alloc_frugal))]
pub fn poll_widget_triggered() -> Option<crate::core::ObjectId> {
control_backend::get_control_backend().poll_widget_triggered()
}
#[cfg(not(alloc_frugal))]
pub fn poll_widget_trigger_event() -> Option<WidgetTriggerEvent> {
control_backend::get_control_backend().poll_widget_trigger_event()
}
#[cfg(not(alloc_frugal))]
pub fn wait_for_host_events(timeout: std::time::Duration) -> bool {
let observed = platform::frame_wait::generation();
platform::frame_wait::wait_after(observed, timeout);
platform::frame_wait::generation() != observed
}
#[cfg(not(alloc_frugal))]
pub fn drain_widget_triggers_for(widget_id: crate::core::ObjectId) -> usize {
let mut dispatched = 0usize;
while let Some(event) =
control_backend::get_control_backend().pop_widget_trigger_event_for(widget_id)
{
#[cfg(full_widgets)]
{
app::dispatch_trigger(event.widget_id, event.kind);
}
#[cfg(not(full_widgets))]
{
let _ = (event.widget_id, event.kind);
}
dispatched += 1;
}
dispatched
}
pub fn drain_triggers() -> usize {
#[cfg(alloc_frugal)]
{
0
}
#[cfg(not(alloc_frugal))]
{
#[cfg(full_widgets)]
let mut dispatched = 0usize;
#[cfg(not(full_widgets))]
let dispatched = 0usize;
while let Some(event) = poll_widget_trigger_event() {
#[cfg(full_widgets)]
{
app::dispatch_trigger(event.widget_id, event.kind);
dispatched += 1;
}
#[cfg(not(full_widgets))]
{
log::debug!(
"drain_triggers: consumed a {:?} trigger for widget {} in a build with no \
widget router (profile has no device class); nothing was dispatched",
event.kind,
event.widget_id
);
let _ = (event.widget_id, event.kind);
}
}
dispatched
}
}
#[cfg(not(alloc_frugal))]
pub fn inject_widget_trigger_event(
widget_id: crate::core::ObjectId,
kind: WidgetTriggerKind,
) -> bool {
control_backend::get_control_backend().inject_widget_trigger_event(widget_id, kind)
}
#[cfg(not(alloc_frugal))]
pub fn queue_resize_trigger(window_id: crate::core::ObjectId, width: u32, height: u32) -> bool {
control_backend::get_control_backend().queue_resize_trigger(window_id, width, height)
}
#[cfg(alloc_frugal)]
pub fn queue_resize_trigger(window_id: crate::core::ObjectId, width: u32, height: u32) -> bool {
let _ = (window_id, width, height);
false
}
#[cfg(not(alloc_frugal))]
pub fn window_client_size(window_id: crate::core::ObjectId) -> Option<(u32, u32)> {
control_backend::get_control_backend().window_client_size(window_id)
}
#[cfg(alloc_frugal)]
pub fn window_client_size(window_id: crate::core::ObjectId) -> Option<(u32, u32)> {
let _ = window_id;
None
}
#[cfg(not(alloc_frugal))]
pub fn set_clipboard_text(text: &str) -> bool {
platform::get_platform().set_clipboard_text(text)
}
#[cfg(not(alloc_frugal))]
pub fn get_clipboard_text() -> String {
platform::get_platform().get_clipboard_text()
}
#[cfg(not(alloc_frugal))]
pub fn clipboard_text() -> Option<String> {
platform::get_platform().clipboard_text()
}
#[cfg(not(alloc_frugal))]
pub fn platform_clipboard() -> Option<&'static dyn crate::platform::clipboard::RichClipboardBackend>
{
platform::get_platform().clipboard_backend()
}
#[cfg(not(alloc_frugal))]
pub fn choose_path(
purpose: crate::platform::PathPurpose,
title: &str,
) -> Result<Option<std::path::PathBuf>, crate::platform::PathPickerError> {
platform::get_platform().choose_path(purpose, title)
}
#[cfg(not(alloc_frugal))]
pub fn schedule_on_main(after: std::time::Duration, work: impl FnOnce() + Send + 'static) -> bool {
platform::main_thread::schedule_in(after, work)
}
#[cfg(not(alloc_frugal))]
pub fn open_path(
title: &str,
) -> Result<Option<std::path::PathBuf>, crate::platform::PathPickerError> {
choose_path(crate::platform::PathPurpose::OpenFile, title)
}
#[cfg(not(alloc_frugal))]
pub fn save_path(
title: &str,
) -> Result<Option<std::path::PathBuf>, crate::platform::PathPickerError> {
choose_path(crate::platform::PathPurpose::SaveFile, title)
}
#[cfg(not(alloc_frugal))]
pub fn select_directory(
title: &str,
) -> Result<Option<std::path::PathBuf>, crate::platform::PathPickerError> {
choose_path(crate::platform::PathPurpose::SelectDirectory, title)
}
#[cfg(not(alloc_frugal))]
pub fn create_menu_bar(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
#[cfg(widgets_unstripped)]
{
backend_for_kind(widget::WidgetKind::MenuBar).create_menu_bar(parent, x, y, width, height)
}
#[cfg(not(widgets_unstripped))]
{
let _ = (parent, x, y, width, height);
NO_SUCH_CONTROL
}
}
#[cfg(not(alloc_frugal))]
pub fn create_menu(
parent: crate::core::ObjectId,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
#[cfg(widgets_unstripped)]
{
backend_for_kind(widget::WidgetKind::Menu).create_menu(parent, text, x, y, width, height)
}
#[cfg(not(widgets_unstripped))]
{
let _ = (parent, text, x, y, width, height);
NO_SUCH_CONTROL
}
}
#[cfg(not(alloc_frugal))]
pub fn attach_menu_bar_to_window(
window: crate::core::ObjectId,
menu_bar: crate::core::ObjectId,
) -> bool {
control_backend::get_control_backend().attach_menu_bar_to_window(window, menu_bar)
}
#[cfg(not(alloc_frugal))]
pub fn menu_add_item(
parent_menu: crate::core::ObjectId,
text: &str,
shortcut: Option<&str>,
) -> crate::core::ObjectId {
control_backend::get_control_backend().menu_add_item(parent_menu, text, shortcut)
}
#[cfg(not(alloc_frugal))]
pub fn native_menu_item_icons_supported() -> bool {
control_backend::get_control_backend().supports_menu_item_icons()
}
#[cfg(not(alloc_frugal))]
pub fn format_shortcut(shortcut: &crate::shortcut::Shortcut) -> String {
platform::get_platform().format_shortcut(shortcut)
}
#[cfg(not(alloc_frugal))]
pub fn poll_menu_triggered() -> Option<crate::core::ObjectId> {
control_backend::get_control_backend().poll_menu_triggered()
}
#[cfg(not(alloc_frugal))]
pub fn menu_item_shortcut(menu_item: crate::core::ObjectId) -> Option<String> {
control_backend::get_control_backend().menu_item_shortcut(menu_item)
}
#[cfg(full_widgets)]
pub fn menu_open_at(
menu: crate::core::ObjectId,
x: i32,
y: i32,
viewport: crate::core::Rect,
) -> bool {
if viewport.width == 0 || viewport.height == 0 {
return false;
}
crate::widget::runtime::open_context_menu(menu, crate::core::Point::new(x, y), viewport)
}
#[cfg(full_widgets)]
pub fn menu_close(menu: crate::core::ObjectId) -> bool {
let hidden = crate::widget::runtime::with_widget_mut(menu, |widget| {
let Some(menu) = (widget as &mut dyn std::any::Any).downcast_mut::<crate::Menu>() else {
return false;
};
menu.hide();
true
})
.unwrap_or(false);
if hidden {
crate::widget::runtime::request_repaint_subtree(menu);
crate::widget::runtime::clear_popup_grab();
}
hidden
}
#[cfg(not(alloc_frugal))]
pub fn backend_handle(widget: crate::core::ObjectId) -> Option<usize> {
platform::get_platform().get_native_handle(widget)
}
#[cfg(not(alloc_frugal))]
pub fn inject_menu_trigger(menu_item_id: crate::core::ObjectId) -> bool {
control_backend::get_control_backend().inject_menu_trigger(menu_item_id)
}
#[cfg(not(alloc_frugal))]
pub fn create_tool_bar(
parent: crate::core::ObjectId,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
#[cfg(widgets_unstripped)]
{
backend_for_kind(widget::WidgetKind::ToolBar).create_tool_bar(parent, x, y, width, height)
}
#[cfg(not(widgets_unstripped))]
{
let _ = (parent, x, y, width, height);
NO_SUCH_CONTROL
}
}
#[cfg(not(alloc_frugal))]
pub fn create_status_bar(
parent: crate::core::ObjectId,
text: &str,
x: i32,
y: i32,
width: u32,
height: u32,
) -> crate::core::ObjectId {
#[cfg(widgets_unstripped)]
{
backend_for_kind(widget::WidgetKind::StatusBar)
.create_status_bar(parent, text, x, y, width, height)
}
#[cfg(not(widgets_unstripped))]
{
let _ = (parent, text, x, y, width, height);
NO_SUCH_CONTROL
}
}
#[cfg(not(alloc_frugal))]
pub fn begin_drag(source_widget_id: crate::core::ObjectId, mime: &str, payload: &[u8]) -> bool {
platform::get_platform().begin_drag(source_widget_id, mime, payload)
}
#[cfg(not(alloc_frugal))]
pub fn poll_drop_event() -> Option<DropEvent> {
platform::get_platform().poll_drop_event()
}
#[cfg(not(alloc_frugal))]
pub fn inject_drop_event(event: DropEvent) -> bool {
platform::get_platform().inject_drop_event(event)
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_ime_enabled(widget_id: crate::core::ObjectId, enabled: bool) -> bool {
control_backend::get_control_backend().set_widget_ime_enabled(widget_id, enabled)
}
#[cfg(not(alloc_frugal))]
pub fn is_widget_ime_enabled(widget_id: crate::core::ObjectId) -> bool {
control_backend::get_control_backend().is_widget_ime_enabled(widget_id)
}
#[cfg(not(alloc_frugal))]
pub fn platform_ime_bridge() -> Option<&'static dyn crate::platform::ime::ImeBridge> {
platform::get_platform().ime_bridge()
}
#[cfg(not(alloc_frugal))]
pub fn set_widget_accessibility_name(widget_id: crate::core::ObjectId, name: &str) -> bool {
control_backend::get_control_backend().set_widget_accessibility_name(widget_id, name)
}
#[cfg(not(alloc_frugal))]
pub fn get_widget_accessibility_name(widget_id: crate::core::ObjectId) -> String {
control_backend::get_control_backend().get_widget_accessibility_name(widget_id)
}
#[cfg(not(alloc_frugal))]
pub use platform::{
backend_name, capabilities, dpi_scale_factor, get_platform, init as platform_init,
quit as platform_quit, run as platform_run, runtime_gui_mode, runtime_gui_mode_for,
};
pub use platform::{
CapabilityContract, DropEvent, EmbeddedCapabilityContract, MobileBackend,
NativeCapabilityContract, OpenError, PlatformCapabilities, RuntimeGuiMode, WidgetTriggerEvent,
WidgetTriggerKind, WindowStateFlag,
};
#[allow(deprecated)]
pub mod deprecated {
#[deprecated(
note = "renamed to `mount_surface`; 'custom' named a mechanism that no longer exists"
)]
pub fn mount_custom_widget(
parent: crate::core::ObjectId,
id: crate::core::ObjectId,
rect: crate::core::Rect,
) -> bool {
crate::mount_surface(parent, id, rect)
}
#[deprecated(
note = "renamed to `resize_surface`; 'custom' named a mechanism that no longer exists"
)]
pub fn resize_custom_widget(id: crate::core::ObjectId, rect: crate::core::Rect) -> bool {
crate::resize_surface(id, rect)
}
#[deprecated(
note = "renamed to `unmount_surface`; 'custom' named a mechanism that no longer exists"
)]
pub fn unmount_custom_widget(id: crate::core::ObjectId) -> bool {
crate::unmount_surface(id)
}
#[deprecated(
note = "renamed to `invalidate_surface`; 'custom' named a mechanism that no longer exists"
)]
pub fn request_custom_repaint(id: crate::core::ObjectId) -> bool {
crate::invalidate_surface(id)
}
#[deprecated(
note = "renamed to `supports_surfaces`; 'custom' named a mechanism that no longer exists"
)]
pub fn supports_custom_widgets() -> bool {
crate::supports_surfaces()
}
#[cfg(not(alloc_frugal))]
#[deprecated(
note = "renamed to `backend_handle`; 'native' named a mechanism, and which object a \
backend holds is its own business (principle #52)"
)]
pub fn native_handle(widget: crate::core::ObjectId) -> Option<usize> {
crate::backend_handle(widget)
}
}
#[allow(deprecated)]
pub use deprecated::{
mount_custom_widget, request_custom_repaint, resize_custom_widget, supports_custom_widgets,
unmount_custom_widget,
};
#[cfg(not(alloc_frugal))]
#[allow(deprecated)]
pub use deprecated::native_handle;
#[cfg(test)]
mod docs_paths_tests;
#[cfg(test)]
mod compat_path_tests {
#[test]
#[allow(deprecated)]
fn old_surface_names_still_resolve_at_the_crate_root() {
let _: fn(crate::core::ObjectId, crate::core::ObjectId, crate::core::Rect) -> bool =
crate::mount_custom_widget;
let _: fn(crate::core::ObjectId, crate::core::Rect) -> bool = crate::resize_custom_widget;
let _: fn(crate::core::ObjectId) -> bool = crate::unmount_custom_widget;
let _: fn(crate::core::ObjectId) -> bool = crate::request_custom_repaint;
let _: fn() -> bool = crate::supports_custom_widgets;
}
#[test]
#[allow(deprecated)]
fn deprecated_aliases_delegate_to_the_surface_api() {
assert_eq!(crate::supports_custom_widgets(), crate::supports_surfaces());
}
}