#[widget]
Expand description
Expands a struct to a widget struct and macro.
Each widget is a struct and macro pair of the same name that builds a custom widget using WidgetBuilder
. Widgets
inherit from one other widget and can also inherit multiple mix-ins. Widgets can have intrinsic nodes, default properties
and can build to a custom output type.
Properties can be strongly associated with the widget using the #[property(.., widget_impl(Widget))]
directive, existing properties
can be implemented for the widget using the widget_impl!
macro.
§Attribute
The widget attribute must be placed in a struct Name(Parent);
declaration, only struct following the exact pattern are allowed,
different struct syntaxes will generate a compile error.
The attribute requires one argument, it must be a macro style $crate
path to the widget struct, this is used in the generated macro
to find the struct during instantiation. The path must be to the public path to the struct, that is, the same path that will be used
to import the widget. After the required widget path custom rules for the generated macro can be declared.
use zng::prelude_wgt::*;
/// Minimal widget.
#[widget($crate::Foo)]
pub struct Foo(WidgetBase);
§Inherit
The widget struct field must be the parent widget type. All widgets inherit from another or the
WidgetBase
, the parent widgets intrinsic properties and nodes are all included in the new widget. The intrinsic
properties are included by deref, the new widget will dereference to the parent widget, during widget build auto-deref will select
the property methods first, this mechanism even allows for property overrides.
§Intrinsic
The widget struct can define a method widget_intrinsic
that includes custom build actions in the WidgetBuilder
, this special
method will be called once for the widget. The same method is also called for the inherited widgets.
use zng::prelude_wgt::*;
#[widget($crate::Foo)]
pub struct Foo(WidgetBase);
impl Foo {
fn widget_intrinsic(&mut self) {
self.widget_builder().push_build_action(|b| {
// push_intrinsic, capture_var.
});
}
}
The example above demonstrates the intrinsic method used to push_build_action
. This is the primary mechanism for widgets to define their
own behavior that does not depend on properties. Note that the widget inherits from WidgetBase
, during instantiation
of Foo!
the base widget_intrinsic
is called first, then the Foo!
widget_intrinsic
is called.
The method does not need to be pub
, and it is not required.
§Build
The widget struct can define a method that builds the final widget instance.
use zng::prelude_wgt::*;
#[widget($crate::Foo)]
pub struct Foo(WidgetBase);
impl Foo {
/// Custom build.
pub fn widget_build(&mut self) -> impl UiNode {
println!("on build!");
WidgetBase::widget_build(self)
}
}
The build method must have the same visibility as the widget, and can define its own return type, this is the widget instance type. If the build method is not defined the inherited parent build method is used.
Unlike the intrinsic method, the widget only has one widget_build
, if defined it overrides the parent
widget_build
. Most widgets don’t define their own build, leaving it to be inherited from WidgetBase
. The base instance type
is an opaque impl UiNode
.
Normal widgets must implement UiNode
, otherwise they cannot be used as child of other widgets.
The widget outer-node also must implement the widget context, to ensure that the widget is correctly placed in the UI tree.
Note that you can still use the parent type build implementation, so even if you need
to run code on build or define a custom type you don’t need to deref to the parent type to build.
§Defaults
The widget_set!
macro can be used inside widget_intrinsic
to set properties and when conditions that are applied on the widget by default,
if not overridden by derived widgets or the widget instance. During the call to widget_intrinsic
the self.importance()
value is
Importance::WIDGET
, after it is changed to Importance::INSTANCE
, so just by setting properties in widget_intrinsic
they
will have less importance allowing for the override mechanism to replace them.
§Impl Properties
The widget_impl!
macro can be used inside a impl WgtIdent { }
block to strongly associate a property with the widget,
and the property
attribute has a widget_impl(WgtIdent)
directive that also strongly associates a property with the widget.
These two mechanisms can be used to define properties for the widget, the impl properties don’t need to be imported and are always selected over other properties of the same name. They also appear in the widget documentation and can have a distinct visual in IDEs as they are represented by immutable methods while standalone properties are represented by mutable trait methods.
As a general rule only properties that are captured by the widget, or only work with the widget, or have an special meaning in the widget are implemented like this, standalone properties that can be used in any widget are not implemented.
§Generated Macro
The generated widget macro has the same syntax as widget_set!
, except that is also starts the widget and builds it at the end.
This widget macro call:
let wgt = Foo! {
id = "foo";
};
Expands to this:
let wgt = {
let mut wgt = Foo::widget_new();
widget_set! {
&mut wgt;
id = "foo";
}
wgt.widget_build()
};
§Custom Rules
You can declare custom rules for the widget macro, this can be used to declare custom shorthand syntax for the widget.
The custom rules are declared inside braces after the widget path in the widget attribute. The syntax is similar to macro_rules!
rules, but the expanded tokens are the direct input of the normal widget expansion.
(<rule>) => { <init> };
The <rule>
is any macro pattern rule, the <init>
is the normal widget init code that the rule expands to.
Note that custom rules are not inherited, they apply only to the declaring widget macro, inherited widgets must replicate the rules if desired.
Example of a widget that declares a shorthand syntax to implicitly set the id
property:
use zng::prelude_wgt::*;
#[widget($crate::Foo {
($id:expr) => {
id = $id;
};
})]
pub struct Foo(WidgetBase);
let wgt = Foo!("foo");
The macro instance above is equivalent to:
let wgt = Foo! {
id = "foo";
};
§Limitations
The expanded tokens can only be a recursive input for the same widget macro, you can’t expand to a different widget.
Some rules are intercepted by the default widget rules:
$(#[$attr:meta])* $($property:ident)::+ = $($rest:tt)*
, blocks all custom$ident = $tt*
patterns.$(#[$attr:meta])* when $($rest:tt)*
, blocks all customwhen $tt*
patterns.
Note that the default single property shorthand syntax is not blocked, for example Text!(font_size)
will match
the custom shorthand rule and try to set the txt
with the font_size
variable, without the shorthand it would create a widget without
txt
that sets font_size
. So a custom rule $p:expr
is only recommended for widgets that have a property of central importance.
§Widget Type
A public associated function widget_type
is also generated for the widget, it returns a WidgetType
instance that describes the
widget type. Note that this is not the widget instance type, only the struct and macro type. If compiled with the "inspector"
feature
the type is also available in the widget info.
§See Also
See the WidgetBase
, WidgetBuilder
, WidgetBuilding
, NestGroup
and Importance
for more details.
Expands a struct to a widget and macro.
§Full Documentation
Read the documentation in the zng::widget::widget
page.