1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
// Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License in the LICENSE-APACHE file or at: // https://www.apache.org/licenses/LICENSE-2.0 //! Event handling - handler use super::*; #[allow(unused)] use crate::Widget; // for doc-links use crate::{WidgetConfig, WidgetId}; /// Event handling for a [`Widget`] /// /// This trait is part of the [`Widget`] family and is derived by /// [`derive(Widget)`] unless `#[handler(handle = noauto)]` /// or `#[handler(noauto)]` is used. /// /// Interactive widgets should implement their event-handling logic here /// (although it is also possible to implement this in [`SendEvent::send`], /// which might be preferable when dealing with child widgets). /// /// The default implementation does nothing, and is derived by `derive(Widget)` /// when a `#[handler]` attribute is present (except with parameter /// `handler=noauto`). /// /// [`derive(Widget)`]: ../macros/index.html#the-derivewidget-macro pub trait Handler: WidgetConfig { /// Type of message returned by this widget /// /// This mechanism allows type-safe handling of user-defined responses to /// handled actions, for example an enum encoding button presses or a /// floating-point value from a slider. /// /// The [`VoidMsg`] type may be used where messages are never generated. /// This is distinct from `()`, which might be applicable when a widget only /// needs to "wake up" a parent. type Msg; /// Generic handler: translate presses to activations /// /// This is configuration for [`Manager::handle_generic`], and can be used /// to translate *press* (click/touch) events into [`Event::Activate`]. // NOTE: not an associated constant because these are not object-safe #[inline] fn activation_via_press(&self) -> bool { false } /// Handle an event and return a user-defined message /// /// Widgets should handle any events applicable to themselves here, and /// return all other events via [`Response::Unhandled`]. #[inline] fn handle(&mut self, _: &mut Manager, event: Event) -> Response<Self::Msg> { Response::Unhandled(event) } } /// Event routing /// /// This trait is part of the [`Widget`] family and is derived by /// [`derive(Widget)`] unless `#[handler(send = noauto)]` /// or `#[handler(noauto)]` is used. /// /// This trait is responsible for routing events to the correct widget. It is /// separate from [`Handler`] since it can be derived for many parent widgets, /// even when event *handling* must be implemented manually. /// /// This trait is implemented by `derive(Widget)` when a `#[handler]` attribute /// is present (except with parameter `send=noauto`). /// /// [`derive(Widget)`]: ../macros/index.html#the-derivewidget-macro pub trait SendEvent: Handler { /// Send an event /// /// This method is responsible for routing events toward descendents. /// [`WidgetId`] values are assigned via depth-first search with parents /// ordered after all children. Disabling a widget is recursive, hence /// disabled widgets should not forward any events. /// /// The following logic is recommended for routing events: /// ```no_test /// if self.is_disabled() { /// return Response::Unhandled(event); /// } /// if id <= self.child1.id() { /// self.child1.event(mgr, id, event).into() /// } else if id <= self.child2.id() { /// self.child2.event(mgr, id, event).into() /// } ... { /// } else { /// debug_assert!(id == self.id(), "SendEvent::send: bad WidgetId"); /// Manager::handle_generic(self, mgr, event) /// } /// ``` /// Parents which don't handle any events themselves may simplify this: /// ```no_test /// if !self.is_disabled() && id <= self.w.id() { /// return self.w.send(mgr, id, event); /// } /// Response::Unhandled(event) /// ``` /// /// When the child's [`Handler::Msg`] type is not [`VoidMsg`], its response /// messages can be handled here (in place of `.into()` above). /// /// The example above uses [`Manager::handle_generic`], which is an optional /// tool able to perform some simplifications on events. It is also valid to /// call [`Handler::handle`] directly or simply to embed handling logic here. fn send(&mut self, mgr: &mut Manager, id: WidgetId, event: Event) -> Response<Self::Msg>; } impl<'a> Manager<'a> { /// Generic event simplifier /// /// This is a free function often called from [`SendEvent::send`] to /// simplify certain events and then invoke [`Handler::handle`]. pub fn handle_generic<W>( widget: &mut W, mgr: &mut Manager, mut event: Event, ) -> Response<<W as Handler>::Msg> where W: Handler + ?Sized, { if widget.activation_via_press() { // Translate press events match event { Event::PressStart { source, coord, .. } if source.is_primary() => { mgr.request_grab(widget.id(), source, coord, GrabMode::Grab, None); return Response::None; } Event::PressMove { source, cur_id, .. } => { let cond = cur_id == Some(widget.id()); let target = if cond { cur_id } else { None }; mgr.set_grab_depress(source, target); return Response::None; } Event::PressEnd { end_id, .. } if end_id == Some(widget.id()) => { event = Event::Activate; } _ => (), }; } match event { Event::NavFocus => return Response::Focus(widget.rect()), _ => (), } widget.handle(mgr, event) } }