v0.27.1
ui! widgets accept on EventKind { body } for inline gesture handlers, with two unambiguous positions: between attrs and children body (Form C), or as a modifier chain after the widget (Form B). The seven GestureEvent variants are routed by name; multi-tap is supported on Tap via a new MultiTapTracker resource with a 300ms window.
Added
Widget() on EventKind { body } { children }(Form C, inline) —onlives between attrs and children body. Multipleonclauses stack on the same widget.Widget() {} on EventKind { body }(Form B, modifier chain) —onfollows a fully-parsed widget. Inside a nested body,onattaches to the nearest preceding sibling widget. Multipleonclauses chain.- Mixed Form B + Form C on the same widget — all
onclauses collect into one dispatch fn, regardless of their position. on Tap(n)multi-tap —n∈ {1, 2, 3} routes byMultiTapTracker::current_count.on Tapandon Tap(2)coexist on the same widget; the dispatch fn picks the matching arm at fire time.MultiTapTrackerresource —bubble_dispatch_atlazy-inserts the resource on the first Tap. The 300ms window isMULTI_TAP_WINDOW_MS.now_ms == 0is the "no clock available" sentinel and never accumulates count.bubble_dispatch_at(world, event, now_ms)— clock-aware dispatch;bubble_dispatchdelegates to it withnow_ms = 0. The real input loop inApp::runuses the live monotonic clock.- Auto-destructured fields in handler bodies —
x,y,dx,dy,vx,vy,scale_delta,angle,targetare all in scope as appropriate for the matched event variant.__world: &mut Worldand__entity: Entityare also bound. - trybuild fixtures for ui! diagnostics:
on_form_a_inside_body.rs(rejectsWidget() { on EventKind {} }with a clear error),on_non_tap_with_args.rs,on_qualified_path.rs,on_unknown_event.rs. gallery/examples/on_handlers_demo.rs— four colour-coded boxes withon Tap/on Tap(2)/on Tap(3)/on LongPressin modifier-chain form, a label above counts each kind.
Notes
- Bodies default to
true(consume the event); explicitreturn falseletsbubble_dispatchkeep walking. - On Component widgets (
Button,Slider, etc.) the useron EventKinddispatch fn replaces the component's internalGestureHandler— same single-handler ECS semantics that already governed manualworld.insert(GestureHandler { ... }). on Path::EventKindqualified form parses but raises a compile error pointing users at the unqualified form. Non-Tap events with parameters (on LongPress(500)etc.) compile-error too.
Internal
- xrune dependency:
1.5.1(1.5.0 yanked).DsRune::inscribe_widgetnow takeson_handlers: &[DsOn]for the on-clauses attached to the widget;DsRune::inscribe_onis removed.