Skip to main content

ferroui_base/input/
data_transfer.rs

1use super::{DataFormat, DataTransferItem, IAsyncDataTransfer, IAsyncDataTransferItem, IDataTransfer, IDataTransferItem};
2use crate::reactive::IDisposable;
3use std::cell::RefCell;
4use std::rc::Rc;
5
6#[derive(Default)]
7struct Cache {
8    formats: Option<Rc<[DataFormat]>>,
9    items: Option<Rc<[Rc<DataTransferItem>]>>,
10    sync_items: Option<Rc<[Rc<dyn IDataTransferItem>]>>,
11    async_items: Option<Rc<[Rc<dyn IAsyncDataTransferItem>]>>,
12}
13
14/// A mutable implementation of [`IDataTransfer`] and
15/// [`IAsyncDataTransfer`].
16///
17/// While it also implements [`IAsyncDataTransfer`], this type always
18/// returns data synchronously. For advanced usages, consider implementing
19/// [`IAsyncDataTransfer`] directly.
20pub struct DataTransfer {
21    items: RefCell<Vec<Rc<DataTransferItem>>>,
22    cache: RefCell<Cache>,
23}
24
25impl DataTransfer {
26    /// Creates an empty data transfer.
27    pub fn new() -> Rc<DataTransfer> {
28        Rc::new(DataTransfer { items: RefCell::new(Vec::new()), cache: RefCell::new(Cache::default()) })
29    }
30
31    /// Gets the formats supported by the items of this object, without
32    /// duplicates.
33    pub fn formats(&self) -> Rc<[DataFormat]> {
34        if let Some(formats) = self.cache.borrow().formats.as_ref() {
35            return formats.clone();
36        }
37
38        let mut formats: Vec<DataFormat> = Vec::new();
39        for item in self.items().iter() {
40            for format in item.formats().iter() {
41                if !formats.contains(format) {
42                    formats.push(format.clone());
43                }
44            }
45        }
46
47        let formats: Rc<[DataFormat]> = Rc::from(formats);
48        self.cache.borrow_mut().formats = Some(formats.clone());
49        formats
50    }
51
52    /// Gets a list of [`DataTransferItem`] contained in this object.
53    pub fn items(&self) -> Rc<[Rc<DataTransferItem>]> {
54        if let Some(items) = self.cache.borrow().items.as_ref() {
55            return items.clone();
56        }
57
58        let items: Rc<[Rc<DataTransferItem>]> = Rc::from(self.items.borrow().as_slice());
59        self.cache.borrow_mut().items = Some(items.clone());
60        items
61    }
62
63    /// Adds an existing [`DataTransferItem`] to this object.
64    pub fn add(&self, item: Rc<DataTransferItem>) {
65        let old = std::mem::take(&mut *self.cache.borrow_mut());
66        drop(old);
67        self.items.borrow_mut().push(item);
68    }
69}
70
71impl IDisposable for DataTransfer {
72    fn dispose(&self) {}
73}
74
75impl IDataTransfer for DataTransfer {
76    fn formats(&self) -> Rc<[DataFormat]> {
77        DataTransfer::formats(self)
78    }
79
80    fn items(&self) -> Rc<[Rc<dyn IDataTransferItem>]> {
81        if let Some(items) = self.cache.borrow().sync_items.as_ref() {
82            return items.clone();
83        }
84
85        let items: Rc<[Rc<dyn IDataTransferItem>]> =
86            self.items.borrow().iter().map(|item| item.clone() as Rc<dyn IDataTransferItem>).collect();
87        self.cache.borrow_mut().sync_items = Some(items.clone());
88        items
89    }
90
91    fn as_async_data_transfer(self: Rc<Self>) -> Option<Rc<dyn IAsyncDataTransfer>> {
92        Some(self)
93    }
94}
95
96impl IAsyncDataTransfer for DataTransfer {
97    fn formats(&self) -> Rc<[DataFormat]> {
98        DataTransfer::formats(self)
99    }
100
101    fn items(&self) -> Rc<[Rc<dyn IAsyncDataTransferItem>]> {
102        if let Some(items) = self.cache.borrow().async_items.as_ref() {
103            return items.clone();
104        }
105
106        let items: Rc<[Rc<dyn IAsyncDataTransferItem>]> =
107            self.items.borrow().iter().map(|item| item.clone() as Rc<dyn IAsyncDataTransferItem>).collect();
108        self.cache.borrow_mut().async_items = Some(items.clone());
109        items
110    }
111
112    fn as_data_transfer(self: Rc<Self>) -> Option<Rc<dyn IDataTransfer>> {
113        Some(self)
114    }
115}