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)
    }
}