ferroui_base/input/platform/
clipboard.rs1use super::{ClipboardError, IClipboard, IClipboardImpl};
2use crate::input::{IAsyncDataTransfer, LocalBoxFuture};
3use std::cell::RefCell;
4use std::rc::{Rc, Weak};
5
6pub struct Clipboard {
8 this: Weak<Clipboard>,
9 clipboard_impl: Rc<dyn IClipboardImpl>,
10 last_data_transfer: RefCell<Option<Rc<dyn IAsyncDataTransfer>>>,
11}
12
13impl Clipboard {
14 pub fn new(clipboard_impl: Rc<dyn IClipboardImpl>) -> Rc<Clipboard> {
16 Rc::new_cyclic(|this| Clipboard { this: this.clone(), clipboard_impl, last_data_transfer: RefCell::new(None) })
17 }
18
19 fn take_last_data_transfer(&self) -> Option<Rc<dyn IAsyncDataTransfer>> {
20 self.last_data_transfer.borrow_mut().take()
21 }
22}
23
24impl IClipboard for Clipboard {
25 fn clear_async(&self) -> LocalBoxFuture<Result<(), ClipboardError>> {
26 if let Some(last_data_transfer) = self.take_last_data_transfer() {
27 last_data_transfer.dispose();
28 }
29
30 self.clipboard_impl.clear_async()
31 }
32
33 fn set_data_async(
34 &self,
35 data_transfer: Option<Rc<dyn IAsyncDataTransfer>>,
36 ) -> LocalBoxFuture<Result<(), ClipboardError>> {
37 let Some(data_transfer) = data_transfer else {
38 return self.clear_async();
39 };
40
41 if self.clipboard_impl.as_owned_clipboard_impl().is_some() {
42 let old = self.last_data_transfer.replace(Some(data_transfer.clone()));
43 drop(old);
44 }
45
46 self.clipboard_impl.set_data_async(data_transfer)
47 }
48
49 fn flush_async(&self) -> LocalBoxFuture<Result<(), ClipboardError>> {
50 match self.clipboard_impl.as_flushable_clipboard_impl() {
51 Some(flushable) => flushable.flush_async(),
52 None => Box::pin(std::future::ready(Ok(()))),
53 }
54 }
55
56 fn try_get_data_async(&self) -> LocalBoxFuture<Result<Option<Rc<dyn IAsyncDataTransfer>>, ClipboardError>> {
57 self.clipboard_impl.try_get_data_async()
58 }
59
60 fn try_get_in_process_data_async(
61 &self,
62 ) -> LocalBoxFuture<Result<Option<Rc<dyn IAsyncDataTransfer>>, ClipboardError>> {
63 if self.last_data_transfer.borrow().is_none() {
64 return Box::pin(std::future::ready(Ok(None)));
65 }
66
67 let Some(owned_clipboard_impl) = self.clipboard_impl.as_owned_clipboard_impl() else {
68 return Box::pin(std::future::ready(Ok(None)));
69 };
70
71 let is_current_owner = owned_clipboard_impl.is_current_owner_async();
72 let this = self.this.clone();
73
74 Box::pin(async move {
75 let is_current_owner = is_current_owner.await?;
77 let Some(this) = this.upgrade() else {
78 return Ok(None);
79 };
80
81 if !is_current_owner {
82 drop(this.take_last_data_transfer());
83 }
84
85 let result = this.last_data_transfer.borrow().clone();
86 Ok(result)
87 })
88 }
89}