template class EE::UI::UIValueBinding

Overview

Move-only two-way binding between an ObservableValue and a UIWidget property. More…

#include <uivaluebinding.hpp>

template <typename T>
class UIValueBinding {
public:
    // typedefs

    typedef UIValueConverter<T> Converter;

    // structs

    struct State;

    // construction

    UIValueBinding();
    UIValueBinding(const UIValueBinding&);
    UIValueBinding(UIValueBinding&&);
    UIValueBinding(ObservableValue<T>& value, UIWidget* widget, const Converter& converter = converterDefault(), const std::string& propertyName = "value", Event::EventType eventType = Event::OnValueChange);

    // methods

    static Converter converterDefault();
    UIValueBinding& operator=(const UIValueBinding&);
    UIValueBinding& operator=(UIValueBinding&&);
    void disconnect();
    operator bool() const;
    bool isConnected() const;
    bool isValid() const;
    UIWidget* widget() const;
    std::optional<T> value() const;
    bool setValue(const T& value);
    ObservableValue<T>::Connection observeValue(typename ObservableValue<T>::Callback callback);
    UIValueValidationState* validationState();
    const UIValueValidationState* validationState() const;
};

Detailed Documentation

Move-only two-way binding between an ObservableValue and a UIWidget property.

The converter maps directly between T and the widget property string. Its toValue() callback decides whether widget input may enter the model. Model-originated values are authoritative and are formatted through fromValue().

Destroying the binding disconnects both directions. Destroying either the observable or widget first is safe and does not keep that endpoint alive.

Synchronization is immediate and single-threaded. The observable, widget, and binding must all be used on the widget’s owning UI thread.

Use UIValueBinding when an ObservableValue belongs to a UI-independent model. The returned binding must be retained for as long as synchronization is desired.

ObservableValue<std::string> userName{ "Ada" };
auto binding = bindValue( userName, textInput,
                     UIValueConverter<std::string>::converterString(),
                     "text", Event::OnTextChanged );
userName = "Grace"; // Updates textInput without coupling the model to UIWidget.

Construction

UIValueBinding(ObservableValue<T>& value, UIWidget* widget, const Converter& converter = converterDefault(), const std::string& propertyName = "value", Event::EventType eventType = Event::OnValueChange)

Starts synchronizing value with a property of widget.

The current model value is applied to the widget immediately. Later eventType events parse the widget property back into the model.

Methods

static Converter converterDefault()

Returns:

The standard converter for the bound value type.

void disconnect()

Stops synchronization in both directions. Calling this repeatedly is safe.

operator bool() const

Returns:

Whether both model and widget endpoints are still alive and connected.

bool isConnected() const

Returns:

Whether both model and widget endpoints are still alive and connected.

bool isValid() const

Returns:

Whether the most recent conversion or validation succeeded.

UIWidget* widget() const

Returns:

The bound widget, or nullptr after disconnection or widget destruction.

std::optional<T> value() const

Returns:

A copy of the model value, or std::nullopt after disconnection.

bool setValue(const T& value)

Returns:

true when the connected model still exists and was assigned value.

ObservableValue<T>::Connection observeValue(typename ObservableValue<T>::Callback callback)

Returns:

A scoped observer connection to later model changes, or an empty connection.

UIValueValidationState* validationState()

Returns:

Observable conversion and input-validation state.