zng_app/
widget.rs

1//! Widget, UI node API.
2
3pub mod base;
4pub mod border;
5pub mod builder;
6pub mod info;
7pub mod inspector;
8pub mod node;
9
10mod easing;
11pub use easing::*;
12
13use atomic::Atomic;
14use parking_lot::{Mutex, RwLock};
15use std::{
16    borrow::Cow,
17    sync::{Arc, atomic::Ordering::Relaxed},
18};
19use zng_app_context::context_local;
20use zng_handle::Handle;
21use zng_layout::unit::{DipPoint, DipToPx as _, Layout1d, Layout2d, Px, PxPoint, PxTransform};
22use zng_state_map::{OwnedStateMap, StateId, StateMapMut, StateMapRef, StateValue};
23use zng_task::UiTask;
24use zng_txt::{Txt, formatx};
25use zng_var::{AnyVar, BoxAnyVarValue, ResponseVar, Var, VarHandle, VarHandles, VarValue};
26use zng_view_api::display_list::ReuseRange;
27
28use crate::{
29    event::{Event, EventArgs, EventHandle, EventHandles},
30    handler::{AppHandler, AppHandlerArgs, app_hn, app_hn_once},
31    update::{LayoutUpdates, RenderUpdates, UPDATES, UpdateFlags, UpdateOp, UpdatesTrace},
32    window::WINDOW,
33};
34
35use self::info::{WidgetBorderInfo, WidgetBoundsInfo, WidgetInfo};
36
37// proc-macros used internally during widget creation.
38#[doc(hidden)]
39pub use zng_app_proc_macros::{property_impl, property_meta, widget_new};
40
41pub use zng_app_proc_macros::{property, widget, widget_mixin};
42
43/// <span data-del-macro-root></span> Sets properties and when condition on a widget builder.
44///
45/// # Examples
46///
47/// ```
48/// # use zng_app::{*, widget::{base::*, node::*, widget, property}};
49/// # use zng_var::*;
50/// # #[property(CONTEXT)] pub fn enabled(child: impl IntoUiNode, enabled: impl IntoVar<bool>) -> UiNode { child.into_node() }
51/// # #[widget($crate::Wgt)]
52/// # pub struct Wgt(WidgetBase);
53/// # fn main() {
54/// # let flag = true;
55/// #
56/// let mut wgt = Wgt::widget_new();
57///
58/// if flag {
59///     widget_set! {
60///         &mut wgt;
61///         enabled = false;
62///     }
63/// }
64///
65/// widget_set! {
66///     &mut wgt;
67///     id = "wgt";
68/// }
69///
70/// let wgt = wgt.widget_build();
71/// # }
72/// ```
73///
74/// In the example above the widget will always build with custom `id`, but only will set `enabled = false` when `flag` is `true`.
75///
76/// Note that properties are designed to have a default *neutral* value that behaves as if unset, in the example case you could more easily write:
77///
78/// ```
79/// # zng_app::enable_widget_macros!();
80/// # use zng_app::{*, widget::{node::*, base::*, widget, property}};
81/// # use zng_color::*;
82/// # use zng_var::*;
83/// # #[widget($crate::Wgt)] pub struct Wgt(WidgetBase);
84/// # #[property(CONTEXT)] pub fn enabled(child: impl IntoUiNode, enabled: impl IntoVar<bool>) -> UiNode { child.into_node() }
85/// # fn main() {
86/// # let flag = true;
87/// let wgt = Wgt! {
88///     enabled = !flag;
89///     id = "wgt";
90/// };
91/// # }
92/// ```
93///
94/// You should use this macro only in contexts where a widget will be build in steps, or in very hot code paths where a widget
95/// has many properties and only some will be non-default per instance.
96///
97/// # Property Assign
98///
99/// Properties can be assigned using the `property = value;` syntax, this expands to a call to the property method, either
100/// directly implemented on the widget or from a trait.
101///
102/// ```
103/// # use zng_app::{*, widget::{node::*, property}};
104/// # use zng_color::*;
105/// # use zng_var::*;
106/// # use zng_layout::unit::*;
107/// # #[property(CONTEXT)] pub fn background_color(child: impl IntoUiNode, color: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
108/// # fn main() {
109/// # let wgt = zng_app::widget::base::WidgetBase! {
110/// id = "name";
111/// background_color = colors::BLUE;
112/// # }; }
113/// ```
114///
115/// The example above is equivalent to:
116///
117/// ```
118/// # use zng_app::{*, widget::{node::*, property}};
119/// # use zng_color::*;
120/// # use zng_var::*;
121/// # use zng_layout::unit::*;
122/// # #[property(CONTEXT)] pub fn background_color(child: impl IntoUiNode, color: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
123/// # fn main() {
124/// # let mut wgt = zng_app::widget::base::WidgetBase::widget_new();
125/// wgt.id("name");
126/// wgt.background_color(colors::BLUE);
127/// # }
128/// ```
129///
130/// Note that `id` is an intrinsic property inherited from [`WidgetBase`], but `background_color` is an extension property declared
131/// by a [`property`] function. Extension properties require `&mut self` access to the widget, intrinsic properties only require `&self`,
132/// this is done so that IDEs that use a different style for mutable methods highlight the properties that are not intrinsic to the widget.
133///
134/// ## Path Assign
135///
136/// A full or partial path can be used to specify exactly what extension property will be set:
137///
138/// ```
139/// # use zng_app::{*, widget::{node::*, property}};
140/// # use zng_color::*;
141/// # use zng_var::*;
142/// # use zng_layout::unit::*;
143/// # #[property(CONTEXT)] pub fn background_color(child: impl IntoUiNode, color: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
144/// # fn main() {
145/// # let wgt = zng_app::widget::base::WidgetBase! {
146/// self::background_color = colors::BLUE;
147/// # }; }
148/// ```
149///
150/// In the example above `self::background_color` specify that an extension property that is imported in the `self` module must be set,
151/// even if the widget gets an intrinsic `background_color` property the extension property will still be used.
152///
153/// The example above is equivalent to:
154///
155/// ```
156/// # use zng_app::{*, widget::{node::*, property}};
157/// # use zng_color::*;
158/// # use zng_var::*;
159/// # use zng_layout::unit::*;
160/// # #[property(CONTEXT)] pub fn background_color(child: impl IntoUiNode, color: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
161/// # fn main() {
162/// # let mut wgt = zng_app::widget::base::WidgetBase::widget_new();
163/// self::background_color::background_color(&mut wgt, colors::BLUE);
164/// # }
165/// ```
166///
167/// ## Named Assign
168///
169/// Properties can have multiple parameters, multiple parameters can be set using the struct init syntax:
170///
171/// ```rust,no_fmt
172/// # use zng_app::{*, widget::{node::*, property}};
173/// # use zng_color::*;
174/// # use zng_var::*;
175/// # use zng_layout::unit::*;
176/// # #[property(CONTEXT)] pub fn border(child: impl IntoUiNode, widths: impl IntoVar<SideOffsets>, sides: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
177/// # fn main() {
178/// # let wgt = zng_app::widget::base::WidgetBase! {
179/// border = {
180///     widths: 1,
181///     sides: colors::RED,
182/// };
183/// # }; }
184/// ```
185///
186/// Note that just like in struct init the parameters don't need to be in order:
187///
188/// ```rust,no_fmt
189/// # use zng_app::{*, widget::{node::*, property}};
190/// # use zng_color::*;
191/// # use zng_var::*;
192/// # use zng_layout::unit::*;
193/// # #[property(CONTEXT)] pub fn border(child: impl IntoUiNode, widths: impl IntoVar<SideOffsets>, sides: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
194/// # fn main() {
195/// # let wgt = zng_app::widget::base::WidgetBase! {
196/// border = {
197///     sides: colors::RED,
198///     widths: 1,
199/// };
200/// # }; }
201/// ```
202///
203/// Internally each property method has auxiliary methods that validate the member names and construct the property using sorted params, therefore
204/// accepting any parameter order. Note each parameter is evaluated in the order they appear, even if they are assigned in a different order after.
205///
206/// ```rust,no_fmt
207/// # use zng_app::{*, widget::{node::*, property}};
208/// # use zng_color::*;
209/// # use zng_var::*;
210/// # use zng_layout::unit::*;
211/// # #[property(CONTEXT)] pub fn border(child: impl IntoUiNode, widths: impl IntoVar<SideOffsets>, sides: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
212/// # fn main() {
213/// let mut eval_order = vec![];
214///
215/// # let wgt = zng_app::widget::base::WidgetBase! {
216/// border = {
217///     sides: {
218///         eval_order.push("sides");
219///         colors::RED
220///     },
221///     widths: {
222///         eval_order.push("widths");
223///         1
224///     },
225/// };
226/// # };
227///
228/// assert_eq!(eval_order, vec!["sides", "widths"]);
229/// # }
230/// ```
231///
232/// ## Unnamed Assign Multiple
233///
234/// Properties with multiple parameters don't need to be set using the named syntax:
235///
236/// ```rust,no_fmt
237/// # use zng_app::{*, widget::{node::*, property}};
238/// # use zng_color::*;
239/// # use zng_var::*;
240/// # use zng_layout::unit::*;
241/// # #[property(CONTEXT)] pub fn border(child: impl IntoUiNode, widths: impl IntoVar<SideOffsets>, sides: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
242/// # fn main() {
243/// # let wgt = zng_app::widget::base::WidgetBase! {
244/// border = 1, colors::RED;
245/// # }; }
246/// ```
247///
248/// The example above is equivalent to:
249///
250/// ```
251/// # use zng_app::{*, widget::{node::*, property}};
252/// # use zng_color::*;
253/// # use zng_var::*;
254/// # use zng_layout::unit::*;
255/// # #[property(CONTEXT)] pub fn border(child: impl IntoUiNode, widths: impl IntoVar<SideOffsets>, sides: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
256/// # fn main() {
257/// # let mut wgt = zng_app::widget::base::WidgetBase::widget_new();
258/// wgt.border(1, colors::RED);
259/// # }
260/// ```
261///
262/// ## Shorthand Assign
263///
264/// Is a variable with the same name as a property is in context the `= name` can be omitted:
265///
266/// ```
267/// # use zng_app::{*, widget::{node::*, property}};
268/// # use zng_color::*;
269/// # use zng_var::*;
270/// # use zng_layout::unit::*;
271/// # #[property(CONTEXT)] pub fn background_color(child: impl IntoUiNode, color: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
272/// # #[property(CONTEXT)] pub fn border(child: impl IntoUiNode, widths: impl IntoVar<SideOffsets>, sides: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
273/// # fn main() {
274/// let id = "name";
275/// let background_color = colors::BLUE;
276/// let widths = 1;
277///
278/// let wgt = zng_app::widget::base::WidgetBase! {
279///     id;
280///     self::background_color;
281///     border = {
282///         widths,
283///         sides: colors::RED,
284///     };
285/// };
286/// # }
287/// ```
288///
289/// Note that the shorthand syntax also works for path properties and parameter names.
290///
291/// The above is equivalent to:
292///
293/// ```
294/// # use zng_app::{*, widget::{node::*, property}};
295/// # use zng_color::*;
296/// # use zng_var::*;
297/// # use zng_layout::unit::*;
298/// # #[property(CONTEXT)] pub fn background_color(child: impl IntoUiNode, color: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
299/// # #[property(CONTEXT)] pub fn border(child: impl IntoUiNode, widths: impl IntoVar<SideOffsets>, sides: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
300/// # fn main() {
301/// let id = "name";
302/// let background_color = colors::BLUE;
303/// let widths = 1;
304///
305/// let wgt = zng_app::widget::base::WidgetBase! {
306///     id = id;
307///     self::background_color = background_color;
308///     border = {
309///         widths: widths,
310///         sides: colors::RED,
311///     };
312/// };
313/// # }
314/// ```
315///
316/// # Property Unset
317///
318/// All properties can be assigned to an special value `unset!`, that *removes* a property, when the widget is build the
319/// unset property will not be instantiated:
320///
321/// ```rust,no_fmt
322/// # use zng_app::{*, widget::{node::*, property}};
323/// # use zng_color::*;
324/// # use zng_var::*;
325/// # use zng_layout::unit::*;
326/// # #[property(CONTEXT)] pub fn border(child: impl IntoUiNode, widths: impl IntoVar<SideOffsets>, sides: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
327/// # fn main() {
328/// # let wgt = zng_app::widget::base::WidgetBase! {
329/// border = unset!;
330/// # }; }
331/// ```
332///
333/// The example above is equivalent to:
334///
335/// ```
336/// # use zng_app::{*, widget::{node::*, property}};
337/// # use zng_color::*;
338/// # use zng_var::*;
339/// # use zng_layout::unit::*;
340/// # #[property(CONTEXT)] pub fn border(child: impl IntoUiNode, widths: impl IntoVar<SideOffsets>, sides: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
341/// # fn main() {
342/// # let mut wgt = zng_app::widget::base::WidgetBase::widget_new();
343/// wgt.unset_border();
344/// # }
345/// ```
346///
347/// Each property method generates an auxiliary `unset_property` method, the unset is registered in the widget builder using the current
348/// importance, in `widget_intrinsic` they only unset already inherited default assigns, in instances it unsets all inherited or
349/// previous assigns, see [`WidgetBuilder::push_unset`] for more details.
350///
351/// # Generic Properties
352///
353/// Generic properties need a *turbofish* annotation on assign:
354///
355/// ```rust,no_fmt
356/// # use zng_app::{*, widget::{node::*, property}};
357/// # use zng_color::*;
358/// # use zng_var::*;
359/// # use zng_layout::unit::*;
360/// # #[property(CONTEXT)] pub fn value<T: VarValue>(child: impl IntoUiNode, value: impl IntoVar<T>) -> UiNode { child.into_node() }
361/// #
362/// # fn main() {
363/// # let wgt = zng_app::widget::base::WidgetBase! {
364/// value::<f32> = 1.0;
365/// # };}
366/// ```
367///
368/// # When
369///
370/// Conditional property assigns can be setup using `when` blocks. A `when` block has a `bool` expression and property assigns,
371/// when the expression is `true` each property has the assigned value, unless it is overridden by a later `when` block.
372///
373/// ```rust,no_fmt
374/// # use zng_app::{*, widget::{node::*, property}};
375/// # use zng_color::*;
376/// # use zng_var::*;
377/// # use zng_layout::unit::*;
378/// # #[property(CONTEXT)] pub fn background_color(child: impl IntoUiNode, color: impl IntoVar<Rgba>) -> UiNode { child.into_node() }
379/// # #[property(EVENT)] pub fn is_pressed(child: impl IntoUiNode, state: impl IntoVar<bool>) -> UiNode { child.into_node() }
380/// # fn main() {
381/// # let _scope = APP.minimal();
382/// # let wgt = zng_app::widget::base::WidgetBase! {
383/// background_color = colors::RED;
384///
385/// when *#is_pressed {
386///     background_color = colors::GREEN;
387/// }
388/// # }; }
389/// ```
390///
391/// ## When Condition
392///
393/// The `when` block defines a condition expression, in the example above this is `*#is_pressed`. The expression can be any Rust expression
394/// that results in a [`bool`] value, you can reference properties in it using the `#` token followed by the property name or path and you
395/// can reference variables in it using the `#{var}` syntax. If a property or var is referenced the `when` block is dynamic, updating all
396/// assigned properties when the expression result changes.
397///
398/// ### Property Reference
399///
400/// The most common `when` expression reference is a property, in the example above the `is_pressed` property is instantiated for the widget
401/// and it controls when the background is set to green. Note that a reference to the value is inserted in the expression
402/// so an extra deref `*` is required. A property can also be referenced with a path, `#properties::is_pressed` also works.
403///
404/// The syntax seen so far is actually a shorthand way to reference the first input of a property, the full syntax is `#is_pressed.0` or
405/// `#is_pressed.state`. You can use the extended syntax to reference inputs of properties with more than one input, the input can be
406/// reference by tuple-style index or by name. Note that if the value it self is a tuple or `struct` you need to use the extended syntax
407/// to reference a member of the value, `#foo.0.0` or `#foo.0.name`. Methods have no ambiguity, `#foo.name()` is the same as `#foo.0.name()`.
408///
409/// Not all properties can be referenced in `when` conditions, only inputs of type `impl IntoVar<T>` and `impl IntoValue<T>` are
410/// allowed, attempting to reference a different kind of input generates a compile error.
411///
412/// ### Variable Reference
413///
414/// Other variable can also be referenced, context variables or any locally declared variable can be referenced. Like with properties
415/// the variable value is inserted in the expression as a reference so you may need to deref in case the var is a simple [`Copy`] value.
416///
417/// ```rust,no_fmt
418/// # use zng_app::{*, widget::{node::*, property, self}};
419/// # use zng_color::*;
420/// # use zng_var::*;
421/// # use zng_layout::unit::*;
422/// #
423/// # #[property(FILL)]
424/// # pub fn background_color(child: impl IntoUiNode, color: impl IntoVar<Rgba>) -> UiNode {
425/// #   let _ = color;
426/// #   child.into_node()
427/// # }
428/// #
429/// context_var! {
430///     pub static FOO_VAR: Vec<&'static str> = vec![];
431///     pub static BAR_VAR: bool = false;
432/// }
433///
434/// # fn main() {
435/// # let _scope = APP.minimal();
436/// # let wgt = widget::base::WidgetBase! {
437/// background_color = colors::RED;
438/// when !*#{BAR_VAR} && #{FOO_VAR}.contains(&"green") {
439///     background_color = colors::GREEN;
440/// }
441/// # };}
442/// ```
443///
444/// ## When Assigns
445///
446/// Inside the `when` block a list of property assigns is expected, most properties can be assigned, but `impl IntoValue<T>` properties cannot,
447/// you also cannot `unset!` in when assigns, a compile time error happens if the property cannot be assigned.
448///
449/// On instantiation a single instance of the property will be generated, the parameters will track the when expression state and update
450/// to the value assigned when it is `true`. When no block is `true` the value assigned to the property outside `when` blocks is used, or the property default value. When more then one block is `true` the *last* one sets the value.
451///
452/// ### Default Values
453///
454/// A when assign can be defined by a property without setting a default value, during instantiation if the property declaration has
455/// a default value it is used, or if the property was later assigned a value it is used as *default*, if it is not possible to generate
456/// a default value the property is not instantiated and the when assign is not used.
457///
458/// The same apply for properties referenced in the condition expression, note that all `is_state` properties have a default value so
459/// it is more rare that a default value is not available. If a condition property cannot be generated the entire when block is ignored.
460///
461/// [`WidgetBase`]: struct@crate::widget::base::WidgetBase
462/// [`WidgetBuilder::push_unset`]: crate::widget::builder::WidgetBuilder::push_unset
463#[macro_export]
464macro_rules! widget_set {
465    (
466        $(#[$skip:meta])*
467        $($invalid:ident)::+ = $($tt:tt)*
468    ) => {
469        compile_error!{
470            "expected `&mut <wgt>;` at the beginning"
471        }
472    };
473    (
474        $(#[$skip:meta])*
475        when = $($invalid:tt)*
476    ) => {
477        compile_error!{
478            "expected `&mut <wgt>;` at the beginning"
479        }
480    };
481    (
482        $wgt_mut:ident;
483        $($tt:tt)*
484    ) => {
485        $crate::widget::widget_set! {
486            &mut *$wgt_mut;
487            $($tt)*
488        }
489    };
490    (
491        $wgt_borrow_mut:expr;
492        $($tt:tt)*
493    ) => {
494        $crate::widget::widget_new! {
495            new {
496                let wgt__ = $wgt_borrow_mut;
497            }
498            build { }
499            set { $($tt)* }
500        }
501    };
502}
503#[doc(inline)]
504pub use widget_set;
505
506/// <span data-del-macro-root></span> Implement a property on the widget to strongly associate it with the widget.
507///
508/// Widget implemented properties can be used on the widget without needing to be imported, they also show in
509/// the widget documentation page. As a general rule only properties that are captured by the widget, or only work with the widget,
510/// or have an special meaning in the widget are implemented like this, standalone properties that can be used in
511/// any widget are not implemented.
512///
513/// Note that you can also implement a property for a widget in the property declaration using the
514/// `impl(Widget)` directive in the [`property`] macro.
515///
516/// # Syntax
517///
518/// The macro syntax is one or more impl declarations, each declaration can have docs followed by the implementation
519/// visibility, usually `pub`, followed by the path to the property function, followed by a parenthesized list of
520/// the function input arguments, terminated by semicolon.
521///
522/// `pub path::to::property(input: impl IntoVar<bool>);`
523///
524/// # Examples
525///
526/// The example below declares a widget and uses this macro to implements the `align` property for the widget.
527///
528/// ```
529/// # fn main() { }
530/// # use zng_app::widget::{*, node::{UiNode, IntoUiNode}, base::WidgetBase};
531/// # use zng_layout::unit::Align;
532/// # use zng_var::IntoVar;
533/// # mod zng { use super::*; pub mod widget { use super::*; #[zng_app::widget::property(LAYOUT)] pub fn align(child: impl IntoUiNode, align: impl IntoVar<Align>) -> UiNode { child.into_node() } } }
534/// #
535/// #[widget($crate::MyWgt)]
536/// pub struct MyWgt(WidgetBase);
537///
538/// impl MyWgt {
539///     widget_impl! {
540///         /// Docs for the property in the widget.
541///         pub zng::widget::align(align: impl IntoVar<Align>);
542///     }
543/// }
544/// ```
545#[macro_export]
546macro_rules! widget_impl {
547    (
548        $(
549            $(#[$attr:meta])*
550            $vis:vis $($property:ident)::+ ($($arg:ident : $arg_ty:ty)*);
551        )+
552    ) => {
553        $(
554            $crate::widget::property_impl! {
555                attrs { $(#[$attr])* }
556                vis { $vis }
557                path { $($property)::* }
558                args { $($arg:$arg_ty),* }
559            }
560        )+
561    }
562}
563#[doc(inline)]
564pub use widget_impl;
565
566zng_unique_id::unique_id_64! {
567    /// Unique ID of a widget.
568    ///
569    /// # Name
570    ///
571    /// IDs are only unique for the same process.
572    /// You can associate a [`name`] with an ID to give it a persistent identifier.
573    ///
574    /// [`name`]: WidgetId::name
575    pub struct WidgetId;
576}
577zng_unique_id::impl_unique_id_name!(WidgetId);
578zng_unique_id::impl_unique_id_fmt!(WidgetId);
579zng_unique_id::impl_unique_id_bytemuck!(WidgetId);
580
581zng_var::impl_from_and_into_var! {
582    /// Calls [`WidgetId::named`].
583    fn from(name: &'static str) -> WidgetId {
584        WidgetId::named(name)
585    }
586    /// Calls [`WidgetId::named`].
587    fn from(name: String) -> WidgetId {
588        WidgetId::named(name)
589    }
590    /// Calls [`WidgetId::named`].
591    fn from(name: Cow<'static, str>) -> WidgetId {
592        WidgetId::named(name)
593    }
594    /// Calls [`WidgetId::named`].
595    fn from(name: char) -> WidgetId {
596        WidgetId::named(name)
597    }
598    /// Calls [`WidgetId::named`].
599    fn from(name: Txt) -> WidgetId {
600        WidgetId::named(name)
601    }
602    fn from(id: WidgetId) -> zng_view_api::access::AccessNodeId {
603        zng_view_api::access::AccessNodeId(id.get())
604    }
605
606    fn from(some: WidgetId) -> Option<WidgetId>;
607}
608impl serde::Serialize for WidgetId {
609    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
610    where
611        S: serde::Serializer,
612    {
613        let name = self.name();
614        if name.is_empty() {
615            use serde::ser::Error;
616            return Err(S::Error::custom("cannot serialize unnamed `WidgetId`"));
617        }
618        name.serialize(serializer)
619    }
620}
621impl<'de> serde::Deserialize<'de> for WidgetId {
622    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
623    where
624        D: serde::Deserializer<'de>,
625    {
626        let name = Txt::deserialize(deserializer)?;
627        Ok(WidgetId::named(name))
628    }
629}
630
631/// Defines how widget update requests inside [`WIDGET::with_context`] are handled.
632#[derive(Debug, Clone, Copy, PartialEq, Eq)]
633pub enum WidgetUpdateMode {
634    /// All updates flagged during the closure call are discarded, previous pending
635    /// requests are retained.
636    ///
637    /// This mode is used by [`UiNodeOp::Measure`].
638    ///
639    /// [`UiNodeOp::Measure`]: crate::widget::node::UiNodeOp::Measure
640    Ignore,
641    /// All updates flagged after the closure call are retained and propagate to the parent widget flags.
642    ///
643    /// This is the mode is used for all [`UiNodeOp`] delegation, except measure.
644    ///
645    /// [`UiNodeOp`]: crate::widget::node::UiNodeOp
646    Bubble,
647}
648
649/// Current context widget.
650///
651/// # Panics
652///
653/// Most of the methods on this service panic if not called inside a widget context.
654pub struct WIDGET;
655impl WIDGET {
656    /// Returns `true` if called inside a widget.
657    pub fn is_in_widget(&self) -> bool {
658        !WIDGET_CTX.is_default()
659    }
660
661    /// Get the widget ID, if called inside a widget.
662    pub fn try_id(&self) -> Option<WidgetId> {
663        if self.is_in_widget() { Some(WIDGET_CTX.get().id) } else { None }
664    }
665
666    /// Gets a text with detailed path to the current widget.
667    ///
668    /// This can be used to quickly identify the current widget during debug, the path printout will contain
669    /// the widget types if the inspector metadata is found for the widget.
670    ///
671    /// This method does not panic if called outside of a widget.
672    pub fn trace_path(&self) -> Txt {
673        if let Some(w_id) = WINDOW.try_id() {
674            if let Some(id) = self.try_id() {
675                let tree = WINDOW.info();
676                if let Some(wgt) = tree.get(id) {
677                    wgt.trace_path()
678                } else {
679                    formatx!("{w_id:?}//<no-info>/{id:?}")
680                }
681            } else {
682                formatx!("{w_id:?}//<no-widget>")
683            }
684        } else if let Some(id) = self.try_id() {
685            formatx!("<no-window>//{id:?}")
686        } else {
687            Txt::from_str("<no-widget>")
688        }
689    }
690
691    /// Gets a text with a detailed widget id.
692    ///
693    /// This can be used to quickly identify the current widget during debug, the printout will contain the widget
694    /// type if the inspector metadata is found for the widget.
695    ///
696    /// This method does not panic if called outside of a widget.
697    pub fn trace_id(&self) -> Txt {
698        if let Some(id) = self.try_id() {
699            if WINDOW.try_id().is_some() {
700                let tree = WINDOW.info();
701                if let Some(wgt) = tree.get(id) {
702                    wgt.trace_id()
703                } else {
704                    formatx!("{id:?}")
705                }
706            } else {
707                formatx!("{id:?}")
708            }
709        } else {
710            Txt::from("<no-widget>")
711        }
712    }
713
714    /// Get the widget ID.
715    pub fn id(&self) -> WidgetId {
716        WIDGET_CTX.get().id
717    }
718
719    /// Gets the widget info.
720    pub fn info(&self) -> WidgetInfo {
721        WINDOW.info().get(WIDGET.id()).expect("widget info not init")
722    }
723
724    /// Widget bounds, updated every layout.
725    pub fn bounds(&self) -> WidgetBoundsInfo {
726        WIDGET_CTX.get().bounds.lock().clone()
727    }
728
729    /// Widget border, updated every layout.
730    pub fn border(&self) -> WidgetBorderInfo {
731        WIDGET_CTX.get().border.lock().clone()
732    }
733
734    /// Gets the parent widget or `None` if is root.
735    ///
736    /// Panics if not called inside a widget.
737    pub fn parent_id(&self) -> Option<WidgetId> {
738        WIDGET_CTX.get().parent_id.load(Relaxed)
739    }
740
741    /// Schedule an [`UpdateOp`] for the current widget.
742    pub fn update_op(&self, op: UpdateOp) -> &Self {
743        match op {
744            UpdateOp::Update => self.update(),
745            UpdateOp::Info => self.update_info(),
746            UpdateOp::Layout => self.layout(),
747            UpdateOp::Render => self.render(),
748            UpdateOp::RenderUpdate => self.render_update(),
749        }
750    }
751
752    fn update_impl(&self, flag: UpdateFlags) -> &Self {
753        let _ = WIDGET_CTX.get().flags.fetch_update(Relaxed, Relaxed, |mut f| {
754            if !f.contains(flag) {
755                f.insert(flag);
756                Some(f)
757            } else {
758                None
759            }
760        });
761        self
762    }
763
764    /// Schedule an update for the current widget.
765    ///
766    /// After the current update the app-extensions, parent window and widgets will update again.
767    pub fn update(&self) -> &Self {
768        UpdatesTrace::log_update();
769        self.update_impl(UpdateFlags::UPDATE)
770    }
771
772    /// Schedule an info rebuild for the current widget.
773    ///
774    /// After all requested updates apply the parent window and widgets will re-build the info tree.
775    pub fn update_info(&self) -> &Self {
776        UpdatesTrace::log_info();
777        self.update_impl(UpdateFlags::INFO)
778    }
779
780    /// Schedule a re-layout for the current widget.
781    ///
782    /// After all requested updates apply the parent window and widgets will re-layout.
783    pub fn layout(&self) -> &Self {
784        UpdatesTrace::log_layout();
785        self.update_impl(UpdateFlags::LAYOUT)
786    }
787
788    /// Schedule a re-render for the current widget.
789    ///
790    /// After all requested updates and layouts apply the parent window and widgets will re-render.
791    ///
792    /// This also overrides any pending [`render_update`] request.
793    ///
794    /// [`render_update`]: Self::render_update
795    pub fn render(&self) -> &Self {
796        UpdatesTrace::log_render();
797        self.update_impl(UpdateFlags::RENDER)
798    }
799
800    /// Schedule a frame update for the current widget.
801    ///
802    /// After all requested updates and layouts apply the parent window and widgets will update the frame.
803    ///
804    /// This request is supplanted by any [`render`] request.
805    ///
806    /// [`render`]: Self::render
807    pub fn render_update(&self) -> &Self {
808        UpdatesTrace::log_render();
809        self.update_impl(UpdateFlags::RENDER_UPDATE)
810    }
811
812    /// Flags the widget to re-init after the current update returns.
813    ///
814    /// The widget responds to this request differently depending on the node method that calls it:
815    ///
816    /// * [`UiNode::init`] and [`UiNode::deinit`]: Request is ignored, removed.
817    /// * [`UiNode::event`]: If the widget is pending a reinit, it is reinited first, then the event is propagated to child nodes.
818    ///   If a reinit is requested during event handling the widget is reinited immediately after the event handler.
819    /// * [`UiNode::update`]: If the widget is pending a reinit, it is reinited and the update ignored.
820    ///   If a reinit is requested during update the widget is reinited immediately after the update.
821    /// * Other methods: Reinit request is flagged and an [`UiNode::update`] is requested for the widget.
822    ///
823    /// [`UiNode::init`]: crate::widget::node::UiNode::init
824    /// [`UiNode::deinit`]: crate::widget::node::UiNode::deinit
825    /// [`UiNode::event`]: crate::widget::node::UiNode::event
826    /// [`UiNode::update`]: crate::widget::node::UiNode::update
827    pub fn reinit(&self) {
828        let _ = WIDGET_CTX.get().flags.fetch_update(Relaxed, Relaxed, |mut f| {
829            if !f.contains(UpdateFlags::REINIT) {
830                f.insert(UpdateFlags::REINIT);
831                Some(f)
832            } else {
833                None
834            }
835        });
836    }
837
838    /// Calls `f` with a read lock on the current widget state map.
839    pub fn with_state<R>(&self, f: impl FnOnce(StateMapRef<WIDGET>) -> R) -> R {
840        f(WIDGET_CTX.get().state.read().borrow())
841    }
842
843    /// Calls `f` with a write lock on the current widget state map.
844    pub fn with_state_mut<R>(&self, f: impl FnOnce(StateMapMut<WIDGET>) -> R) -> R {
845        f(WIDGET_CTX.get().state.write().borrow_mut())
846    }
847
848    /// Get the widget state `id`, if it is set.
849    pub fn get_state<T: StateValue + Clone>(&self, id: impl Into<StateId<T>>) -> Option<T> {
850        let id = id.into();
851        self.with_state(|s| s.get_clone(id))
852    }
853
854    /// Require the widget state `id`.
855    ///
856    /// Panics if the `id` is not set.
857    pub fn req_state<T: StateValue + Clone>(&self, id: impl Into<StateId<T>>) -> T {
858        let id = id.into();
859        self.with_state(|s| s.req(id).clone())
860    }
861
862    /// Set the widget state `id` to `value`.
863    ///
864    /// Returns the previous set value.
865    pub fn set_state<T: StateValue>(&self, id: impl Into<StateId<T>>, value: impl Into<T>) -> Option<T> {
866        let id = id.into();
867        let value = value.into();
868        self.with_state_mut(|mut s| s.set(id, value))
869    }
870
871    /// Sets the widget state `id` without value.
872    ///
873    /// Returns if the state `id` was already flagged.
874    pub fn flag_state(&self, id: impl Into<StateId<()>>) -> bool {
875        let id = id.into();
876        self.with_state_mut(|mut s| s.flag(id))
877    }
878
879    /// Calls `init` and sets `id` if it is not already set in the widget.
880    pub fn init_state<T: StateValue>(&self, id: impl Into<StateId<T>>, init: impl FnOnce() -> T) {
881        let id = id.into();
882        self.with_state_mut(|mut s| {
883            s.entry(id).or_insert_with(init);
884        });
885    }
886
887    /// Sets the `id` to the default value if it is not already set.
888    pub fn init_state_default<T: StateValue + Default>(&self, id: impl Into<StateId<T>>) {
889        self.init_state(id.into(), Default::default)
890    }
891
892    /// Returns `true` if the `id` is set or flagged in the widget.
893    pub fn contains_state<T: StateValue>(&self, id: impl Into<StateId<T>>) -> bool {
894        let id = id.into();
895        self.with_state(|s| s.contains(id))
896    }
897
898    /// Subscribe to receive [`UpdateOp`] when the `var` changes.
899    pub fn sub_var_op(&self, op: UpdateOp, var: &AnyVar) -> &Self {
900        let w = WIDGET_CTX.get();
901        let s = var.subscribe(op, w.id);
902
903        // function to avoid generics code bloat
904        fn push(w: Arc<WidgetCtxData>, s: VarHandle) {
905            if WIDGET_HANDLES_CTX.is_default() {
906                w.handles.var_handles.lock().push(s);
907            } else {
908                WIDGET_HANDLES_CTX.get().var_handles.lock().push(s);
909            }
910        }
911        push(w, s);
912
913        self
914    }
915
916    /// Subscribe to receive [`UpdateOp`] when the `var` changes and `predicate` approves the new value.
917    ///
918    /// Note that the `predicate` does not run in the widget context, it runs on the app context.
919    pub fn sub_var_op_when<T: VarValue>(
920        &self,
921        op: UpdateOp,
922        var: &Var<T>,
923        predicate: impl Fn(&T) -> bool + Send + Sync + 'static,
924    ) -> &Self {
925        let w = WIDGET_CTX.get();
926        let s = var.subscribe_when(op, w.id, predicate);
927
928        // function to avoid generics code bloat
929        fn push(w: Arc<WidgetCtxData>, s: VarHandle) {
930            if WIDGET_HANDLES_CTX.is_default() {
931                w.handles.var_handles.lock().push(s);
932            } else {
933                WIDGET_HANDLES_CTX.get().var_handles.lock().push(s);
934            }
935        }
936        push(w, s);
937
938        self
939    }
940
941    /// Subscribe to receive updates when the `var` changes.
942    pub fn sub_var(&self, var: &AnyVar) -> &Self {
943        self.sub_var_op(UpdateOp::Update, var)
944    }
945    /// Subscribe to receive updates when the `var` changes and the `predicate` approves the new value.
946    ///
947    /// Note that the `predicate` does not run in the widget context, it runs on the app context.
948    pub fn sub_var_when<T: VarValue>(&self, var: &Var<T>, predicate: impl Fn(&T) -> bool + Send + Sync + 'static) -> &Self {
949        self.sub_var_op_when(UpdateOp::Update, var, predicate)
950    }
951
952    /// Subscribe to receive info rebuild requests when the `var` changes.
953    pub fn sub_var_info(&self, var: &AnyVar) -> &Self {
954        self.sub_var_op(UpdateOp::Info, var)
955    }
956    /// Subscribe to receive info rebuild requests when the `var` changes and the `predicate` approves the new value.
957    ///
958    /// Note that the `predicate` does not run in the widget context, it runs on the app context.
959    pub fn sub_var_info_when<T: VarValue>(&self, var: &Var<T>, predicate: impl Fn(&T) -> bool + Send + Sync + 'static) -> &Self {
960        self.sub_var_op_when(UpdateOp::Info, var, predicate)
961    }
962
963    /// Subscribe to receive layout requests when the `var` changes.
964    pub fn sub_var_layout(&self, var: &AnyVar) -> &Self {
965        self.sub_var_op(UpdateOp::Layout, var)
966    }
967    /// Subscribe to receive layout requests when the `var` changes and the `predicate` approves the new value.
968    ///
969    /// Note that the `predicate` does not run in the widget context, it runs on the app context.
970    pub fn sub_var_layout_when<T: VarValue>(&self, var: &Var<T>, predicate: impl Fn(&T) -> bool + Send + Sync + 'static) -> &Self {
971        self.sub_var_op_when(UpdateOp::Layout, var, predicate)
972    }
973
974    /// Subscribe to receive render requests when the `var` changes.
975    pub fn sub_var_render(&self, var: &AnyVar) -> &Self {
976        self.sub_var_op(UpdateOp::Render, var)
977    }
978    /// Subscribe to receive render requests when the `var` changes and the `predicate` approves the new value.
979    ///
980    /// Note that the `predicate` does not run in the widget context, it runs on the app context.
981    pub fn sub_var_render_when<T: VarValue>(&self, var: &Var<T>, predicate: impl Fn(&T) -> bool + Send + Sync + 'static) -> &Self {
982        self.sub_var_op_when(UpdateOp::Render, var, predicate)
983    }
984
985    /// Subscribe to receive render update requests when the `var` changes.
986    pub fn sub_var_render_update(&self, var: &AnyVar) -> &Self {
987        self.sub_var_op(UpdateOp::RenderUpdate, var)
988    }
989    /// Subscribe to receive render update requests when the `var` changes and the `predicate` approves the new value.
990    ///
991    /// Note that the `predicate` does not run in the widget context, it runs on the app context.
992    pub fn sub_var_render_update_when<T: VarValue>(&self, var: &Var<T>, predicate: impl Fn(&T) -> bool + Send + Sync + 'static) -> &Self {
993        self.sub_var_op_when(UpdateOp::RenderUpdate, var, predicate)
994    }
995
996    /// Subscribe to receive events from `event` when the event targets this widget.
997    pub fn sub_event<A: EventArgs>(&self, event: &Event<A>) -> &Self {
998        let w = WIDGET_CTX.get();
999        let s = event.subscribe(w.id);
1000
1001        // function to avoid generics code bloat
1002        fn push(w: Arc<WidgetCtxData>, s: EventHandle) {
1003            if WIDGET_HANDLES_CTX.is_default() {
1004                w.handles.event_handles.lock().push(s);
1005            } else {
1006                WIDGET_HANDLES_CTX.get().event_handles.lock().push(s);
1007            }
1008        }
1009        push(w, s);
1010
1011        self
1012    }
1013
1014    /// Hold the event `handle` until the widget is deinited.
1015    pub fn push_event_handle(&self, handle: EventHandle) {
1016        if WIDGET_HANDLES_CTX.is_default() {
1017            WIDGET_CTX.get().handles.event_handles.lock().push(handle);
1018        } else {
1019            WIDGET_HANDLES_CTX.get().event_handles.lock().push(handle);
1020        }
1021    }
1022
1023    /// Hold the event `handles` until the widget is deinited.
1024    pub fn push_event_handles(&self, handles: EventHandles) {
1025        if WIDGET_HANDLES_CTX.is_default() {
1026            WIDGET_CTX.get().handles.event_handles.lock().extend(handles);
1027        } else {
1028            WIDGET_HANDLES_CTX.get().event_handles.lock().extend(handles);
1029        }
1030    }
1031
1032    /// Hold the var `handle` until the widget is deinited.
1033    pub fn push_var_handle(&self, handle: VarHandle) {
1034        if WIDGET_HANDLES_CTX.is_default() {
1035            WIDGET_CTX.get().handles.var_handles.lock().push(handle);
1036        } else {
1037            WIDGET_HANDLES_CTX.get().var_handles.lock().push(handle);
1038        }
1039    }
1040
1041    /// Hold the var `handles` until the widget is deinited.
1042    pub fn push_var_handles(&self, handles: VarHandles) {
1043        if WIDGET_HANDLES_CTX.is_default() {
1044            WIDGET_CTX.get().handles.var_handles.lock().extend(handles);
1045        } else {
1046            WIDGET_HANDLES_CTX.get().var_handles.lock().extend(handles);
1047        }
1048    }
1049
1050    /// Transform point in the window space to the widget inner bounds.
1051    pub fn win_point_to_wgt(&self, point: DipPoint) -> Option<PxPoint> {
1052        let wgt_info = WIDGET.info();
1053        wgt_info
1054            .inner_transform()
1055            .inverse()?
1056            .transform_point(point.to_px(wgt_info.tree().scale_factor()))
1057    }
1058
1059    /// Gets the transform from the window space to the widget inner bounds.
1060    pub fn win_to_wgt(&self) -> Option<PxTransform> {
1061        WIDGET.info().inner_transform().inverse()
1062    }
1063
1064    /// Calls `f` with an override target for var and event subscription handles.
1065    ///
1066    /// By default when vars and events are subscribed using the methods of this service the
1067    /// subscriptions live until the widget is deinited. This method intersects these
1068    /// subscriptions, registering then in `handles` instead.
1069    pub fn with_handles<R>(&self, handles: &mut WidgetHandlesCtx, f: impl FnOnce() -> R) -> R {
1070        WIDGET_HANDLES_CTX.with_context(&mut handles.0, f)
1071    }
1072
1073    /// Calls `f` while the widget is set to `ctx`.
1074    ///
1075    /// If `update_mode` is [`WidgetUpdateMode::Bubble`] the update flags requested for the `ctx` after `f` will be copied to the
1076    /// caller widget context, otherwise they are ignored.
1077    ///
1078    /// This method can be used to manually define a widget context, note that widgets already define their own context.
1079    #[inline(always)]
1080    pub fn with_context<R>(&self, ctx: &mut WidgetCtx, update_mode: WidgetUpdateMode, f: impl FnOnce() -> R) -> R {
1081        struct Restore<'a> {
1082            update_mode: WidgetUpdateMode,
1083            parent_id: Option<WidgetId>,
1084            prev_flags: UpdateFlags,
1085            ctx: &'a mut WidgetCtx,
1086        }
1087        impl<'a> Restore<'a> {
1088            fn new(ctx: &'a mut WidgetCtx, update_mode: WidgetUpdateMode) -> Self {
1089                let parent_id = WIDGET.try_id();
1090
1091                if let Some(ctx) = ctx.0.as_mut() {
1092                    ctx.parent_id.store(parent_id, Relaxed);
1093                } else {
1094                    unreachable!()
1095                }
1096
1097                let prev_flags = match update_mode {
1098                    WidgetUpdateMode::Ignore => ctx.0.as_mut().unwrap().flags.load(Relaxed),
1099                    WidgetUpdateMode::Bubble => UpdateFlags::empty(),
1100                };
1101
1102                Self {
1103                    update_mode,
1104                    parent_id,
1105                    prev_flags,
1106                    ctx,
1107                }
1108            }
1109        }
1110        impl<'a> Drop for Restore<'a> {
1111            fn drop(&mut self) {
1112                let ctx = match self.ctx.0.as_mut() {
1113                    Some(c) => c,
1114                    None => return, // can happen in case of panic
1115                };
1116
1117                match self.update_mode {
1118                    WidgetUpdateMode::Ignore => {
1119                        ctx.flags.store(self.prev_flags, Relaxed);
1120                    }
1121                    WidgetUpdateMode::Bubble => {
1122                        let wgt_flags = ctx.flags.load(Relaxed);
1123
1124                        if let Some(parent) = self.parent_id.map(|_| WIDGET_CTX.get()) {
1125                            let propagate = wgt_flags
1126                                & (UpdateFlags::UPDATE
1127                                    | UpdateFlags::INFO
1128                                    | UpdateFlags::LAYOUT
1129                                    | UpdateFlags::RENDER
1130                                    | UpdateFlags::RENDER_UPDATE);
1131
1132                            let _ = parent.flags.fetch_update(Relaxed, Relaxed, |mut u| {
1133                                if !u.contains(propagate) {
1134                                    u.insert(propagate);
1135                                    Some(u)
1136                                } else {
1137                                    None
1138                                }
1139                            });
1140                            ctx.parent_id.store(None, Relaxed);
1141                        } else if let Some(window_id) = WINDOW.try_id() {
1142                            // is at root, register `UPDATES`
1143                            UPDATES.update_flags_root(wgt_flags, window_id, ctx.id);
1144                            // some builders don't clear the root widget flags like they do for other widgets.
1145                            ctx.flags.store(wgt_flags & UpdateFlags::REINIT, Relaxed);
1146                        } else {
1147                            // used outside window
1148                            UPDATES.update_flags(wgt_flags, ctx.id);
1149                            ctx.flags.store(UpdateFlags::empty(), Relaxed);
1150                        }
1151                    }
1152                }
1153            }
1154        }
1155
1156        let mut _restore = Restore::new(ctx, update_mode);
1157        WIDGET_CTX.with_context(&mut _restore.ctx.0, f)
1158    }
1159    /// Calls `f` while no widget is available in the context.
1160    #[inline(always)]
1161    pub fn with_no_context<R>(&self, f: impl FnOnce() -> R) -> R {
1162        WIDGET_CTX.with_default(f)
1163    }
1164
1165    #[cfg(any(test, doc, feature = "test_util"))]
1166    pub(crate) fn test_root_updates(&self) {
1167        let ctx = WIDGET_CTX.get();
1168        // is at root, register `UPDATES`
1169        UPDATES.update_flags_root(ctx.flags.load(Relaxed), WINDOW.id(), ctx.id);
1170        // some builders don't clear the root widget flags like they do for other widgets.
1171        ctx.flags.store(UpdateFlags::empty(), Relaxed);
1172    }
1173
1174    pub(crate) fn layout_is_pending(&self, layout_widgets: &LayoutUpdates) -> bool {
1175        let ctx = WIDGET_CTX.get();
1176        ctx.flags.load(Relaxed).contains(UpdateFlags::LAYOUT) || layout_widgets.delivery_list().enter_widget(ctx.id)
1177    }
1178
1179    /// Remove update flag and returns if it intersected.
1180    pub(crate) fn take_update(&self, flag: UpdateFlags) -> bool {
1181        let mut r = false;
1182        let _ = WIDGET_CTX.get().flags.fetch_update(Relaxed, Relaxed, |mut f| {
1183            if f.intersects(flag) {
1184                r = true;
1185                f.remove(flag);
1186                Some(f)
1187            } else {
1188                None
1189            }
1190        });
1191        r
1192    }
1193
1194    /// Current pending updates.
1195    #[cfg(debug_assertions)]
1196    pub(crate) fn pending_update(&self) -> UpdateFlags {
1197        WIDGET_CTX.get().flags.load(Relaxed)
1198    }
1199
1200    /// Remove the render reuse range if render was not invalidated on this widget.
1201    pub(crate) fn take_render_reuse(&self, render_widgets: &RenderUpdates, render_update_widgets: &RenderUpdates) -> Option<ReuseRange> {
1202        let ctx = WIDGET_CTX.get();
1203        let mut try_reuse = true;
1204
1205        // take RENDER, RENDER_UPDATE
1206        let _ = ctx.flags.fetch_update(Relaxed, Relaxed, |mut f| {
1207            if f.intersects(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE) {
1208                try_reuse = false;
1209                f.remove(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE);
1210                Some(f)
1211            } else {
1212                None
1213            }
1214        });
1215
1216        if try_reuse && !render_widgets.delivery_list().enter_widget(ctx.id) && !render_update_widgets.delivery_list().enter_widget(ctx.id)
1217        {
1218            ctx.render_reuse.lock().take()
1219        } else {
1220            None
1221        }
1222    }
1223
1224    pub(crate) fn set_render_reuse(&self, range: Option<ReuseRange>) {
1225        *WIDGET_CTX.get().render_reuse.lock() = range;
1226    }
1227}
1228
1229context_local! {
1230    pub(crate) static WIDGET_CTX: WidgetCtxData = WidgetCtxData::no_context();
1231    static WIDGET_HANDLES_CTX: WidgetHandlesCtxData = WidgetHandlesCtxData::dummy();
1232}
1233
1234/// Defines the backing data of [`WIDGET`].
1235///
1236/// Each widget owns this data and calls [`WIDGET.with_context`] to delegate to it's child node.
1237///
1238/// [`WIDGET.with_context`]: WIDGET::with_context
1239pub struct WidgetCtx(Option<Arc<WidgetCtxData>>);
1240impl WidgetCtx {
1241    /// New widget context.
1242    pub fn new(id: WidgetId) -> Self {
1243        Self(Some(Arc::new(WidgetCtxData {
1244            parent_id: Atomic::new(None),
1245            id,
1246            flags: Atomic::new(UpdateFlags::empty()),
1247            state: RwLock::new(OwnedStateMap::default()),
1248            handles: WidgetHandlesCtxData::dummy(),
1249            bounds: Mutex::new(WidgetBoundsInfo::default()),
1250            border: Mutex::new(WidgetBorderInfo::default()),
1251            render_reuse: Mutex::new(None),
1252        })))
1253    }
1254
1255    /// Drops all var and event handles, clears all state.
1256    ///
1257    /// If `retain_state` is enabled the state will not be cleared and can still read.
1258    pub fn deinit(&mut self, retain_state: bool) {
1259        let ctx = self.0.as_mut().unwrap();
1260        ctx.handles.var_handles.lock().clear();
1261        ctx.handles.event_handles.lock().clear();
1262        ctx.flags.store(UpdateFlags::empty(), Relaxed);
1263        *ctx.render_reuse.lock() = None;
1264
1265        if !retain_state {
1266            ctx.state.write().clear();
1267        }
1268    }
1269
1270    /// Returns `true` if reinit was requested for the widget.
1271    ///
1272    /// Note that widget implementers must use [`take_reinit`] to fulfill the request.
1273    ///
1274    /// [`take_reinit`]: Self::take_reinit
1275    pub fn is_pending_reinit(&self) -> bool {
1276        self.0.as_ref().unwrap().flags.load(Relaxed).contains(UpdateFlags::REINIT)
1277    }
1278
1279    /// Returns `true` if an [`WIDGET.reinit`] request was made.
1280    ///
1281    /// Unlike other requests, the widget implement must re-init immediately.
1282    ///
1283    /// [`WIDGET.reinit`]: WIDGET::reinit
1284    pub fn take_reinit(&mut self) -> bool {
1285        let ctx = self.0.as_mut().unwrap();
1286
1287        let mut flags = ctx.flags.load(Relaxed);
1288        let r = flags.contains(UpdateFlags::REINIT);
1289        if r {
1290            flags.remove(UpdateFlags::REINIT);
1291            ctx.flags.store(flags, Relaxed);
1292        }
1293
1294        r
1295    }
1296
1297    /// Gets the widget id.
1298    pub fn id(&self) -> WidgetId {
1299        self.0.as_ref().unwrap().id
1300    }
1301    /// Gets the widget bounds.
1302    pub fn bounds(&self) -> WidgetBoundsInfo {
1303        self.0.as_ref().unwrap().bounds.lock().clone()
1304    }
1305
1306    /// Gets the widget borders.
1307    pub fn border(&self) -> WidgetBorderInfo {
1308        self.0.as_ref().unwrap().border.lock().clone()
1309    }
1310
1311    /// Call `f` with an exclusive lock to the widget state.
1312    pub fn with_state<R>(&mut self, f: impl FnOnce(&mut OwnedStateMap<WIDGET>) -> R) -> R {
1313        f(&mut self.0.as_mut().unwrap().state.write())
1314    }
1315
1316    /// Clone a reference to the widget context.
1317    ///
1318    /// This must be used only if the widget implementation is split.
1319    pub fn share(&mut self) -> Self {
1320        Self(self.0.clone())
1321    }
1322}
1323
1324pub(crate) struct WidgetCtxData {
1325    parent_id: Atomic<Option<WidgetId>>,
1326    pub(crate) id: WidgetId,
1327    flags: Atomic<UpdateFlags>,
1328    state: RwLock<OwnedStateMap<WIDGET>>,
1329    handles: WidgetHandlesCtxData,
1330    pub(crate) bounds: Mutex<WidgetBoundsInfo>,
1331    border: Mutex<WidgetBorderInfo>,
1332    render_reuse: Mutex<Option<ReuseRange>>,
1333}
1334impl WidgetCtxData {
1335    #[track_caller]
1336    fn no_context() -> Self {
1337        panic!("no widget in context")
1338    }
1339}
1340
1341struct WidgetHandlesCtxData {
1342    var_handles: Mutex<VarHandles>,
1343    event_handles: Mutex<EventHandles>,
1344}
1345
1346impl WidgetHandlesCtxData {
1347    const fn dummy() -> Self {
1348        Self {
1349            var_handles: Mutex::new(VarHandles::dummy()),
1350            event_handles: Mutex::new(EventHandles::dummy()),
1351        }
1352    }
1353}
1354
1355/// Defines the backing data for [`WIDGET.with_handles`].
1356///
1357/// [`WIDGET.with_handles`]: WIDGET::with_handles
1358pub struct WidgetHandlesCtx(Option<Arc<WidgetHandlesCtxData>>);
1359impl WidgetHandlesCtx {
1360    /// New empty.
1361    pub fn new() -> Self {
1362        Self(Some(Arc::new(WidgetHandlesCtxData::dummy())))
1363    }
1364
1365    /// Drop all handles.
1366    pub fn clear(&mut self) {
1367        let h = self.0.as_ref().unwrap();
1368        h.var_handles.lock().clear();
1369        h.event_handles.lock().clear();
1370    }
1371}
1372impl Default for WidgetHandlesCtx {
1373    fn default() -> Self {
1374        Self::new()
1375    }
1376}
1377
1378/// Extension method to subscribe any widget to a variable.
1379///
1380/// Also see [`WIDGET`] methods for the primary way to subscribe from inside a widget.
1381pub trait AnyVarSubscribe {
1382    /// Register the widget to receive an [`UpdateOp`] when this variable is new.
1383    ///
1384    /// Variables without the [`NEW`] capability return [`VarHandle::dummy`].
1385    ///
1386    /// [`NEW`]: zng_var::VarCapability::NEW
1387    /// [`VarHandle::dummy`]: zng_var::VarHandle
1388    fn subscribe(&self, op: UpdateOp, widget_id: WidgetId) -> VarHandle;
1389}
1390impl AnyVarSubscribe for AnyVar {
1391    fn subscribe(&self, op: UpdateOp, widget_id: WidgetId) -> VarHandle {
1392        if !self.capabilities().is_const() {
1393            self.hook(move |_| {
1394                UPDATES.update_op(op, widget_id);
1395                true
1396            })
1397        } else {
1398            VarHandle::dummy()
1399        }
1400    }
1401}
1402
1403/// Extension methods to subscribe any widget to a variable or app handlers to a variable.
1404///
1405/// Also see [`WIDGET`] methods for the primary way to subscribe from inside a widget.
1406pub trait VarSubscribe<T: VarValue>: AnyVarSubscribe {
1407    /// Register the widget to receive an [`UpdateOp`] when this variable is new and the `predicate` approves the new value.
1408    ///
1409    /// Variables without the [`NEW`] capability return [`VarHandle::dummy`].
1410    ///
1411    /// [`NEW`]: zng_var::VarCapability::NEW
1412    /// [`VarHandle::dummy`]: zng_var::VarHandle
1413    fn subscribe_when(&self, op: UpdateOp, widget_id: WidgetId, predicate: impl Fn(&T) -> bool + Send + Sync + 'static) -> VarHandle;
1414
1415    /// Add a preview `handler` that is called every time this variable updates,
1416    /// the handler is called before UI update.
1417    ///
1418    /// Note that the handler runs on the app context, all [`ContextVar<T>`] used inside will have the default value.
1419    ///
1420    /// [`ContextVar<T>`]: zng_var::ContextVar
1421    fn on_pre_new<H>(&self, handler: H) -> VarHandle
1422    where
1423        H: AppHandler<OnVarArgs<T>>;
1424
1425    /// Add a `handler` that is called every time this variable updates,
1426    /// the handler is called after UI update.
1427    ///
1428    /// Note that the handler runs on the app context, all [`ContextVar<T>`] used inside will have the default value.
1429    ///
1430    /// [`ContextVar<T>`]: zng_var::ContextVar
1431    fn on_new<H>(&self, handler: H) -> VarHandle
1432    where
1433        H: AppHandler<OnVarArgs<T>>;
1434}
1435impl<T: VarValue> AnyVarSubscribe for Var<T> {
1436    fn subscribe(&self, op: UpdateOp, widget_id: WidgetId) -> VarHandle {
1437        self.as_any().subscribe(op, widget_id)
1438    }
1439}
1440impl<T: VarValue> VarSubscribe<T> for Var<T> {
1441    fn subscribe_when(&self, op: UpdateOp, widget_id: WidgetId, predicate: impl Fn(&T) -> bool + Send + Sync + 'static) -> VarHandle {
1442        self.hook(move |a| {
1443            if let Some(a) = a.downcast_value::<T>() {
1444                if predicate(a) {
1445                    UPDATES.update_op(op, widget_id);
1446                }
1447                true
1448            } else {
1449                false
1450            }
1451        })
1452    }
1453
1454    fn on_pre_new<H>(&self, handler: H) -> VarHandle
1455    where
1456        H: AppHandler<OnVarArgs<T>>,
1457    {
1458        var_on_new(self, handler, true)
1459    }
1460
1461    fn on_new<H>(&self, handler: H) -> VarHandle
1462    where
1463        H: AppHandler<OnVarArgs<T>>,
1464    {
1465        var_on_new(self, handler, false)
1466    }
1467}
1468
1469/// Extension methods to subscribe app handlers to a response variable.
1470pub trait ResponseVarSubscribe<T: VarValue> {
1471    /// Add a `handler` that is called once when the response is received,
1472    /// the handler is called before all other UI updates.
1473    ///
1474    /// The handle is not called if already [`is_done`], in this case a dummy handle is returned.
1475    ///
1476    /// [`is_done`]: ResponseVar::is_done
1477    fn on_pre_rsp<H>(&self, handler: H) -> VarHandle
1478    where
1479        H: AppHandler<OnVarArgs<T>>;
1480
1481    /// Add a `handler` that is called once when the response is received,
1482    /// the handler is called after all other UI updates.
1483    ///
1484    /// The handle is not called if already [`is_done`], in this case a dummy handle is returned.
1485    ///
1486    /// [`is_done`]: ResponseVar::is_done
1487    fn on_rsp<H>(&self, handler: H) -> VarHandle
1488    where
1489        H: AppHandler<OnVarArgs<T>>;
1490}
1491impl<T: VarValue> ResponseVarSubscribe<T> for ResponseVar<T> {
1492    fn on_pre_rsp<H>(&self, mut handler: H) -> VarHandle
1493    where
1494        H: AppHandler<OnVarArgs<T>>,
1495    {
1496        if self.is_done() {
1497            return VarHandle::dummy();
1498        }
1499
1500        self.on_pre_new(app_hn!(|args: &OnVarArgs<zng_var::Response<T>>, handler_args| {
1501            if let zng_var::Response::Done(value) = &args.value {
1502                handler.event(
1503                    &OnVarArgs::new(value.clone(), args.tags.iter().map(|t| (*t).clone_boxed()).collect()),
1504                    &crate::handler::AppHandlerArgs {
1505                        handle: handler_args,
1506                        is_preview: true,
1507                    },
1508                )
1509            }
1510        }))
1511    }
1512
1513    fn on_rsp<H>(&self, mut handler: H) -> VarHandle
1514    where
1515        H: AppHandler<OnVarArgs<T>>,
1516    {
1517        if self.is_done() {
1518            return VarHandle::dummy();
1519        }
1520
1521        self.on_new(app_hn!(|args: &OnVarArgs<zng_var::Response<T>>, handler_args| {
1522            if let zng_var::Response::Done(value) = &args.value {
1523                handler.event(
1524                    &OnVarArgs::new(value.clone(), args.tags.iter().map(|t| (*t).clone_boxed()).collect()),
1525                    &crate::handler::AppHandlerArgs {
1526                        handle: handler_args,
1527                        is_preview: false,
1528                    },
1529                )
1530            }
1531        }))
1532    }
1533}
1534
1535fn var_on_new<T>(var: &Var<T>, handler: impl AppHandler<OnVarArgs<T>>, is_preview: bool) -> VarHandle
1536where
1537    T: VarValue,
1538{
1539    if var.capabilities().is_const() {
1540        return VarHandle::dummy();
1541    }
1542
1543    let handler = Arc::new(Mutex::new(handler));
1544    let (inner_handle_owner, inner_handle) = Handle::new(());
1545    var.hook(move |args| {
1546        if inner_handle_owner.is_dropped() {
1547            return false;
1548        }
1549
1550        let handle = inner_handle.downgrade();
1551        let value = args.value().clone();
1552        let tags = args.tags().iter().map(|t| (*t).clone_boxed()).collect();
1553        let update_once = app_hn_once!(handler, value, |_| {
1554            handler.lock().event(
1555                &OnVarArgs::new(value, tags),
1556                &AppHandlerArgs {
1557                    handle: &handle,
1558                    is_preview,
1559                },
1560            );
1561        });
1562
1563        if is_preview {
1564            UPDATES.on_pre_update(update_once).perm();
1565        } else {
1566            UPDATES.on_update(update_once).perm();
1567        }
1568        true
1569    })
1570}
1571
1572/// Arguments for a var event handler.
1573#[non_exhaustive]
1574pub struct OnVarArgs<T: VarValue> {
1575    /// The new value.
1576    pub value: T,
1577    /// Custom tag objects that where set when the value was modified.
1578    pub tags: Vec<BoxAnyVarValue>,
1579}
1580impl<T: VarValue> OnVarArgs<T> {
1581    /// New from value and custom modify tags.
1582    pub fn new(value: T, tags: Vec<BoxAnyVarValue>) -> Self {
1583        Self { value, tags }
1584    }
1585
1586    /// Reference all custom tag values of type `T`.
1587    pub fn downcast_tags<Ta: VarValue>(&self) -> impl Iterator<Item = &Ta> + '_ {
1588        self.tags.iter().filter_map(|t| (*t).downcast_ref::<Ta>())
1589    }
1590}
1591impl<T: VarValue> Clone for OnVarArgs<T> {
1592    fn clone(&self) -> Self {
1593        Self {
1594            value: self.value.clone(),
1595            tags: self.tags.iter().map(|t| (*t).clone_boxed()).collect(),
1596        }
1597    }
1598}
1599
1600/// Extension methods to layout var values.
1601pub trait VarLayout<T: VarValue> {
1602    /// Compute the pixel value in the current [`LAYOUT`] context.
1603    ///
1604    /// [`LAYOUT`]: zng_layout::context::LAYOUT
1605    fn layout(&self) -> T::Px
1606    where
1607        T: Layout2d;
1608
1609    /// Compute the pixel value in the current [`LAYOUT`] context with `default`.
1610    ///
1611    /// [`LAYOUT`]: zng_layout::context::LAYOUT
1612    fn layout_dft(&self, default: T::Px) -> T::Px
1613    where
1614        T: Layout2d;
1615
1616    /// Compute the pixel value in the current [`LAYOUT`] context ***x*** axis.
1617    ///
1618    /// [`LAYOUT`]: zng_layout::context::LAYOUT
1619    fn layout_x(&self) -> Px
1620    where
1621        T: Layout1d;
1622
1623    /// Compute the pixel value in the current [`LAYOUT`] context ***y*** axis.
1624    ///
1625    /// [`LAYOUT`]: zng_layout::context::LAYOUT
1626    fn layout_y(&self) -> Px
1627    where
1628        T: Layout1d;
1629
1630    /// Compute the pixel value in the current [`LAYOUT`] context ***z*** axis.
1631    ///
1632    /// [`LAYOUT`]: zng_layout::context::LAYOUT
1633    fn layout_z(&self) -> Px
1634    where
1635        T: Layout1d;
1636
1637    /// Compute the pixel value in the current [`LAYOUT`] context ***x*** axis with `default`.
1638    ///
1639    /// [`LAYOUT`]: zng_layout::context::LAYOUT
1640    fn layout_dft_x(&self, default: Px) -> Px
1641    where
1642        T: Layout1d;
1643
1644    /// Compute the pixel value in the current [`LAYOUT`] context ***y*** axis with `default`.
1645    ///
1646    /// [`LAYOUT`]: zng_layout::context::LAYOUT
1647    fn layout_dft_y(&self, default: Px) -> Px
1648    where
1649        T: Layout1d;
1650
1651    /// Compute the pixel value in the current [`LAYOUT`] context ***z*** axis with `default`.
1652    ///
1653    /// [`LAYOUT`]: zng_layout::context::LAYOUT
1654    fn layout_dft_z(&self, default: Px) -> Px
1655    where
1656        T: Layout1d;
1657}
1658impl<T: VarValue> VarLayout<T> for Var<T> {
1659    fn layout(&self) -> <T>::Px
1660    where
1661        T: Layout2d,
1662    {
1663        self.with(|s| s.layout())
1664    }
1665
1666    fn layout_dft(&self, default: <T>::Px) -> <T>::Px
1667    where
1668        T: Layout2d,
1669    {
1670        self.with(move |s| s.layout_dft(default))
1671    }
1672
1673    fn layout_x(&self) -> Px
1674    where
1675        T: Layout1d,
1676    {
1677        self.with(|s| s.layout_x())
1678    }
1679
1680    fn layout_y(&self) -> Px
1681    where
1682        T: Layout1d,
1683    {
1684        self.with(|s| s.layout_y())
1685    }
1686
1687    fn layout_z(&self) -> Px
1688    where
1689        T: Layout1d,
1690    {
1691        self.with(|s| s.layout_z())
1692    }
1693
1694    fn layout_dft_x(&self, default: Px) -> Px
1695    where
1696        T: Layout1d,
1697    {
1698        self.with(move |s| s.layout_dft_x(default))
1699    }
1700
1701    fn layout_dft_y(&self, default: Px) -> Px
1702    where
1703        T: Layout1d,
1704    {
1705        self.with(move |s| s.layout_dft_y(default))
1706    }
1707
1708    fn layout_dft_z(&self, default: Px) -> Px
1709    where
1710        T: Layout1d,
1711    {
1712        self.with(move |s| s.layout_dft_z(default))
1713    }
1714}
1715
1716/// Integrate [`UiTask`] with widget updates.
1717pub trait UiTaskWidget<R> {
1718    /// Create a UI bound future executor.
1719    ///
1720    /// The `task` is inert and must be polled using [`update`] to start, and it must be polled every
1721    /// [`UiNode::update`] after that, in widgets the `target` can be set so that the update requests are received.
1722    ///
1723    /// [`update`]: UiTask::update
1724    /// [`UiNode::update`]: crate::widget::node::UiNode::update
1725    /// [`UiNode::info`]: crate::widget::node::UiNode::info
1726    fn new<F>(target: Option<WidgetId>, task: impl IntoFuture<IntoFuture = F>) -> Self
1727    where
1728        F: Future<Output = R> + Send + 'static;
1729}
1730impl<R> UiTaskWidget<R> for UiTask<R> {
1731    fn new<F>(target: Option<WidgetId>, task: impl IntoFuture<IntoFuture = F>) -> Self
1732    where
1733        F: Future<Output = R> + Send + 'static,
1734    {
1735        UiTask::new_raw(UPDATES.waker(target), task)
1736    }
1737}