Skip to main content

ferroui_base/input/
focus_changing_event_args.rs

1use super::{IKeyModifiersEventArgs, InputElement, KeyModifiers, NavigationMethod};
2use crate::interactivity::{RoutedEvent, RoutedEventArgs};
3use crate::{ferro_routed_event_args, Ref};
4use std::cell::{Cell, RefCell};
5use std::rc::Rc;
6
7/// Provides data for focus changing: the `GettingFocus` and `LosingFocus`
8/// events, which can cancel or redirect a focus change.
9#[derive(Clone)]
10pub struct FocusChangingEventArgs {
11    base: RoutedEventArgs,
12    new_focused_element: Rc<RefCell<Option<Ref<InputElement>>>>,
13    canceled: Rc<Cell<bool>>,
14    pub(crate) can_cancel_or_redirect_focus: bool,
15
16    /// The element that had focus before the change.
17    pub old_focused_element: Option<Ref<InputElement>>,
18
19    /// Indicates how the change in focus occurred.
20    pub navigation_method: NavigationMethod,
21
22    /// Any key modifiers active at the time of focus.
23    pub key_modifiers: KeyModifiers,
24}
25
26ferro_routed_event_args!(FocusChangingEventArgs: RoutedEventArgs);
27
28impl FocusChangingEventArgs {
29    /// Creates args for a routed event.
30    pub fn new<T: ?Sized>(routed_event: &RoutedEvent<T>) -> Self {
31        Self {
32            base: RoutedEventArgs::with_event(routed_event),
33            new_focused_element: Rc::new(RefCell::new(None)),
34            canceled: Rc::new(Cell::new(false)),
35            can_cancel_or_redirect_focus: false,
36            old_focused_element: None,
37            navigation_method: NavigationMethod::Unspecified,
38            key_modifiers: KeyModifiers::NONE,
39        }
40    }
41
42    /// The element that focus will move to.
43    pub fn new_focused_element(&self) -> Option<Ref<InputElement>> {
44        self.new_focused_element.borrow().clone()
45    }
46
47    pub(crate) fn set_new_focused_element(&self, value: Option<Ref<InputElement>>) {
48        let old = self.new_focused_element.replace(value);
49        drop(old);
50    }
51
52    /// Whether the focus change is canceled.
53    pub fn canceled(&self) -> bool {
54        self.canceled.get()
55    }
56
57    /// Attempts to cancel the current focus change. Returns true if the
58    /// focus change was cancelled; otherwise, false.
59    pub fn try_cancel(&self) -> bool {
60        self.canceled.set(self.can_cancel_or_redirect_focus);
61        self.canceled.get()
62    }
63
64    /// Attempts to redirect focus from the targeted element to the
65    /// specified element. Returns true if the focus change was redirected;
66    /// otherwise, false.
67    pub fn try_set_new_focused_element(&self, input_element: Option<&Ref<InputElement>>) -> bool {
68        if self.can_cancel_or_redirect_focus {
69            self.set_new_focused_element(input_element.cloned());
70        }
71
72        input_element == self.new_focused_element.borrow().as_ref()
73    }
74}
75
76impl IKeyModifiersEventArgs for FocusChangingEventArgs {
77    fn key_modifiers(&self) -> KeyModifiers {
78        self.key_modifiers
79    }
80}