use std::{ borrow::Borrow, cell::RefCell, rc::Rc, thread::{self, ThreadId}, }; use crate::Element; use iced::{Length, Rectangle, Size, event}; use iced_core::{Widget, id::Id, widget, widget::tree}; #[derive(Debug)] pub struct RcWrapper { pub(crate) data: Rc>, pub(crate) thread_id: ThreadId, } impl Default for RcWrapper { fn default() -> Self { Self::new(T::default()) } } impl Clone for RcWrapper { fn clone(&self) -> Self { Self { data: self.data.clone(), thread_id: self.thread_id, } } } unsafe impl Send for RcWrapper {} unsafe impl Sync for RcWrapper {} impl RcWrapper { pub fn new(element: T) -> Self { Self { data: Rc::new(RefCell::new(element)), thread_id: thread::current().id(), } } /// # Panics /// /// Will panic if used outside of original thread. pub fn with_data(&self, f: impl FnOnce(&T) -> O) -> O { assert_eq!(self.thread_id, thread::current().id()); let my_ref: &T = &RefCell::borrow(self.data.as_ref()); f(my_ref) } /// # Panics /// /// Will panic if used outside of original thread. pub fn with_data_mut(&self, f: impl FnOnce(&mut T) -> O) -> O { assert_eq!(self.thread_id, thread::current().id()); let my_refmut: &mut T = &mut RefCell::borrow_mut(self.data.as_ref()); f(my_refmut) } } #[derive(Clone)] pub struct RcElementWrapper { pub(crate) element: RcWrapper>, } impl RcElementWrapper { #[must_use] pub fn new(element: Element<'static, M>) -> Self { RcElementWrapper { element: RcWrapper::new(element), } } } impl Borrow> for RcElementWrapper { fn borrow(&self) -> &(dyn Widget + 'static) { self } } impl Widget for RcElementWrapper { fn size(&self) -> Size { self.element.with_data(|e| e.as_widget().size()) } fn size_hint(&self) -> Size { self.element.with_data(move |e| e.as_widget().size_hint()) } fn layout( &self, tree: &mut tree::Tree, renderer: &crate::Renderer, limits: &crate::iced_core::layout::Limits, ) -> crate::iced_core::layout::Node { self.element .with_data_mut(|e| e.as_widget_mut().layout(tree, renderer, limits)) } fn draw( &self, tree: &tree::Tree, renderer: &mut crate::Renderer, theme: &crate::Theme, style: &crate::iced_core::renderer::Style, layout: crate::iced_core::Layout<'_>, cursor: crate::iced_core::mouse::Cursor, viewport: &Rectangle, ) { self.element.with_data(move |e| { e.as_widget() .draw(tree, renderer, theme, style, layout, cursor, viewport); }); } fn tag(&self) -> tree::Tag { self.element.with_data(|e| e.as_widget().tag()) } fn state(&self) -> tree::State { self.element.with_data(|e| e.as_widget().state()) } fn children(&self) -> Vec { self.element.with_data(|e| e.as_widget().children()) } fn diff(&mut self, tree: &mut tree::Tree) { self.element.with_data_mut(|e| e.as_widget_mut().diff(tree)); } fn operate( &self, state: &mut tree::Tree, layout: crate::iced_core::Layout<'_>, renderer: &crate::Renderer, operation: &mut dyn widget::Operation, ) { self.element.with_data(|e| { e.as_widget().operate(state, layout, renderer, operation); }); } fn on_event( &mut self, state: &mut tree::Tree, event: crate::iced::Event, layout: crate::iced_core::Layout<'_>, cursor: crate::iced_core::mouse::Cursor, renderer: &crate::Renderer, clipboard: &mut dyn crate::iced_core::Clipboard, shell: &mut crate::iced_core::Shell<'_, M>, viewport: &Rectangle, ) -> event::Status { self.element.with_data_mut(|e| { e.as_widget_mut().on_event( state, event, layout, cursor, renderer, clipboard, shell, viewport, ) }) } fn mouse_interaction( &self, state: &tree::Tree, layout: crate::iced_core::Layout<'_>, cursor: crate::iced_core::mouse::Cursor, viewport: &Rectangle, renderer: &crate::Renderer, ) -> crate::iced_core::mouse::Interaction { self.element.with_data(|e| { e.as_widget() .mouse_interaction(state, layout, cursor, viewport, renderer) }) } fn overlay<'a>( &'a mut self, state: &'a mut tree::Tree, layout: crate::iced_core::Layout<'_>, renderer: &crate::Renderer, translation: crate::iced_core::Vector, ) -> Option> { assert_eq!(self.element.thread_id, thread::current().id()); Rc::get_mut(&mut self.element.data).and_then(|e| { e.get_mut() .as_widget_mut() .overlay(state, layout, renderer, translation) }) } fn id(&self) -> Option { self.element.with_data_mut(|e| e.as_widget_mut().id()) } fn set_id(&mut self, id: Id) { self.element.with_data_mut(|e| e.as_widget_mut().set_id(id)); } fn drag_destinations( &self, state: &tree::Tree, layout: crate::iced_core::Layout<'_>, renderer: &crate::Renderer, dnd_rectangles: &mut crate::iced_core::clipboard::DndDestinationRectangles, ) { self.element.with_data_mut(|e| { e.as_widget_mut() .drag_destinations(state, layout, renderer, dnd_rectangles); }); } } impl From> for Element<'static, Message> { fn from(wrapper: RcElementWrapper) -> Self { Element::new(wrapper) } } impl From> for RcElementWrapper { fn from(e: Element<'static, Message>) -> Self { RcElementWrapper::new(e) } }