zng/
lib.rs

1#![expect(clippy::needless_doctest_main)]
2#![doc(html_favicon_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo-icon.png")]
3#![doc(html_logo_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo.png")]
4
5//! Zng is a cross-platform GUI framework, it provides ready made highly customizable widgets, responsive layout,
6//! live data binding, easy localization, automatic focus navigation and accessibility, async and multi-threaded tasks, robust
7//! multi-process architecture and more.
8//!
9//! Zng is pronounced "zing", or as an initialism: ZNG (Z Nesting Graphics).
10//!
11//! Every component of the framework can be extended, you can create new widgets or add properties to existing ones,
12//! at a lower level you can introduce new events and services, seamless integrating custom hardware.
13//!
14//! # Usage
15//!
16//! First add this to your `Cargo.toml`:
17//!
18//! ```toml
19//! [dependencies]
20//! zng = { version = "0.14.2", features = ["view_prebuilt"] }
21//! ```
22//!
23//! Then create your first app:
24//!
25//! ```no_run
26//! use zng::prelude::*;
27//!
28//! fn main() {
29//!     zng::env::init!();
30//!     app();
31//! }
32//!
33//! fn app() {
34//!     APP.defaults().run_window(async {
35//!         Window! {
36//!             child_align = Align::CENTER;
37//!             child = {
38//!                 let size = var(28i32);
39//!                 Button! {
40//!                     child = Text! {
41//!                         txt = "Hello World!";
42//!
43//!                         #[easing(200.ms())]
44//!                         font_size = size.map_into();
45//!                     };
46//!                     on_click = hn!(|_| {
47//!                         let next = size.get() + 10;
48//!                         size.set(if next > 80 { 28 } else { next });
49//!                     });
50//!                 }
51//!             };
52//!         }
53//!     })
54//! }
55//! ```
56//!
57//! You can also use a [prebuild view](app#prebuild) and run in the [same process](app#same-process), see [`app`] for more details.
58//!
59//! # Widgets & Properties
60//!
61//! The high-level building blocks of UI.
62//!
63//! ```
64//! use zng::prelude::*;
65//!
66//! # let _scope = APP.defaults();
67//! # let _ =
68//! Button! {
69//!     child = Text!("Green?");
70//!     widget::background_color = colors::GREEN;
71//!     on_click = hn!(|_| println!("SUPER GREEN!"));
72//! }
73//! # ;
74//! ```
75//!
76//! In the example above [`Button!`] and [`Text!`] are widgets and `child`, [`background_color`] and [`on_click`] are properties.
77//! Widgets are mostly an aggregation of properties that define an specific function and presentation, most properties are standalone
78//! implementations of an specific behavior or appearance, in the example only `child` is implemented by the button widget, the
79//! other two properties can be set in any widget.
80//!
81//! Each widget is a dual macro and `struct` of the same name, in the documentation only the `struct` is visible, when
82//! an struct represents a widget it is tagged with <strong><code>W</code></strong>. Each properties is declared as a function,
83//! in the documentation property functions are tagged with <strong><code>P</code></strong>.
84//!
85//! Widget instances can be of any type, usually they are an opaque [`impl UiNode`], some special widgets have an instance type,
86//! the [`Window!`] widget for example has the instance type [`WindowRoot`]. Property instances are always of type `impl UiNode`,
87//! each property function takes an `impl UiNode` input plus one or more value inputs and returns an `impl UiNode` output that
88//! wraps the input node adding the property behavior, the widgets take care of this node chaining nesting each property
89//! instance in the proper order, internally every widget instance is a tree of nested node instances.
90//!
91//! Widgets and properties are very versatile, each widget documentation page will promote the properties that the widget implementer
92//! explicitly associated with the widget, but that is only a starting point.
93//!
94//! ```
95//! use zng::prelude::*;
96//!
97//! # let _app = APP.minimal();
98//! # let _ =
99//! Wgt! {
100//!     layout::align = layout::Align::CENTER;
101//!     layout::size = 50;
102//!     
103//!     #[easing(200.ms())]
104//!     widget::background_color = colors::RED;
105//!     
106//!     when *#gesture::is_hovered {
107//!         widget::background_color = colors::GREEN;
108//!     }
109//! }
110//! # ;
111//! ```
112//!
113//! In the example above an [`Wgt!`] is completely defined by stand-alone properties, [`align`] and [`size`] define
114//! the bounds of the widget, [`background_color`] fills the bounds with color and [`is_hovered`] reacts to pointer interaction.
115//!
116//! The example also introduces [`when`] blocks, [state properties] and the [`easing`] property attribute. State properties
117//! compute an state from the widget, this state can be used to change the value of other properties. When blocks are a powerful
118//! feature of widgets, they declare conditional property values. The easing attribute can be set in any property with transitionable
119//! values to smoothly animate between changes.
120//!
121//! The [`widget`](mod@widget) module documentation provides an in-depth explanation of how widgets and properties work.
122//!
123//! [`Button!`]: struct@button::Button
124//! [`Window!`]: struct@window::Window
125//! [`Text!`]: struct@text::Text
126//! [`Wgt!`]: struct@widget::Wgt
127//! [`background_color`]: fn@widget::background_color
128//! [`on_click`]: fn@gesture::on_click
129//! [`is_hovered`]: fn@gesture::is_hovered
130//! [`align`]: fn@layout::align
131//! [`size`]: fn@layout::size
132//! [`when`]: widget#when
133//! [state properties]: widget#state-properties
134//! [`easing`]: widget::easing
135//! [`impl UiNode`]: widget::node::UiNode
136//! [`WindowRoot`]: window::WindowRoot
137//!
138//! # Variables
139//!
140//! Observable values that glue most of the UI together.
141//!
142//! ```
143//! use zng::prelude::*;
144//!
145//! # let _app = APP.minimal();
146//! let btn_pressed = var(false);
147//!
148//! # let _ =
149//! Stack! {
150//!     direction = StackDirection::top_to_bottom();
151//!     spacing = 10;
152//!     children = ui_vec![
153//!         Button! {
154//!             child = Text! { txt = "Press Me!"; };
155//!             gesture::is_pressed = btn_pressed.clone();   
156//!         },
157//!         Text! {
158//!             txt = btn_pressed.map(|&b| {
159//!                 if b {
160//!                     "Button is pressed!"
161//!                 } else {
162//!                     "Button is not pressed."
163//!                 }.into()
164//!             });
165//!         }
166//!     ]
167//! }
168//! # ;
169//! ```
170//!
171//! The example above binds the pressed state of a widget with the text content of another using a [`var`]. Variables
172//! are the most common property input kind, in the example `direction`, `spacing`, `is_pressed` and `txt` all accept
173//! an [`IntoVar<T>`] input that gets converted into a [`Var<T>`] when the property is instantiated.
174//!
175//! There are multiple variable types, they can be a simple static value, a shared observable and modifiable value or a
176//! contextual value. Variables can also depend on other variables automatically updating when input variables update.
177//!
178//! ```
179//! use zng::prelude::*;
180//!
181//! # let _app = APP.minimal();
182//! fn ui(txt: impl IntoVar<Txt>) -> impl UiNode {
183//!     Text!(txt)
184//! }
185//!
186//! ui("static value");
187//!
188//! let txt = var(Txt::from("dynamic value"));
189//! ui(txt.clone());
190//! txt.set("change applied next update");
191//!
192//! let show_txt = var(true);
193//! ui(expr_var!(if *#{show_txt} { #{txt}.clone() } else { Txt::from("") }));
194//!
195//! ui(text::FONT_COLOR_VAR.map(|s| formatx!("font color is {s}")));
196//! ```
197//!
198//! In the example a [`var`] clone is shared with the UI and a new value is scheduled for the next app update. Variable
199//! updates are batched, during each app update pass every property can observe the current value and schedule modifications to
200//! the value, the modifications are only applied after, potentially causing a new update pass if any value actually changed, see
201//! [var updates] in the [var module] documentation for more details.
202//!
203//! The example also demonstrates the [`expr_var!`], a read-only observable variable that interpolates other variables, the
204//! value of this variable automatically update when any of the interpolated variables update.
205//!
206//! And finally the example demonstrates a context var, `FONT_COLOR_VAR`. Context variables get their value from the
207//! *environment* where they are used, the UI in the example can show different a different text depending on where it is placed.
208//! Context variables are usually encapsulated by properties strongly associated with a widget, most of [`Text!`] properties just
209//! set a context var that affects all text instances in the widget they are placed and descendant widgets.
210//!
211//! There are other useful variable types, see the [var module] module documentation for more details.
212//!
213//! [`var`]: var::var
214//! [`expr_var!`]: var::expr_var
215//! [var module]: crate::var
216//! [`IntoVar<T>`]: var::IntoVar
217//! [`Var<T>`]: var::Var
218//!
219//! # Context
220//!
221//! Context or *ambient* values set on parent widgets affecting descendant widgets.
222//!
223//! ```
224//! use zng::prelude::*;
225//!
226//! # let _app = APP.minimal();
227//! # let _ =
228//! Stack! {
229//!     direction = StackDirection::top_to_bottom();
230//!     spacing = 10;
231//!     
232//!     text::font_color = colors::RED;
233//!
234//!     children = ui_vec![
235//!         Button! { child = Text!("Text 1"); },
236//!         Button! { child = Text!("Text 2"); },
237//!         Button! {
238//!             child = Text!("Text 3");
239//!             text::font_color = colors::GREEN;
240//!         },
241//!     ];
242//! }
243//! # ;
244//! ```
245//!
246//! In the example above "Text 1" and "Text 2" are rendered in red and "Text 3" is rendered in green. The context
247//! of a widget is important, `text::font_color` sets text color in the `Stack!` widget and all descendant widgets,
248//! the color is overridden in the third `Button!` for the context of that button and descendants, the `Text!`
249//! widget has a different appearance just by being in a different context.
250//!
251//! Note that the text widget can also set the color directly, in the following example the "Text 4" is blue, this
252//! value is still contextual, but texts are usually leaf widgets so only the text is affected.
253//!
254//! ```
255//! # use zng::prelude::*;
256//! # let _app = APP.minimal();
257//! # let _ =
258//! Text! {
259//!     txt = "Text 4";
260//!     font_color = colors::BLUE;
261//! }
262//! # ;
263//! ```
264//!
265//! In the example above a context variable defines the text color, but not just variables are contextual, layout
266//! units and widget services are also contextual, widget implementers may declare custom contextual values too,
267//! see [context local] in the app module documentation for more details.
268//!
269//! [context local]: app#context-local
270//!  
271//! # Services
272//!
273//! App or contextual value and function providers.
274//!
275//! ```
276//! use zng::prelude::*;
277//! use zng::clipboard::CLIPBOARD;
278//!
279//! # let _app = APP.minimal();
280//! # let _ =
281//! Stack! {
282//!     direction = StackDirection::top_to_bottom();
283//!     spacing = 10;
284//!
285//!     children = {
286//!         let txt = var(Txt::from(""));
287//!         let txt_is_err = var(false);
288//!         ui_vec![
289//!             Button! {
290//!                 child = Text!("Paste");
291//!                 on_click = hn!(txt, txt_is_err, |_| {
292//!                     match CLIPBOARD.text() {
293//!                         Ok(p) => if let Some(t) = p {
294//!                             txt.set(t);
295//!                             txt_is_err.set(false);
296//!                         },
297//!                         Err(e) => {
298//!                             let t = WIDGET.trace_path();
299//!                             txt.set(formatx!("error in {t}: {e}"));
300//!                             txt_is_err.set(true);
301//!                         }
302//!                     }
303//!                 });
304//!             },
305//!             Text! {
306//!                 txt;
307//!                 when *#{txt_is_err} {
308//!                     font_color = colors::RED;
309//!                 }
310//!             }
311//!         ]
312//!     };
313//! }
314//! # ;
315//! ```
316//!
317//! The example above uses two services, `CLIPBOARD` and `WIDGET`. Services are represented
318//! by an unit struct named like a static item, service functionality is available as methods on
319//! this unit struct. Services are contextual, `CLIPBOARD` exists on the app context, it can only operate
320//! in app threads, `WIDGET` represents the current widget and can only be used inside a widget.
321//!
322//! The default app provides multiple services, some common ones are [`APP`], [`WINDOWS`], [`WINDOW`], [`WIDGET`],
323//! [`FOCUS`], [`POPUP`], [`DATA`] and more. Services all follow the same pattern, they are a unit struct named like a static
324//! item, if you see such a type it is a service.
325//!
326//! Most services are synchronized with the update cycle. If the service provides a value that value does not change mid-update, all
327//! widgets read the same value in the same update. If the service run some operation it takes requests to run the operation, the
328//! requests are only applied after the current UI update. This is even true for the [`INSTANT`] service that provides the current
329//! time.
330//!
331//! [`WINDOWS`]: window::WINDOWS
332//! [`WINDOW`]: window::WINDOW
333//! [`WIDGET`]: widget::WIDGET
334//! [`FOCUS`]: focus::FOCUS
335//! [`POPUP`]: popup::POPUP
336//! [`DATA`]: data_context::DATA
337//! [`INSTANT`]: app::INSTANT
338//!
339//! # Events & Commands
340//!
341//! Targeted messages send from the system to widgets or from one widget to another.
342//!
343//! ```no_run
344//! use zng::{prelude::*, clipboard::{on_paste, CLIPBOARD, PASTE_CMD}};
345//!
346//! APP.defaults().run_window(async {
347//!     let cmd = PASTE_CMD.scoped(WINDOW.id());
348//!     let paste_btn = Button! {
349//!         child = Text!(cmd.name());
350//!         widget::enabled = cmd.is_enabled();
351//!         widget::visibility = cmd.has_handlers().map_into();
352//!         tooltip = Tip!(Text!(cmd.name_with_shortcut()));
353//!         on_click = hn!(|args: &gesture::ClickArgs| {
354//!             args.propagation().stop();
355//!             cmd.notify();
356//!         });
357//!     };
358//!
359//!     let pasted_txt = var(Txt::from(""));
360//!
361//!     Window! {
362//!         on_paste = hn!(pasted_txt, |_| {
363//!             if let Some(t) = CLIPBOARD.text().ok().flatten() {
364//!                 pasted_txt.set(t);
365//!             }
366//!         });
367//!         
368//!         child = Stack! {
369//!             children_align = Align::CENTER;
370//!             direction = StackDirection::top_to_bottom();
371//!             spacing = 20;             
372//!             children = ui_vec![paste_btn, Text!(pasted_txt)];
373//!         };
374//!     }
375//! });
376//! ```
377//!
378//! The example above uses events and command events. Events are represented by a static instance
379//! of [`Event<A>`] with name suffix `_EVENT`. Events are usually abstracted by
380//! one or more event property, event properties are named with prefix `on_` and accept one input of
381//! [`impl WidgetHandler<A>`]. Commands are specialized events represented by a static instance of [`Command`]
382//! with name suffix `_CMD`. Every command is also an `Event<CommandArgs>`, unlike other events it is common
383//! for the command instance to be used directly.
384//!
385//! The `on_click` property handles the `CLICK_EVENT` when the click was done with the primary button and targets
386//! the widget or a descendant of the widget. The [`hn!`] is a widget handler that synchronously handles the event.
387//! See the [`event`] module documentation for details about event propagation, targeting and route. And see
388//! [`handler`] module for other handler types, including [`async_hn!`] that enables async `.await` in any event property.
389//!
390//! The example above defines a button for the `PASTE_CMD` command scoped on the window. Scoped commands are different
391//! instances of [`Command`], the command scope can be a window or widget ID, the scope is the target of the command and
392//! the context of the command metadata. In the example the button is only visible if the command scope (window) has
393//! a paste handler, the button is only enabled it at least one paste handler on the scope is enabled, the button also
394//! displays the command name and shortcut metadata, and finally on click the button notifies a command event that is
395//! received in `on_click`.
396//!
397//! Commands enable separation of concerns, the button in the example does not need to know what the window will do on paste,
398//! in fact the button does not even need to know what command it is requesting. Widgets can also be controlled using commands,
399//! the `Scroll!` widget for example can be controlled from anywhere else in the app using the [`scroll::cmd`] commands. See
400//! the [commands](event#commands) section in the event module documentation for more details.
401//!
402//! [`Event<A>`]: event::Event
403//! [`Command`]: event::Command
404//! [`impl WidgetHandler<A>`]: handler::WidgetHandler
405//! [`hn!`]: handler::hn!
406//! [`async_hn!`]: handler::async_hn!
407//!
408//! # Layout
409//!
410//! Contextual properties and constraints that affect how a widget is sized and placed on the screen.
411//!
412//! ```
413//! use zng::prelude::*;
414//! # let _app = APP.minimal();
415//!
416//! # let _ =
417//! Container! {
418//!     layout::size = (400, 350);
419//!     widget::background_color = colors::BLUE.darken(70.pct());    
420//!
421//!     child = Button! {
422//!         child = Text!("Text");
423//!     
424//!         layout::align = layout::Align::CENTER;
425//!         layout::size = (60.pct(), 70.pct());
426//!     };
427//! }
428//! # ;
429//! ```
430//!
431//! In the example above the container widget sets an exact size using `layout::size` with exact units, the
432//! button widget sets a relative size using percentage units and positions itself in the container using `layout::align`.
433//! All the layout properties are stand-alone, in the example only the text widget implements layout directly. Layout
434//! properties modify the layout context by setting constraints and defining units, this context is available for all
435//! properties that need it during layout, see the [`layout`] module documentation for more details.
436//!
437//! # Error Handling
438//!
439//! Recoverable errors handled internally are logged using [`tracing`], in debug builds tracing events (info, warn and error)
440//! are printed using [`app::print_tracing`] by default if no tracing subscriber is set before the app starts building.
441//!
442//! Components always attempt to recover from errors when possible, or at least attempt to contain errors and turn then into
443//! a displayable message. The general idea is to at least give the end user a chance to workaround the issue.
444//!
445//! Components do not generally attempt to recover from panics, with some notable exceptions. The view-process will attempt to respawn
446//! if it crashes, because all state is safe in the app-process all windows and frames can be recreated, this lets the app survive
447//! some catastrophic video driver errors, like a forced disconnect caused by a driver update. The [`task::spawn`] and related
448//! fire-and-forget task runners will also just log the panic as an error.
449//!
450//! The [`zng::app::crash_handler`] is enabled by default, it collect panic backtraces, crash minidumps, show a crash dialog to the user
451//! and restart the app. During development a debug crash dialog is provided, it shows the stdout/stderr, panics stacktrace and
452//! minidumps collected if any non-panic fatal error happens. Note that the crash handler **stops debuggers from working**, see the
453//! [Debugger section] of the crash-handler docs on how to automatically disable the crash handler for debugger runs.
454//!
455//! [`tracing`]: https://docs.rs/tracing
456//! [Debugger section]: zng::app::crash_handler#debugger
457//!
458//! # In-Depth Documentation
459//!
460//! This crate level documentation only gives an overview required to start making apps using existing widgets and properties.
461//! All top-level modules in this crate contains in-depth documentation about their subject, of particular importance the
462//! [`app`], [`widget`](mod@widget), [`layout`] and [`render`] modules should give you a solid understanding of how everything works.
463//!
464//! ## Cargo Features
465//!
466//! See the [Cargo Features] section in the crate README for Cargo features documentation.
467//!
468//! [Cargo Features]: https://github.com/zng-ui/zng/tree/main/crates/zng#cargo-features
469
470#![warn(unused_extern_crates)]
471#![warn(missing_docs)]
472
473// manually expanded enable_widget_macros to avoid error running doc tests:
474// macro-expanded `extern crate` items cannot shadow names passed with `--extern`
475#[doc(hidden)]
476#[allow(unused_extern_crates)]
477extern crate self as zng;
478#[doc(hidden)]
479pub use zng_app::__proc_macro_util;
480
481pub use zng_clone_move::{async_clmv, async_clmv_fn, async_clmv_fn_once, clmv};
482
483pub mod access;
484pub mod ansi_text;
485pub mod app;
486pub mod button;
487pub mod checkerboard;
488pub mod clipboard;
489pub mod color;
490pub mod config;
491pub mod container;
492pub mod data_context;
493pub mod data_view;
494pub mod dialog;
495pub mod drag_drop;
496pub mod env;
497pub mod event;
498pub mod focus;
499pub mod font;
500pub mod fs_watcher;
501pub mod gesture;
502pub mod grid;
503pub mod handler;
504pub mod hot_reload;
505pub mod icon;
506pub mod image;
507pub mod keyboard;
508pub mod l10n;
509pub mod label;
510pub mod layer;
511pub mod layout;
512pub mod markdown;
513pub mod menu;
514pub mod mouse;
515pub mod panel;
516pub mod pointer_capture;
517pub mod popup;
518pub mod progress;
519pub mod render;
520pub mod rule_line;
521pub mod scroll;
522pub mod selectable;
523pub mod slider;
524pub mod stack;
525pub mod state_map;
526pub mod style;
527pub mod task;
528pub mod text;
529pub mod text_input;
530pub mod third_party;
531pub mod timer;
532pub mod tip;
533pub mod toggle;
534pub mod touch;
535pub mod undo;
536pub mod update;
537pub mod var;
538pub mod view_process;
539pub mod widget;
540pub mod window;
541pub mod wrap;
542
543/// Start and manage an app process.
544pub struct APP;
545impl std::ops::Deref for APP {
546    type Target = zng_app::APP;
547
548    fn deref(&self) -> &Self::Target {
549        &zng_app::APP
550    }
551}
552
553/// Types for general app development.
554///
555/// See also [`prelude_wgt`] for declaring new widgets and properties.
556pub mod prelude {
557    #[doc(no_inline)]
558    pub use crate::__prelude::*;
559}
560mod __prelude {
561    pub use crate::APP;
562    pub use crate::{color, gesture, keyboard, layout, mouse, task, timer, touch, widget};
563
564    pub use zng_task::rayon::prelude::{
565        FromParallelIterator as _, IndexedParallelIterator as _, IntoParallelIterator as _, IntoParallelRefIterator as _,
566        IntoParallelRefMutIterator as _, ParallelBridge as _, ParallelDrainFull as _, ParallelDrainRange as _, ParallelExtend as _,
567        ParallelIterator as _, ParallelSlice as _, ParallelSliceMut as _, ParallelString as _,
568    };
569
570    pub use zng_task::io::{
571        AsyncBufRead as _, AsyncRead as _, AsyncReadExt as _, AsyncSeek as _, AsyncSeekExt as _, AsyncWrite as _, AsyncWriteExt as _,
572    };
573
574    pub use zng_app::{
575        INSTANT,
576        event::{AnyEventArgs as _, CommandInfoExt as _, CommandNameExt as _, CommandParam, EventArgs as _},
577        handler::{app_hn, app_hn_once, async_app_hn, async_app_hn_once, async_hn, async_hn_once, hn, hn_once},
578        shortcut::{CommandShortcutExt as _, shortcut},
579        widget::{
580            AnyVarSubscribe as _, VarLayout as _, VarSubscribe as _, WIDGET, WidgetId, easing,
581            node::{UiNode, UiNodeList, UiNodeListChain as _, UiVec, ui_vec},
582        },
583        window::{WINDOW, WindowId},
584    };
585
586    pub use zng_app::widget::inspector::WidgetInfoInspectorExt as _;
587
588    pub use zng_var::{
589        AnyVar as _, AnyWeakVar as _, IntoValue, IntoVar, Var, VarValue, WeakVar as _, context_var, expr_var, getter_var, merge_var,
590        state_var, var, var_from, when_var,
591    };
592
593    pub use crate::var::animation::easing;
594
595    pub use zng_layout::unit::{
596        Align, AngleUnits as _, ByteUnits as _, DipToPx as _, FactorUnits as _, Layout1d as _, Layout2d as _, Length, LengthUnits as _,
597        LineFromTuplesBuilder as _, PxToDip as _, RectFromTuplesBuilder as _, ResolutionUnits as _, TimeUnits as _,
598    };
599
600    pub use zng_txt::{ToTxt as _, Txt, formatx};
601
602    pub use zng_clone_move::{async_clmv, async_clmv_fn, async_clmv_fn_once, clmv};
603
604    pub use zng_color::{LightDarkVarExt as _, MixAdjust as _, colors, hex, hsl, hsla, hsv, hsva, light_dark, rgb, rgba, web_colors};
605
606    #[cfg(feature = "clipboard")]
607    pub use zng_ext_clipboard::CLIPBOARD;
608
609    #[cfg(feature = "config")]
610    pub use zng_ext_config::CONFIG;
611
612    pub use zng_ext_font::{FontStretch, FontStyle, FontWeight};
613
614    #[cfg(feature = "image")]
615    pub use zng_ext_image::ImageSource;
616
617    #[cfg(feature = "image")]
618    pub use zng_wgt_image::Image;
619
620    pub use zng_ext_input::{
621        focus::{FOCUS, WidgetInfoFocusExt as _, cmd::CommandFocusExt as _, iter::IterFocusableExt as _},
622        gesture::{CommandShortcutMatchesExt as _, HeadlessAppGestureExt as _},
623        keyboard::HeadlessAppKeyboardExt as _,
624        mouse::WidgetInfoMouseExt as _,
625    };
626
627    pub use zng_ext_l10n::{L10N, l10n, lang};
628
629    pub use zng_wgt_text::lang;
630
631    #[cfg(feature = "undo")]
632    pub use zng_ext_undo::{CommandUndoExt as _, REDO_CMD, UNDO, UNDO_CMD};
633
634    #[cfg(feature = "window")]
635    pub use zng_ext_window::{
636        AppRunWindowExt as _, HeadlessAppWindowExt as _, WINDOW_Ext as _, WINDOWS, WidgetInfoImeArea as _, WindowCloseRequestedArgs,
637        WindowIcon,
638    };
639
640    pub use zng_wgt::{CommandIconExt as _, ICONS, Wgt};
641
642    pub use crate::text;
643    pub use zng_wgt_text::Text;
644
645    #[cfg(feature = "text_input")]
646    pub use zng_wgt_text_input::{TextInput, selectable::SelectableText};
647
648    #[cfg(feature = "window")]
649    pub use crate::window;
650    #[cfg(feature = "window")]
651    pub use zng_wgt_window::Window;
652
653    pub use zng_wgt_container::Container;
654
655    #[cfg(feature = "button")]
656    pub use zng_wgt_button::Button;
657
658    #[cfg(feature = "data_context")]
659    pub use zng_wgt_data::{DATA, data};
660
661    #[cfg(feature = "grid")]
662    pub use crate::grid;
663    #[cfg(feature = "grid")]
664    pub use zng_wgt_grid::Grid;
665
666    pub use crate::layer;
667    pub use zng_wgt_layer::{AnchorMode, LAYERS, LayerIndex};
668
669    pub use crate::popup;
670    pub use zng_wgt_layer::popup::POPUP;
671
672    #[cfg(feature = "menu")]
673    pub use crate::menu;
674    #[cfg(feature = "menu")]
675    pub use zng_wgt_menu::{
676        Menu,
677        context::{ContextMenu, context_menu, context_menu_fn},
678        sub::SubMenu,
679    };
680
681    #[cfg(feature = "rule_line")]
682    pub use zng_wgt_rule_line::hr::Hr;
683
684    #[cfg(feature = "scroll")]
685    pub use zng_wgt_scroll::{SCROLL, Scroll};
686
687    #[cfg(feature = "toggle")]
688    pub use crate::toggle;
689    #[cfg(feature = "toggle")]
690    pub use zng_wgt_toggle::Toggle;
691
692    #[cfg(feature = "tooltip")]
693    pub use crate::tip;
694    #[cfg(feature = "tooltip")]
695    pub use zng_wgt_tooltip::{Tip, tooltip, tooltip_fn};
696
697    pub use zng_wgt::{WidgetFn, wgt_fn};
698
699    pub use zng_wgt_style::{Style, style_fn};
700
701    #[cfg(feature = "stack")]
702    pub use zng_wgt_stack::{Stack, StackDirection};
703
704    #[cfg(feature = "wrap")]
705    pub use zng_wgt_wrap::Wrap;
706
707    #[cfg(feature = "data_view")]
708    pub use zng_wgt_data_view::{DataView, DataViewArgs};
709
710    #[cfg(feature = "settings_editor")]
711    pub use zng_wgt_settings::SettingBuilderEditorExt as _;
712
713    #[cfg(feature = "dialog")]
714    pub use crate::dialog;
715    #[cfg(feature = "dialog")]
716    pub use zng_wgt_dialog::DIALOG;
717}
718
719/// Prelude for declaring new properties and widgets.
720///
721/// This prelude can be imported over [`prelude`].
722///
723/// # Examples
724///
725/// ```
726/// # fn main() { }
727/// use zng::{prelude::*, prelude_wgt::*};
728///
729/// /// A button with only text child.
730/// #[widget($crate::TextButton)]
731/// pub struct TextButton(Button);
732///
733/// /// Button text.
734/// #[property(CHILD, capture, widget_impl(TextButton))]
735/// pub fn txt(txt: impl IntoVar<Txt>) { }
736///
737/// impl TextButton {
738///     fn widget_intrinsic(&mut self) {
739///         self.widget_builder().push_build_action(|b| {
740///             let txt = b
741///                     .capture_var::<Txt>(property_id!(Self::txt))
742///                     .unwrap_or_else(|| LocalVar(Txt::from("")).boxed());
743///             b.set_child(Text!(txt));
744///         });
745///     }
746/// }
747/// ```
748pub mod prelude_wgt {
749    #[doc(no_inline)]
750    pub use crate::__prelude_wgt::*;
751}
752mod __prelude_wgt {
753    pub use zng_app::{
754        DInstant, Deadline, INSTANT,
755        event::{
756            AnyEventArgs as _, Command, CommandHandle, CommandInfoExt as _, CommandNameExt as _, CommandParam, Event, EventArgs as _,
757            EventHandle, EventHandles, EventPropagationHandle, command, event, event_args,
758        },
759        handler::{AppHandler, WidgetHandler, app_hn, app_hn_once, async_app_hn, async_app_hn_once, async_hn, async_hn_once, hn, hn_once},
760        render::{FrameBuilder, FrameUpdate, FrameValue, FrameValueKey, FrameValueUpdate, SpatialFrameId, TransformStyle},
761        shortcut::{CommandShortcutExt as _, Shortcut, ShortcutFilter, Shortcuts, shortcut},
762        timer::{DeadlineHandle, DeadlineVar, TIMERS, TimerHandle, TimerVar},
763        update::{EventUpdate, UPDATES, UpdateDeliveryList, UpdateOp, WidgetUpdates},
764        widget::{
765            AnyVarSubscribe as _, VarLayout as _, VarSubscribe as _, WIDGET, WidgetId, WidgetUpdateMode,
766            base::{WidgetBase, WidgetImpl},
767            border::{BORDER, BorderSides, BorderStyle, CornerRadius, CornerRadiusFit, LineOrientation, LineStyle},
768            builder::{NestGroup, WidgetBuilder, WidgetBuilding, property_id},
769            easing,
770            info::{
771                InteractionPath, Interactivity, Visibility, WidgetBorderInfo, WidgetBoundsInfo, WidgetInfo, WidgetInfoBuilder,
772                WidgetLayout, WidgetMeasure, WidgetPath,
773            },
774            node::{
775                ArcNode, ArcNodeList, BoxedUiNode, BoxedUiNodeList, EditableUiNodeList, EditableUiNodeListRef, FillUiNode, NilUiNode,
776                PanelList, SORTING_LIST, SortingList, UiNode, UiNodeList, UiNodeListChain as _, UiNodeListObserver, UiNodeOp, UiVec,
777                ZIndex, match_node, match_node_leaf, match_node_list, match_node_typed, match_widget, ui_vec,
778            },
779            property, ui_node, widget, widget_impl, widget_mixin, widget_set,
780        },
781        window::{MonitorId, WINDOW, WindowId},
782    };
783
784    pub use zng_var::{
785        AnyVar as _, AnyWeakVar as _, ArcVar, BoxedVar, ContextVar, IntoValue, IntoVar, LocalVar, ReadOnlyArcVar, ResponderVar,
786        ResponseVar, Var, VarCapability, VarHandle, VarHandles, VarValue, WeakVar as _, context_var, expr_var, getter_var,
787        impl_from_and_into_var, merge_var, response_done_var, response_var, state_var, var, when_var,
788    };
789
790    pub use zng_layout::{
791        context::{DIRECTION_VAR, LAYOUT, LayoutDirection, LayoutMetrics},
792        unit::{
793            Align, AngleDegree, AngleGradian, AngleRadian, AngleUnits as _, ByteUnits as _, Dip, DipBox, DipPoint, DipRect, DipSideOffsets,
794            DipSize, DipToPx as _, DipVector, Factor, Factor2d, FactorPercent, FactorSideOffsets, FactorUnits as _, Layout1d as _,
795            Layout2d as _, LayoutAxis, Length, LengthUnits as _, Line, LineFromTuplesBuilder as _, Point, Px, PxBox, PxConstraints,
796            PxConstraints2d, PxCornerRadius, PxLine, PxPoint, PxRect, PxSideOffsets, PxSize, PxToDip as _, PxTransform, PxVector, Rect,
797            RectFromTuplesBuilder as _, ResolutionUnits as _, SideOffsets, Size, TimeUnits as _, Transform, Vector,
798        },
799    };
800
801    pub use zng_txt::{ToTxt as _, Txt, formatx};
802
803    pub use zng_clone_move::{async_clmv, async_clmv_fn, async_clmv_fn_once, clmv};
804
805    pub use crate::task;
806
807    pub use zng_app_context::{CaptureFilter, ContextLocal, ContextValueSet, LocalContext, RunOnDrop, app_local, context_local};
808
809    pub use crate::state_map;
810    pub use zng_state_map::{OwnedStateMap, StateId, StateMapMut, StateMapRef, static_id};
811
812    pub use zng_wgt::prelude::{IdEntry, IdMap, IdSet};
813
814    pub use zng_wgt::{WidgetFn, wgt_fn};
815
816    pub use zng_color::{
817        ColorScheme, Hsla, Hsva, LightDark, MixAdjust as _, MixBlendMode, Rgba, colors, gradient, hex, hsl, hsla, hsv, hsva, light_dark,
818        rgb, rgba, web_colors,
819    };
820
821    pub use zng_wgt::node::{
822        bind_state, bind_state_init, border_node, command_property, event_property, event_state, event_state2, event_state3, event_state4,
823        fill_node, list_presenter, presenter, presenter_opt, widget_state_get_state, widget_state_is_state, with_context_blend,
824        with_context_local, with_context_local_init, with_context_var, with_context_var_init, with_widget_state, with_widget_state_modify,
825    };
826
827    #[cfg(feature = "window")]
828    pub use zng_ext_window::WidgetInfoBuilderImeArea as _;
829
830    #[cfg(hot_reload)]
831    pub use crate::hot_reload::hot_node;
832}
833
834mod defaults {
835    use zng_app::{AppExtended, AppExtension};
836    #[cfg(feature = "clipboard")]
837    use zng_ext_clipboard::ClipboardManager;
838    #[cfg(feature = "config")]
839    use zng_ext_config::ConfigManager;
840    use zng_ext_font::FontManager;
841    #[cfg(feature = "fs_watcher")]
842    use zng_ext_fs_watcher::FsWatcherManager;
843    #[cfg(feature = "image")]
844    use zng_ext_image::ImageManager;
845    use zng_ext_input::{
846        focus::FocusManager, gesture::GestureManager, keyboard::KeyboardManager, mouse::MouseManager,
847        pointer_capture::PointerCaptureManager, touch::TouchManager,
848    };
849
850    #[cfg(feature = "drag_drop")]
851    use zng_ext_input::drag_drop::DragDropManager;
852
853    use zng_ext_l10n::L10nManager;
854    #[cfg(feature = "undo")]
855    use zng_ext_undo::UndoManager;
856
857    #[cfg(feature = "window")]
858    use zng_ext_window::WindowManager;
859
860    use crate::default_editors;
861
862    #[cfg(feature = "dyn_app_extension")]
863    macro_rules! DefaultsAppExtended {
864        () => {
865            AppExtended<Vec<Box<dyn zng_app::AppExtensionBoxed>>>
866        }
867    }
868    #[cfg(not(feature = "dyn_app_extension"))]
869    macro_rules! DefaultsAppExtended {
870        () => {
871            AppExtended<impl AppExtension>
872        }
873    }
874
875    impl super::APP {
876        /// App with default extensions.
877        ///     
878        /// # Extensions
879        ///
880        /// Extensions included.
881        ///
882        /// * [`FsWatcherManager`] if the `"fs_watcher"` feature is enabled.
883        /// * [`ConfigManager`] if the `"config"` feature is enabled.
884        /// * [`L10nManager`]
885        /// * [`PointerCaptureManager`]
886        /// * [`MouseManager`]
887        /// * [`TouchManager`]
888        /// * [`KeyboardManager`]
889        /// * [`GestureManager`]
890        /// * [`WindowManager`] if the `"window"` feature is enabled.
891        /// * [`FontManager`]
892        /// * [`FocusManager`]
893        /// * [`DragDropManager`] if the `"drag_drop"` feature is enabled.
894        /// * [`ImageManager`] if the `"image"` feature is enabled.
895        /// * [`ClipboardManager`] if the `"clipboard"` feature is enabled.
896        /// * [`UndoManager`]
897        /// * [`SingleInstanceManager`] if the `"single_instance"` feature is enabled.
898        /// * [`HotReloadManager`] if the `"hot_reload"` feature is enabled.
899        /// * [`MaterialIconsManager`] if any `"material_icons*"` feature is enabled.
900        /// * [`SvgManager`] if the `"svg"` feature is enabled.
901        ///
902        /// [`MaterialIconsManager`]: zng_wgt_material_icons::MaterialIconsManager
903        /// [`SingleInstanceManager`]: zng_ext_single_instance::SingleInstanceManager
904        /// [`HotReloadManager`]: zng_ext_hot_reload::HotReloadManager
905        /// [`ConfigManager`]: zng_ext_config::ConfigManager
906        /// [`L10nManager`]: zng_ext_l10n::L10nManager
907        /// [`FontManager`]: zng_ext_font::FontManager
908        /// [`SvgManager`]: zng_ext_svg::SvgManager
909        pub fn defaults(&self) -> DefaultsAppExtended![] {
910            let r = self.minimal();
911
912            #[cfg(feature = "fs_watcher")]
913            let r = r.extend(FsWatcherManager::default());
914
915            #[cfg(feature = "config")]
916            let r = r.extend(ConfigManager::default());
917
918            let r = r.extend(L10nManager::default());
919
920            let r = r.extend(PointerCaptureManager::default());
921
922            let r = r.extend(MouseManager::default());
923
924            let r = r.extend(TouchManager::default());
925
926            let r = r.extend(KeyboardManager::default());
927
928            let r = r.extend(GestureManager::default());
929
930            #[cfg(feature = "window")]
931            let r = r.extend(WindowManager::default());
932
933            let r = r.extend(FontManager::default());
934
935            let r = r.extend(FocusManager::default());
936
937            #[cfg(feature = "drag_drop")]
938            let r = r.extend(DragDropManager::default());
939
940            #[cfg(feature = "image")]
941            let r = r.extend(ImageManager::default());
942
943            #[cfg(feature = "clipboard")]
944            let r = r.extend(ClipboardManager::default());
945
946            #[cfg(feature = "undo")]
947            let r = r.extend(UndoManager::default());
948
949            #[cfg(all(view, view_prebuilt))]
950            tracing::debug!(r#"both "view" and "view_prebuilt" enabled, will use only one, indeterminate witch"#);
951
952            #[cfg(single_instance)]
953            let r = r.extend(zng_ext_single_instance::SingleInstanceManager::default());
954
955            #[cfg(hot_reload)]
956            let r = r.extend(zng_ext_hot_reload::HotReloadManager::default());
957
958            #[cfg(any(
959                feature = "material_icons_outlined",
960                feature = "material_icons_filled",
961                feature = "material_icons_rounded",
962                feature = "material_icons_sharp",
963            ))]
964            let r = r.extend(zng_wgt_material_icons::MaterialIconsManager);
965
966            #[cfg(feature = "svg")]
967            let r = r.extend(zng_ext_svg::SvgManager::default());
968
969            r.extend(DefaultsInit {})
970        }
971    }
972
973    struct DefaultsInit {}
974    impl AppExtension for DefaultsInit {
975        fn init(&mut self) {
976            // Common editors.
977            zng_wgt::EDITORS.register_fallback(zng_wgt::WidgetFn::new(default_editors::handler));
978            tracing::debug!("defaults init, var_editor set");
979
980            // injected in all windows
981            #[cfg(feature = "window")]
982            {
983                zng_ext_window::WINDOWS.register_root_extender(|a| {
984                    let child = a.root;
985
986                    #[cfg(feature = "inspector")]
987                    let child = zng_wgt_inspector::inspector(child, zng_wgt_inspector::live_inspector(true));
988
989                    child
990                });
991                tracing::debug!("defaults init, root_extender set");
992            }
993            #[cfg(any(target_os = "android", target_os = "ios"))]
994            {
995                zng_ext_window::WINDOWS.register_open_nested_handler(crate::window::default_mobile_nested_open_handler);
996                tracing::debug!("defaults init, open_nested_handler set");
997            }
998
999            // setup OPEN_LICENSES_CMD handler
1000            #[cfg(all(feature = "third_party_default", feature = "third_party"))]
1001            {
1002                crate::third_party::setup_default_view();
1003                tracing::debug!("defaults init, third_party set");
1004            }
1005
1006            // setup SETTINGS_CMD handler
1007            #[cfg(feature = "settings_editor")]
1008            {
1009                zng_wgt_settings::handle_settings_cmd();
1010                tracing::debug!("defaults init, settings set");
1011            }
1012
1013            #[cfg(all(single_instance, feature = "window"))]
1014            {
1015                crate::app::APP_INSTANCE_EVENT
1016                    .on_pre_event(crate::handler::app_hn!(|args: &crate::app::AppInstanceArgs, _| {
1017                        use crate::window::*;
1018
1019                        // focus a window if none are focused.
1020                        if !args.is_current() && WINDOWS.focused_window_id().is_none() {
1021                            for w in WINDOWS.widget_trees() {
1022                                if w.is_rendered()
1023                                    && WINDOWS.mode(w.window_id()) == Ok(WindowMode::Headed)
1024                                    && WINDOWS.focus(w.window_id()).is_ok()
1025                                {
1026                                    break;
1027                                }
1028                            }
1029                        }
1030                    }))
1031                    .perm();
1032                tracing::debug!("defaults init, single_instance set");
1033            }
1034        }
1035
1036        fn deinit(&mut self) {
1037            // ensure zng_view_prebuilt is linked, macOS system linker can "optimize" the entire
1038            // crate away because it is only referenced by `linkme` in `on_process_start!`
1039            #[cfg(all(view_prebuilt, any(target_os = "macos", target_os = "ios")))]
1040            if std::env::var("=").is_ok() {
1041                crate::view_process::prebuilt::run_same_process(|| unreachable!());
1042            }
1043        }
1044    }
1045}
1046
1047#[doc = include_str!("../../README.md")]
1048#[cfg(doctest)]
1049pub mod read_me_test {}
1050
1051mod default_editors {
1052    use zng::{
1053        prelude::*,
1054        widget::{
1055            EditorRequestArgs,
1056            node::{BoxedUiNode, NilUiNode},
1057        },
1058    };
1059
1060    pub fn handler(args: EditorRequestArgs) -> BoxedUiNode {
1061        #[cfg(feature = "text_input")]
1062        if let Some(txt) = args.value::<Txt>() {
1063            return TextInput! {
1064                txt;
1065            }
1066            .boxed();
1067        }
1068        #[cfg(feature = "text_input")]
1069        if let Some(s) = args.value::<String>() {
1070            return TextInput! {
1071                txt = s.map_bidi(|s| Txt::from_str(s), |t: &Txt| t.to_string());
1072            }
1073            .boxed();
1074        }
1075        #[cfg(feature = "text_input")]
1076        if let Some(c) = args.value::<char>() {
1077            return TextInput! {
1078                txt_parse::<char> = c;
1079                style_fn = crate::text_input::FieldStyle!();
1080            }
1081            .boxed();
1082        }
1083
1084        #[cfg(feature = "toggle")]
1085        if let Some(checked) = args.value::<bool>() {
1086            return Toggle! {
1087                style_fn = toggle::CheckStyle!();
1088                checked;
1089            }
1090            .boxed();
1091        }
1092
1093        macro_rules! parse {
1094            ($($ty:ty),+ $(,)?) => {
1095                $(
1096                    #[cfg(feature = "text_input")]
1097                    if let Some(n) = args.value::<$ty>() {
1098                        return TextInput! {
1099                            txt_parse::<$ty> = n;
1100                            style_fn = crate::text_input::FieldStyle!();
1101                        }
1102                        .boxed();
1103                    }
1104
1105                )+
1106            }
1107        }
1108        parse! {
1109            u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64,
1110        }
1111
1112        let _ = args;
1113        NilUiNode.boxed()
1114    }
1115}