ferroui_base/input/platform/
platform_data_transfer.rs1use super::{ClipboardError, PlatformDataTransferItem};
2use crate::input::{DataFormat, IAsyncDataTransfer, IAsyncDataTransferItem, IDataTransfer, IDataTransferItem};
3use crate::reactive::IDisposable;
4use std::cell::RefCell;
5use std::rc::Rc;
6
7pub trait PlatformDataTransferImpl {
9 fn provide_formats(&self) -> Result<Vec<DataFormat>, ClipboardError>;
12
13 fn provide_items(&self) -> Result<Vec<Rc<PlatformDataTransferItem>>, ClipboardError>;
16
17 fn dispose(&self, owner: &PlatformDataTransfer);
20}
21
22pub struct PlatformDataTransfer {
25 formats: RefCell<Option<Rc<[DataFormat]>>>,
26 items: RefCell<Option<Rc<[Rc<PlatformDataTransferItem>]>>>,
27 sync_items: RefCell<Option<Rc<[Rc<dyn IDataTransferItem>]>>>,
28 async_items: RefCell<Option<Rc<[Rc<dyn IAsyncDataTransferItem>]>>>,
29 platform_impl: Box<dyn PlatformDataTransferImpl>,
30}
31
32impl PlatformDataTransfer {
33 pub fn new(platform_impl: impl PlatformDataTransferImpl + 'static) -> Rc<PlatformDataTransfer> {
35 Rc::new(PlatformDataTransfer {
36 formats: RefCell::new(None),
37 items: RefCell::new(None),
38 sync_items: RefCell::new(None),
39 async_items: RefCell::new(None),
40 platform_impl: Box::new(platform_impl),
41 })
42 }
43
44 #[track_caller]
51 pub fn formats(&self) -> Rc<[DataFormat]> {
52 match self.try_formats() {
53 Ok(formats) => formats,
54 Err(error) => panic!("{error}"),
55 }
56 }
57
58 pub fn try_formats(&self) -> Result<Rc<[DataFormat]>, ClipboardError> {
61 if let Some(formats) = self.formats.borrow().as_ref() {
62 return Ok(formats.clone());
63 }
64
65 let formats: Rc<[DataFormat]> = Rc::from(self.platform_impl.provide_formats()?);
66 *self.formats.borrow_mut() = Some(formats.clone());
67 Ok(formats)
68 }
69
70 pub fn are_formats_initialized(&self) -> bool {
72 self.formats.borrow().is_some()
73 }
74
75 #[track_caller]
82 pub fn items(&self) -> Rc<[Rc<PlatformDataTransferItem>]> {
83 match self.try_items() {
84 Ok(items) => items,
85 Err(error) => panic!("{error}"),
86 }
87 }
88
89 pub fn try_items(&self) -> Result<Rc<[Rc<PlatformDataTransferItem>]>, ClipboardError> {
92 if let Some(items) = self.items.borrow().as_ref() {
93 return Ok(items.clone());
94 }
95
96 let items: Rc<[Rc<PlatformDataTransferItem>]> = Rc::from(self.platform_impl.provide_items()?);
97 *self.items.borrow_mut() = Some(items.clone());
98 Ok(items)
99 }
100
101 pub fn are_items_initialized(&self) -> bool {
103 self.items.borrow().is_some()
104 }
105}
106
107impl IDisposable for PlatformDataTransfer {
108 fn dispose(&self) {
109 self.platform_impl.dispose(self)
110 }
111}
112
113impl IDataTransfer for PlatformDataTransfer {
114 fn formats(&self) -> Rc<[DataFormat]> {
115 PlatformDataTransfer::formats(self)
116 }
117
118 fn items(&self) -> Rc<[Rc<dyn IDataTransferItem>]> {
119 if let Some(items) = self.sync_items.borrow().as_ref() {
120 return items.clone();
121 }
122
123 let items: Rc<[Rc<dyn IDataTransferItem>]> =
124 PlatformDataTransfer::items(self).iter().map(|item| item.clone() as Rc<dyn IDataTransferItem>).collect();
125 *self.sync_items.borrow_mut() = Some(items.clone());
126 items
127 }
128
129 fn as_async_data_transfer(self: Rc<Self>) -> Option<Rc<dyn IAsyncDataTransfer>> {
130 Some(self)
131 }
132}
133
134impl IAsyncDataTransfer for PlatformDataTransfer {
135 fn formats(&self) -> Rc<[DataFormat]> {
136 PlatformDataTransfer::formats(self)
137 }
138
139 fn items(&self) -> Rc<[Rc<dyn IAsyncDataTransferItem>]> {
140 match IAsyncDataTransfer::try_items(self) {
141 Ok(items) => items,
142 Err(error) => panic!("{error}"),
143 }
144 }
145
146 fn try_formats(&self) -> Result<Rc<[DataFormat]>, ClipboardError> {
147 PlatformDataTransfer::try_formats(self)
148 }
149
150 fn try_items(&self) -> Result<Rc<[Rc<dyn IAsyncDataTransferItem>]>, ClipboardError> {
151 if let Some(items) = self.async_items.borrow().as_ref() {
152 return Ok(items.clone());
153 }
154
155 let items: Rc<[Rc<dyn IAsyncDataTransferItem>]> = PlatformDataTransfer::try_items(self)?
156 .iter()
157 .map(|item| item.clone() as Rc<dyn IAsyncDataTransferItem>)
158 .collect();
159 *self.async_items.borrow_mut() = Some(items.clone());
160 Ok(items)
161 }
162
163 fn as_data_transfer(self: Rc<Self>) -> Option<Rc<dyn IDataTransfer>> {
164 Some(self)
165 }
166}