Skip to main content

ferroui_reactiveui/binding/interfaces/
i_creates_command_binding.rs

1//! `ICreatesCommandBinding` (ReactiveUI.Binding, `Interfaces/ICreatesCommandBinding.cs`).
2
3use crate::reactive_command::ICommand;
4use ferroui_system::{IDisposable, IObservable};
5use std::any::{Any, TypeId};
6use std::rc::Rc;
7
8/// A command parameter (`object?`): the value the command is executed with, of any type, or none.
9/// A command receives it as `Option<&dyn Any>` (`parameter.as_deref()`).
10pub type CommandParameter = Option<Rc<dyn Any>>;
11
12/// Adds a handler to an event of a control and returns the disposable that removes it: the
13/// counterpart of the pair `addHandler` / `removeHandler` of `Action<EventHandler<TEventArgs>>`.
14pub type CommandEventSubscription = Rc<dyn Fn(Rc<dyn Fn()>) -> Rc<dyn IDisposable>>;
15
16/// A plugin that binds an [`ICommand`] to a control (`ICreatesCommandBinding`). The
17/// implementations are registered in the service locator (Splat) as `dyn ICreatesCommandBinding`,
18/// and the one with the highest affinity for the type of a control binds it
19/// ([`CommandBinderService`](crate::CommandBinderService)), as upstream.
20///
21/// The crate registers none: [`CreatesCommandBindingViaEvent`](crate::CreatesCommandBindingViaEvent)
22/// and [`CreatesCommandBindingViaCommandParameter`](crate::CreatesCommandBindingViaCommandParameter)
23/// bind the controls of one type, and a platform registers its own (the controls of FerroUI).
24///
25/// Deviation (DEVIATIONS.md, ReactiveUI): the trait is object safe. The type parameter `T` of the
26/// control is a `TypeId` in [`get_affinity_for_object`](Self::get_affinity_for_object) and the
27/// control an `Rc<dyn Any>` in the bindings; `TEventArgs` has no counterpart (the handler ignores
28/// the arguments of the event); the add and remove handlers are one
29/// [`CommandEventSubscription`]; the command parameter is an observable of [`CommandParameter`].
30pub trait ICreatesCommandBinding {
31    /// A positive number when this plugin can bind a command to an object of the type
32    /// `target_type`, the highest number winning among the plugins; zero or less when it cannot
33    /// (`GetAffinityForObject<T>(bool hasEventTarget)`). `has_event_target` says whether the caller
34    /// names the event to bind to.
35    fn get_affinity_for_object(&self, target_type: TypeId, has_event_target: bool) -> i32;
36
37    /// Binds `command` to `target` through the default event of the target (`Click`, ...), executed
38    /// with the latest value of `command_parameter`; `None` when no binding was made, as for a
39    /// missing command (`BindCommandToObject<T>`). Disposing the result unbinds the command.
40    fn bind_command_to_object(
41        &self,
42        command: Option<Rc<dyn ICommand>>,
43        target: Option<Rc<dyn Any>>,
44        command_parameter: Rc<dyn IObservable<CommandParameter>>,
45    ) -> Option<Rc<dyn IDisposable>>;
46
47    /// Binds `command` to the event named `event_name` of `target`
48    /// (`BindCommandToObject<T, TEventArgs>(..., string eventName)`).
49    fn bind_command_to_object_event(
50        &self,
51        command: Option<Rc<dyn ICommand>>,
52        target: Option<Rc<dyn Any>>,
53        command_parameter: Rc<dyn IObservable<CommandParameter>>,
54        event_name: &str,
55    ) -> Option<Rc<dyn IDisposable>>;
56
57    /// Binds `command` to the event that `subscription` adds a handler to
58    /// (`BindCommandToObject<T, TEventArgs>(..., addHandler, removeHandler)`).
59    fn bind_command_to_object_with_handlers(
60        &self,
61        command: Option<Rc<dyn ICommand>>,
62        target: Option<Rc<dyn Any>>,
63        command_parameter: Rc<dyn IObservable<CommandParameter>>,
64        subscription: CommandEventSubscription,
65    ) -> Option<Rc<dyn IDisposable>>;
66}