#[property]Expand description
Expands a function to a widget property.
Property functions take one IntoUiNode child input and one or more other inputs and produces an UiNode that implements
the property feature. Alternatively it takes one WidgetBuilding input plus other inputs and modifies the widget build.
The attribute expansion does not modify the function, it can still be used as a function directly. Some properties are implemented by calling other property functions to generate a derived effect.
The attribute expansion generates a hidden trait of the same name and visibility, the trait is implemented for widget builders,
the widget macros use this to set the property. Because it has the same name it is imported together with the property
function, in practice this only matters in doc links where you must use the fn@ disambiguator.
§Attribute Args
The property attribute has one required argument and three optional.
§Nest Group
The first argument is the property NestGroup. The group defines the overall nest position
of the property, for example, LAYOUT properties always wrap FILL properties. This is important as widgets are open and any combination
of properties may end-up instantiated in the same widget.
use zng::prelude_wgt::*;
#[property(LAYOUT)]
pub fn align(child: impl IntoUiNode, align: impl IntoVar<Align>) -> UiNode {
// ..
}The nest group can be tweaked, by adding or subtracting integers, in the example bellow both properties are in the SIZE group,
but size is always inside max_size.
use zng::prelude_wgt::*;
#[property(SIZE+1)]
pub fn size(child: impl IntoUiNode, size: impl IntoVar<Size>) -> UiNode {
// ..
}
#[property(SIZE)]
pub fn max_size(child: impl IntoUiNode, size: impl IntoVar<Size>) -> UiNode {
// ..
}§Default
The next argument is an optional default(args..). It defines the value to use when the property must be instantiated and no value was provided.
The defaults should cause the property to behave as if it is not set, as the default value will be used in widgets that only set the
property in when blocks.
use zng::prelude_wgt::*;
#[property(FILL, default(rgba(0, 0, 0, 0)))]
pub fn background_color(child: impl IntoUiNode, color: impl IntoVar<Rgba>) -> UiNode {
// ..
}In the example above the background_color defines a transparent color as the default, so if the background color is only set in a when
block if will only be visible when it is active.
For properties with multiple inputs the default args may be defined in a comma separated list of params, default(dft0, ..).
§Impl For
The last argument is an optional impl(<widget-type>,...), it strongly associates the property with one or more widgets.
When a property is implemented on a widget users can set it without needing to import the property.
Note that this makes the property have priority over all others of the same name, only a derived widget can override with another strongly associated property.
Note that you can also use the widget_impl! in widget declarations to implement existing properties for a widget.
§Function Args
The property function requires at least two args, the first is the child node and the other(s) the input values. The number and type of inputs is validated at compile time, the types are limited and are identified and validated by their token name, so you cannot use renamed types.
§Child
The first function arg must be of type impl IntoUiNode, it represents the child node and the property node must
delegate to it so that the UI tree functions correctly. The type must be an impl generic, a full path to IntoUiNode
is allowed, but no import renames as the proc-macro attribute can only use tokens to identify the type.
§Or Building
Alternatively, the first function arg must be of type &mut WidgetBuilding, in this case the property function runs
during widget build and can do things like insert multiple nodes on the widget or set the widget child node.
§Inputs
The second arg and optional other args define the property inputs. When a property is assigned in a widget only these inputs
are defined by the user, the child arg is provided by the widget builder. Property inputs are limited, and must be identifiable
by their token name alone. The types are validated at compile time, they must be declared using impl generics,
a full path to the generic traits is allowed, but no import renames.
§Input Types
These are the allowed input types:
§impl IntoVar<T>
The most common type, accepts any value that can be converted IntoVar<T>, usually the property defines the T, but it can be generic.
The property node must respond to var updates. The input kind is InputKind::Var. No auto-default is generated for this type, property
implementation should provide a default value that causes the property to behave as if it was not set.
The input can be read in when expressions and can be assigned in when blocks.
§impl IntoValue<T>
Accepts any value that can be converted IntoValue<T> that does not change, usually the property
defines the T, but it can be generic. The input kind is InputKind::Value. No auto-default is generated for this type.
The input can be read in when expressions, but cannot be assigned in when blocks.
§impl IntoUiNode
This input accepts another UiNode, the implementation must handle it like it handles the child node, delegating all methods. The
input kind is InputKind::UiNode. The UiNode::nil is used as the default value if no other is provided.
The input cannot be read in when expressions, but can be assigned in when blocks.
Note that UI lists like ui_vec! are also nodes, so panel children properties also receive impl IntoUiNode.
§Handler<A>
This input is the type alias Handler<A>, generic for the argument type A, usually the property defines the A, but it can be generic.
The input kind is InputKind::Handler. A no-op handler is used for the default if no other is provided.
Event handler properties usually have the on_ name prefix. You can use the event_property! macro to generate standard event properties.
The input cannot be read in when expressions, but can be assigned in when blocks.
§Getter Properties
Most properties with var inputs are setters, that is the inputs affect the widget. Some properties
can be getters, detecting widget state and setting it on the input variable. These properties are usually named with
a prefix that indicates their input is actually for getting state, the prefixes is_ and has_ mark a property with
a single bool input that reads a widget state, the prefix get_ and actual_ marks a property that reads a non-boolean state from
the widget.
Getter properties are configured with a default read-write variable, so that they can be used in when expressions directly,
for example, when *#is_pressed, the is_pressed property has a default(var(false)), so it automatically initializes
with a read-write variable that is used in the when condition. The property attribute generates defaults automatically
based on the prefix, the default is var(T::default()), this can be overwritten just by setting the default,
it is not possible to declare a getter property without default.
Note that if a property is used in when condition without being set and without default value the when block is discarded on
widget build. If you are implementing a getter property that is not named using the prefixes listed above you must set default(var(T::default()).
§Generics
Apart from the impl generics of inputs and child, there is some support for named generic types, only one named generic is allowed
for inputs impl IntoVar<T>, impl IntoValue<T> and Handler<A>.
§Output
The property output type must be UiNode. The property node implementation can be anything, as long as it delegates
to the child node, see match_node or ui_node about implementing a node.
Some common property patterns have helper functions, for example, to setup a context var you can use the with_context_var function.
§Build Action Properties
Property functions can take a &mut WidgetBuilding first arg, in this case they are build action properties. These properties cannot
be instantiated into a node, they only work if set on an widget. The property function is called during widget build, after property resolution
and widget intrinsic build actions, the function can modify the WidgetBuilding, just like an intrinsic build action.
use zng::prelude_wgt::*;
#[property(CHILD)]
pub fn child(wgt: &mut WidgetBuilding, child: impl IntoUiNode) {
wgt.set_child(child);
}The example above declares a simple property that replaces the widget child.
§Capture Only
Some widgets intrinsic behavior depend on the value of multiple properties that cannot provide any implementation by themselves. In
this case the property should be declared as a build action property and call expect_property_capture.
The widget them must capture the property during build, if it does not an error is logged in build with debug assertions enabled.
use zng::prelude_wgt::*;
#[property(CHILD, widget_impl(MyPanel))]
pub fn children(wgt: &mut WidgetBuilding, children: impl IntoUiNode) {
let _ = children;
wgt.expect_property_capture();
}The example above declares a property that expects to be captured, if the property function actually runs it will log an error in builds with debug assertions enabled.
§More Details
See property_id! and property_args! for more details about what kind of meta-code is generated for properties.
Expands a function to a widget property.
§Full Documentation
Read the documentation in the zng::widget::property page.