Skip to main content

ferroui_xaml_interactions/
platform_handles.rs

1//! Not from the reference: handles of the platform services the actions of the crate hold in
2//! properties and pass to commands.
3//!
4//! A property value and an untyped value compare with `==`; the contracts of the platform
5//! services (the clipboard, the storage provider, the storage items, the data transfers) do not,
6//! so the actions hold them in handles that compare by identity, as the reference compares its
7//! interface references.
8//!
9//! Deviation (DEVIATIONS.md, Behaviors): the properties typed `IClipboard`, `IStorageProvider`,
10//! `IStorageFolder` and `IAsyncDataTransfer` in the reference hold the handles of this module,
11//! and the picked files and folders are passed to commands as lists of handles.
12
13use ferroui_base::input::platform::IClipboard;
14use ferroui_base::input::IAsyncDataTransfer;
15use ferroui_base::platform::storage::{IStorageFile, IStorageFolder, IStorageItem, IStorageProvider};
16use std::fmt;
17use std::ops::Deref;
18use std::rc::Rc;
19
20macro_rules! handle {
21    ($(#[$meta:meta])* $name:ident => $contract:ident) => {
22        $(#[$meta])*
23        #[derive(Clone)]
24        pub struct $name(pub Rc<dyn $contract>);
25
26        impl $name {
27            /// The handle of `value`.
28            pub fn new(value: Rc<dyn $contract>) -> Self {
29                Self(value)
30            }
31
32            /// The shared object.
33            pub fn get(&self) -> &Rc<dyn $contract> {
34                &self.0
35            }
36        }
37
38        impl Deref for $name {
39            type Target = dyn $contract;
40
41            fn deref(&self) -> &(dyn $contract + 'static) {
42                &*self.0
43            }
44        }
45
46        impl PartialEq for $name {
47            fn eq(&self, other: &Self) -> bool {
48                std::ptr::addr_eq(Rc::as_ptr(&self.0), Rc::as_ptr(&other.0))
49            }
50        }
51
52        impl From<Rc<dyn $contract>> for $name {
53            fn from(value: Rc<dyn $contract>) -> Self {
54                Self(value)
55            }
56        }
57
58        impl fmt::Debug for $name {
59            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60                write!(f, "{}({:p})", stringify!($name), Rc::as_ptr(&self.0))
61            }
62        }
63    };
64}
65
66handle!(
67    /// A clipboard (`IClipboard`).
68    ClipboardRef => IClipboard
69);
70
71handle!(
72    /// A storage provider (`IStorageProvider`).
73    StorageProviderRef => IStorageProvider
74);
75
76handle!(
77    /// A folder of a storage provider (`IStorageFolder`).
78    StorageFolderRef => IStorageFolder
79);
80
81handle!(
82    /// A file of a storage provider (`IStorageFile`).
83    StorageFileRef => IStorageFile
84);
85
86handle!(
87    /// A file or folder of a storage provider (`IStorageItem`).
88    StorageItemRef => IStorageItem
89);
90
91handle!(
92    /// A data transfer that is read asynchronously (`IAsyncDataTransfer`).
93    AsyncDataTransferRef => IAsyncDataTransfer
94);