ferroui-browser 0.3.0

The browser platform of FerroUI: a top-level in an element of a web page, rendered with WebGL or to a 2D canvas
Documentation
use crate::browser_data_transfer_helper::IReadableDataItems;
use crate::browser_drag_data_transfer_item::BrowserDragDataTransferItem;
use ferroui_base::input::platform::{
    ClipboardError, PlatformDataTransfer, PlatformDataTransferImpl, PlatformDataTransferItem,
};
use ferroui_base::input::DataFormat;
use std::cell::RefCell;
use std::rc::Rc;

/// Wraps an array of readable data items (a type of the script module) into
/// a data transfer. Synchronous only: used to read the drag-and-drop items.
pub(crate) struct BrowserDragDataTransfer {
    js_items: RefCell<Option<Rc<dyn IReadableDataItems>>>,
    // The items, created once: the formats of the data transfer are those of its items.
    items: RefCell<Option<Vec<Rc<PlatformDataTransferItem>>>>,
}

impl BrowserDragDataTransfer {
    pub(crate) fn new(js_items: Rc<dyn IReadableDataItems>) -> Rc<PlatformDataTransfer> {
        PlatformDataTransfer::new(Self { js_items: RefCell::new(Some(js_items)), items: RefCell::new(None) })
    }

    fn items(&self) -> Vec<Rc<PlatformDataTransferItem>> {
        if let Some(items) = self.items.borrow().as_ref() {
            return items.clone();
        }

        let items: Vec<Rc<PlatformDataTransferItem>> = match self.js_items.borrow().as_ref() {
            Some(js_items) => (0..js_items.len()).map(|i| BrowserDragDataTransferItem::new(js_items.get(i))).collect(),
            None => panic!("Cannot access a disposed object: BrowserDragDataTransfer"),
        };
        *self.items.borrow_mut() = Some(items.clone());
        items
    }
}

impl PlatformDataTransferImpl for BrowserDragDataTransfer {
    fn provide_formats(&self) -> Result<Vec<DataFormat>, ClipboardError> {
        let mut formats: Vec<DataFormat> = Vec::new();
        for item in self.items() {
            for format in item.try_formats()?.iter() {
                if !formats.contains(format) {
                    formats.push(format.clone());
                }
            }
        }
        Ok(formats)
    }

    fn provide_items(&self) -> Result<Vec<Rc<PlatformDataTransferItem>>, ClipboardError> {
        Ok(self.items())
    }

    fn dispose(&self, _owner: &PlatformDataTransfer) {
        // The objects of the page are released with the last reference to them.
        let js_items = self.js_items.borrow_mut().take();
        drop(js_items);
        let items = self.items.borrow_mut().take();
        drop(items);
    }
}