Skip to main content

ferroui_base/input/
key_binding.rs

1use super::{ICommand, KeyEventArgs, KeyGesture};
2use crate::{
3    ferro_class, ferro_impl_classes, ferro_property, instantiate, BoxedValue, FerroObject, FerroObjectImpl,
4    FerroProperty, Ref, StyledProperty,
5};
6use std::rc::Rc;
7
8/// Binds a key gesture to a command.
9#[repr(C)]
10pub struct KeyBinding {
11    base: FerroObject,
12}
13
14ferro_class!(KeyBinding: FerroObject);
15crate::ferro_class_info!(KeyBinding { new: KeyBinding::new });
16ferro_impl_classes!(KeyBinding: FerroObjectImpl);
17
18crate::ferro_properties! { impl KeyBinding {
19    ferro_property!(
20        /// Defines the `Command` property.
21        pub fn command_property() -> StyledProperty<Option<Rc<dyn ICommand>>> {
22            FerroProperty::register::<KeyBinding, _>("Command", None)
23        }
24    );
25
26    ferro_property!(
27        /// Defines the `CommandParameter` property.
28        pub fn command_parameter_property() -> StyledProperty<Option<BoxedValue>> {
29            FerroProperty::register::<KeyBinding, _>("CommandParameter", None)
30        }
31    );
32
33    ferro_property!(
34        /// Defines the `Gesture` property.
35        pub fn gesture_property() -> StyledProperty<Option<KeyGesture>> {
36            FerroProperty::register::<KeyBinding, _>("Gesture", None)
37        }
38    );
39} }
40
41impl KeyBinding {
42    /// Creates the class data; see [`FerroObject::construct`].
43    pub fn construct() -> Self {
44        Self { base: FerroObject::construct() }
45    }
46
47    pub fn new() -> Ref<Self> {
48        instantiate(Self::construct())
49    }
50
51    /// The command invoked by the binding.
52    pub fn command(&self) -> Option<Rc<dyn ICommand>> {
53        self.get_value(Self::command_property())
54    }
55
56    pub fn set_command(&self, value: Option<Rc<dyn ICommand>>) {
57        self.set_value(Self::command_property(), value)
58    }
59
60    /// The parameter passed to the command.
61    pub fn command_parameter(&self) -> Option<BoxedValue> {
62        self.get_value(Self::command_parameter_property())
63    }
64
65    pub fn set_command_parameter(&self, value: Option<BoxedValue>) {
66        self.set_value(Self::command_parameter_property(), value)
67    }
68
69    /// The key gesture that invokes the command.
70    pub fn gesture(&self) -> Option<KeyGesture> {
71        self.get_value(Self::gesture_property())
72    }
73
74    pub fn set_gesture(&self, value: Option<KeyGesture>) {
75        self.set_value(Self::gesture_property(), value)
76    }
77
78    /// Executes the command and marks the event handled, if the event
79    /// matches the gesture and the command can execute.
80    pub fn try_handle(&self, args: &KeyEventArgs) {
81        if self.gesture().is_some_and(|gesture| gesture.matches(Some(args))) {
82            if let Some(command) = self.command() {
83                let parameter = self.command_parameter();
84                if command.can_execute(parameter.as_ref()) {
85                    args.set_handled(true);
86                    command.execute(parameter.as_ref());
87                }
88            }
89        }
90    }
91}