AbstractBinding is the base class for binding classes. More...
#include <kanzi/core.ui/binding/abstract_binding.hpp>
Public Types | |
using | BindingProcessorConstIterator = BindingProcessorContainer::const_iterator |
Binding processor iterator type. More... | |
using | BindingProcessorContainer = vector< BindingProcessorSharedPtr > |
Binding processor container type. More... | |
Public Member Functions | |
void | addProcessor (BindingProcessorSharedPtr processor) |
Add a binding processor. More... | |
void | addReverseProcessor (BindingProcessorSharedPtr processor) |
Add a binding processor (reverse direction). More... | |
BindingProcessorConstIterator | beginProcessors () const |
Gets an iterator to the beginning of binding processors. More... | |
BindingProcessorConstIterator | beginReverseProcessors () const |
Gets an iterator to the beginning of reverse direction binding processors. More... | |
AbstractBindingRuntimeSharedPtr | createRuntime (AbstractBindingSharedPtr binding, BindingLookupContextPtr sourceLookupContext, BindingTargetRuntimePtr targetRuntime) |
Creates a binding runtime for this binding. More... | |
BindingProcessorConstIterator | endProcessors () const |
Gets an iterator to the end of binding processors. More... | |
BindingProcessorConstIterator | endReverseProcessors () const |
Gets an iterator to the end of reverse direction binding processors. More... | |
BindingSource * | getSource () |
Gets the binding source for this binding. More... | |
bool | isCreatedFromKZB () const |
Indicates whether the binding is sourced from a KZB? Used to check whether or not to remove the binding during patching. More... | |
void | removeProcessor (BindingProcessor &processor) |
Remove a binding processor. More... | |
void | removeReverseProcessor (BindingProcessor &processor) |
Remove a binding processor (reverse direction). More... | |
void | setCreatedFromKZB (bool flag) |
Sets the created from KZB flag. More... | |
virtual | ~AbstractBinding ()=default |
Destructor. More... | |
Protected Member Functions | |
AbstractBinding (BindingSourcePtr source) | |
Constructor. More... | |
virtual void | addReverseProcessorOverride (BindingProcessorSharedPtr processor) |
Implementation-dependent binding processor add (reverse direction). More... | |
virtual BindingProcessorConstIterator | beginReverseProcessorsOverride () const |
Implementation-dependent access to reverse direction binding processors. More... | |
virtual AbstractBindingRuntimeSharedPtr | createRuntimeOverride (AbstractBindingSharedPtr binding, BindingLookupContextPtr sourceLookupContext, BindingTargetRuntimePtr targetRuntime)=0 |
Implementation-dependent runtime creation. More... | |
virtual BindingProcessorConstIterator | endReverseProcessorsOverride () const |
Implementation-dependent access to reverse direction binding processors. More... | |
virtual void | removeReverseProcessorOverride (BindingProcessor &processor) |
Implementation-dependent binding processor remove (reverse direction). More... | |
Protected Attributes | |
bool | m_createdFromKZB |
Is the binding sourced from a KZB? This field is used to determine if the binding should be removed during patching. More... | |
BindingProcessorContainer | m_processors |
Binding processor (forward direction). More... | |
BindingSourcePtr | m_source |
Binding source. More... | |
AbstractBinding is the base class for binding classes.
A binding is a relation between two property values. In most cases, this means a relation between a property in a source node or render pass, and a target property in the node or render pass to which the binding is set.
Bindings can also bind values from sources other than object properties and write to other targets. The relationship is abstracted into binding sources and targets.
AbstractBinding contains the immutable data of a binding. To use a binding, create an AbstractBindingRuntime that references the host AbstractBinding for the data. All bindings also contain a BindingSource that describes how to get the source value, and just like the AbstractBindingRuntime, binding sources create a BindingSourceRuntime that references the immutable data in the binding source to perform the read. Unlike BindingSource, BindingTargetRuntime has no binding target counterpart. When you use a binding, Kanzi creates a BindingTargetRuntime and sets it to the AbstractBindingRuntime. Kanzi usually does this for you when you set the binding to a Node or RenderPass.
To use a binding, first create a binding source which determines how to get the source values. To create a binding source that reads a property value from an object:
Use a binding to combine the binding source that you created. The binding determines how Kanzi copies the source value to the target. In this case, a source value is read from source and written to target without caching:
You can now use the binding. To set the binding to a node, use Node::setBinding and specify the binding and target property:
There is now a binding from a property in a sibling node to a property in a node. To remove the binding, use the runtime returned by Node::setBinding:
Kanzi supports these binding types:
The basic form of a binding is called Binding. A binding performs a copy from a source to a target.
To create a one-way binding from a property in a source node to a property in another node:
Most bindings in nodes are one-way bindings. In this case, a property written to the sibling node copies the value to the target.
You can also create two-way bindings. To create a two-way binding, use TwoWayBinding. In a two-way binding setting a property to the source copies the value to the target, the same way as in a one-way binding. In a two-way binding setting a value to the target also copies the value to the source.
To create a two-way binding between two nodes and their properties:
Setting the source value now functions the same way as in a one-way binding.
Setting the value in the target node copies the value to the source.
Bindings can also collect multiple source values, perform mathematical operations on the values, and write a result value for these source values. See ExpressionBinding.
Derivatives of ForwardingAction and others can house manually executed bindings that can be executed in one or two parts. These bindings are executed as part of the action, such as SetPropertyAction or DispatchMessageAction, taking place. See ManualBinding.
To write to other objects, such as another Node or RenderPass, or to write to a property of a RenderPass from a Node, use ToSourceBinding.
BindingSource abstracts the way to get a value for a binding. BindingSource provides the details on how to get the value, and creates a BindingSourceRuntime that refers to the host binding source for the details, but holds the per-binding runtime information.
To create an ObjectPropertyBindingSource that reads properties from objects such as Node or RenderPass:
You can use data sources as binding sources. To use the current effective data source to get values specified by the path within the data source:
Binding sources can resolve resources from a local context. In this case, a resource is resolved using the Node or RenderPass and the result is written to the BindingTargetRuntime.
To create a resource binding source:
To create a resource binding using a shorthand:
Expression bindings use a specific type of source called an ExpressionBindingSource to host the information required for executing mathematical operations.
When the binding is set to a Node or a RenderPass, a BindingTargetRuntime for the binding is internally created. Binding target runtimes do not refer to a host binding target, as BindingSourceRuntime refers to a BindingSource - they contain all the runtime information within themselves. You do not need to create the binding target runtime manually because it is abstracted behind the setBinding() interface of a Node or RenderPass. It is, however, important to understand the differences between the target runtimes.
Bindings are normally installed using setBinding() the function, which creates a ValueSourceBindingTargetRuntime. A value source binding target runtime is just another value source for a property, and does not functionally differ from a custom value source added by PropertyObject::addPropertyValueSource. When the binding is executed, the value is set to the internal value source of the ValueSourceBindingTargetRuntime.
The setBinding() function installs the value source with local value priority by default. This has several implications:
Note also these caveats as compared to normal value source operation:
To remove a binding by removing the local value:
To bind to a value source other than local precedence:
To install a binding as a property modifier:
Bindings installed as modifiers do not differ from regular property modifiers. The modifiers are executed in the order of addition. Adding a binding as a property modifier has these implications:
Binding to a property modifier as one-on-one binding makes little sense, because you can achieve the same result with a value source with less overhead. You can use an ExpressionBinding to read the underlying value from value sources or earlier property modifiers and modify it for more fine-grained control.
To remove a binding that is installed as a property modifier, removing the local property value is not enough. You must remove the binding.
In some situations, it makes sense to specify binding owners to tag the bindings into a group that you can easily identify later. For example, a StateManager or a Style modifying an object can install a binding. Tagging the installed bindings as being owned by a StateObjectRuntime or AppliedStyleEntry enables easy removal of all installed bindings.
To add a binding with an owner pointer:
To remove bindings tagged with an owner pointer:
Binding owners should generally not be required in normal use, but may be important if implementing some state interactions similar to the internal engine use case with states and styles.
You can use binding processors to validate the binding values and to add side effects to bindings. In most cases you add processors to bindings to:
This example defines a binding processor that accepts (validates) the binding result only if the result is an integer value between 1 and 5. The processor does not validate other values, and returning false from the validation causes the result value to not be written.
To use the binding processor defined above:
You do not have to define a new binding processor class for every possible validation. To run arbitrary code, use CallbackBindingProcessor and pass an arbitrary function. This example shows how to do the same thing as above using CallbackBindingProcessor:
To use the callback processor with the given function:
Binding processor container type.
using kanzi::AbstractBinding::BindingProcessorConstIterator = BindingProcessorContainer::const_iterator |
Binding processor iterator type.
|
virtualdefault |
Destructor.
|
inlineexplicitprotected |
Constructor.
source | Binding source for the binding. |
AbstractBindingRuntimeSharedPtr kanzi::AbstractBinding::createRuntime | ( | AbstractBindingSharedPtr | binding, |
BindingLookupContextPtr | sourceLookupContext, | ||
BindingTargetRuntimePtr | targetRuntime | ||
) |
Creates a binding runtime for this binding.
Source runtime is created internally by the contained binding source, target runtime is passed.
binding | Shared pointer to this binding. |
sourceLookupContext | Lookup context to use for binding source(s). |
targetRuntime | An existing binding target. |
|
inline |
Gets the binding source for this binding.
|
inline |
Add a binding processor.
processor | Processor to add. |
|
inline |
Remove a binding processor.
processor | Processor to remove. |
|
inline |
Gets an iterator to the beginning of binding processors.
|
inline |
Gets an iterator to the end of binding processors.
|
inline |
Add a binding processor (reverse direction).
processor | Processor to add. |
|
inline |
Remove a binding processor (reverse direction).
processor | Processor to remove. |
|
inline |
Gets an iterator to the beginning of reverse direction binding processors.
|
inline |
Gets an iterator to the end of reverse direction binding processors.
|
inline |
Indicates whether the binding is sourced from a KZB? Used to check whether or not to remove the binding during patching.
|
inline |
Sets the created from KZB flag.
Should be set for bindings added from KZB data.
flag | New flag state. |
|
protectedpure virtual |
Implementation-dependent runtime creation.
binding | Shared pointer to this binding. |
sourceLookupContext | Lookup context to use for binding source(s). |
targetRuntime | Binding target runtime. |
Implemented in kanzi::ExpressionBinding, kanzi::ManualBinding, kanzi::ToSourceBinding, kanzi::TwoWayBinding, and kanzi::Binding.
|
protectedvirtual |
Implementation-dependent binding processor add (reverse direction).
Default implementation does nothing, since normal bindings are not supposed to have reverse processors.
processor | Processor to add. |
Reimplemented in kanzi::TwoWayBinding.
|
protectedvirtual |
Implementation-dependent binding processor remove (reverse direction).
Default implementation does nothing, since normal bindings are not supposed to have reverse processors.
processor | Processor to remove. |
Reimplemented in kanzi::TwoWayBinding.
|
protectedvirtual |
Implementation-dependent access to reverse direction binding processors.
Default implementation throws an exception, since normal bindings are not supposed to have reverse processors.
Reimplemented in kanzi::TwoWayBinding.
|
protectedvirtual |
Implementation-dependent access to reverse direction binding processors.
Default implementation throws an exception, since normal bindings are not supposed to have reverse processors.
Reimplemented in kanzi::TwoWayBinding.
|
protected |
Binding source.
|
protected |
Binding processor (forward direction).
Inheriting class may add processor for reverse direction.
|
protected |
Is the binding sourced from a KZB? This field is used to determine if the binding should be removed during patching.