ui: add scoped event and observable value bindings

Introduce EventConnection and EventConnectionList for scoped Node event listeners that safely handle either emitter or observer destruction order.

Add ObservableValue and UIValueBinding for UI-independent observable state, along with a shared UIValueConverter policy used by both observable and raw data bindings.

Harden UIDataBind and UIProperty lifetime behavior, documentation, conversion, operators, and multi-widget handling. Preserve UIProperty as the lightweight option for UI-local owned values and UIDataBind for explicitly managed external values.

Use inline ordered callback storage to preserve registration-order dispatch without per-listener tree allocations.

Migrate submenu observation to scoped connections, safely clear ecode run configuration bindings before model erasure, and simplify the 7GUIs Counter example with UIProperty.

Add lifecycle, ordering, conversion, binding, and mutation regression tests.
This commit is contained in:
Martín Lucas Golini
2026-08-08 20:28:45 -03:00
parent 90c5d12c3e
commit 01d5614a71
18 changed files with 1388 additions and 152 deletions
+2 -5
View File
@@ -9,10 +9,7 @@ EE_MAIN_FUNC int main( int, char** ) {
<PushButton id="count_click" layout_width="0" layout_weight="0.5" layout_height="match_parent" text="Count" />
</hbox>
)xml" );
int count = 0;
auto view = hbox->find<UITextView>( "count_view" );
hbox->find( "count_click" )->onClick( [&count, view]( auto ) {
view->setText( String::toString( ++count ) );
} );
UIProperty<int> count( 0, hbox->find<UITextView>( "count_view" ) );
hbox->find( "count_click" )->onClick( [&count]( auto ) { ++count; } );
return app.run();
}