cosmic/widget/
wrapper.rs

1use std::{
2    borrow::Borrow,
3    cell::RefCell,
4    rc::Rc,
5    thread::{self, ThreadId},
6};
7
8use crate::Element;
9use iced::{Length, Rectangle, Size, event};
10use iced_core::{Widget, id::Id, widget, widget::tree};
11
12#[derive(Debug)]
13pub struct RcWrapper<T> {
14    pub(crate) data: Rc<RefCell<T>>,
15    pub(crate) thread_id: ThreadId,
16}
17
18impl<T: Default> Default for RcWrapper<T> {
19    fn default() -> Self {
20        Self::new(T::default())
21    }
22}
23
24impl<T> Clone for RcWrapper<T> {
25    fn clone(&self) -> Self {
26        Self {
27            data: self.data.clone(),
28            thread_id: self.thread_id,
29        }
30    }
31}
32
33unsafe impl<M: 'static> Send for RcWrapper<M> {}
34unsafe impl<M: 'static> Sync for RcWrapper<M> {}
35
36impl<T> RcWrapper<T> {
37    pub fn new(element: T) -> Self {
38        Self {
39            data: Rc::new(RefCell::new(element)),
40            thread_id: thread::current().id(),
41        }
42    }
43
44    /// # Panics
45    ///
46    /// Will panic if used outside of original thread.
47    pub fn with_data<O>(&self, f: impl FnOnce(&T) -> O) -> O {
48        assert_eq!(self.thread_id, thread::current().id());
49        let my_ref: &T = &RefCell::borrow(self.data.as_ref());
50        f(my_ref)
51    }
52
53    /// # Panics
54    ///
55    /// Will panic if used outside of original thread.
56    pub fn with_data_mut<O>(&self, f: impl FnOnce(&mut T) -> O) -> O {
57        assert_eq!(self.thread_id, thread::current().id());
58        let my_refmut: &mut T = &mut RefCell::borrow_mut(self.data.as_ref());
59        f(my_refmut)
60    }
61
62    /// # Panics
63    ///
64    /// Will panic if used outside of original thread.
65    pub(crate) unsafe fn as_ptr(&self) -> *mut T {
66        assert_eq!(self.thread_id, thread::current().id());
67        RefCell::as_ptr(self.data.as_ref())
68    }
69}
70
71#[derive(Clone)]
72pub struct RcElementWrapper<M> {
73    pub(crate) element: RcWrapper<Element<'static, M>>,
74}
75
76impl<M> RcElementWrapper<M> {
77    #[must_use]
78    pub fn new(element: Element<'static, M>) -> Self {
79        RcElementWrapper {
80            element: RcWrapper::new(element),
81        }
82    }
83}
84
85impl<M: 'static> Borrow<dyn Widget<M, crate::Theme, crate::Renderer>> for RcElementWrapper<M> {
86    fn borrow(&self) -> &(dyn Widget<M, crate::Theme, crate::Renderer> + 'static) {
87        self
88    }
89}
90
91impl<M> Widget<M, crate::Theme, crate::Renderer> for RcElementWrapper<M> {
92    fn size(&self) -> Size<Length> {
93        self.element.with_data(|e| e.as_widget().size())
94    }
95
96    fn size_hint(&self) -> Size<Length> {
97        self.element.with_data(move |e| e.as_widget().size_hint())
98    }
99
100    fn layout(
101        &self,
102        tree: &mut tree::Tree,
103        renderer: &crate::Renderer,
104        limits: &crate::iced_core::layout::Limits,
105    ) -> crate::iced_core::layout::Node {
106        self.element
107            .with_data_mut(|e| e.as_widget_mut().layout(tree, renderer, limits))
108    }
109
110    fn draw(
111        &self,
112        tree: &tree::Tree,
113        renderer: &mut crate::Renderer,
114        theme: &crate::Theme,
115        style: &crate::iced_core::renderer::Style,
116        layout: crate::iced_core::Layout<'_>,
117        cursor: crate::iced_core::mouse::Cursor,
118        viewport: &Rectangle,
119    ) {
120        self.element.with_data(move |e| {
121            e.as_widget()
122                .draw(tree, renderer, theme, style, layout, cursor, viewport);
123        });
124    }
125
126    fn tag(&self) -> tree::Tag {
127        self.element.with_data(|e| e.as_widget().tag())
128    }
129
130    fn state(&self) -> tree::State {
131        self.element.with_data(|e| e.as_widget().state())
132    }
133
134    fn children(&self) -> Vec<tree::Tree> {
135        self.element.with_data(|e| e.as_widget().children())
136    }
137
138    fn diff(&mut self, tree: &mut tree::Tree) {
139        self.element.with_data_mut(|e| e.as_widget_mut().diff(tree));
140    }
141
142    fn operate(
143        &self,
144        state: &mut tree::Tree,
145        layout: crate::iced_core::Layout<'_>,
146        renderer: &crate::Renderer,
147        operation: &mut dyn widget::Operation,
148    ) {
149        self.element.with_data(|e| {
150            e.as_widget().operate(state, layout, renderer, operation);
151        });
152    }
153
154    fn on_event(
155        &mut self,
156        state: &mut tree::Tree,
157        event: crate::iced::Event,
158        layout: crate::iced_core::Layout<'_>,
159        cursor: crate::iced_core::mouse::Cursor,
160        renderer: &crate::Renderer,
161        clipboard: &mut dyn crate::iced_core::Clipboard,
162        shell: &mut crate::iced_core::Shell<'_, M>,
163        viewport: &Rectangle,
164    ) -> event::Status {
165        self.element.with_data_mut(|e| {
166            e.as_widget_mut().on_event(
167                state, event, layout, cursor, renderer, clipboard, shell, viewport,
168            )
169        })
170    }
171
172    fn mouse_interaction(
173        &self,
174        state: &tree::Tree,
175        layout: crate::iced_core::Layout<'_>,
176        cursor: crate::iced_core::mouse::Cursor,
177        viewport: &Rectangle,
178        renderer: &crate::Renderer,
179    ) -> crate::iced_core::mouse::Interaction {
180        self.element.with_data(|e| {
181            e.as_widget()
182                .mouse_interaction(state, layout, cursor, viewport, renderer)
183        })
184    }
185
186    fn overlay<'a>(
187        &'a mut self,
188        state: &'a mut tree::Tree,
189        layout: crate::iced_core::Layout<'_>,
190        renderer: &crate::Renderer,
191        translation: crate::iced_core::Vector,
192    ) -> Option<crate::iced_core::overlay::Element<'a, M, crate::Theme, crate::Renderer>> {
193        assert_eq!(self.element.thread_id, thread::current().id());
194        Rc::get_mut(&mut self.element.data).and_then(|e| {
195            e.get_mut()
196                .as_widget_mut()
197                .overlay(state, layout, renderer, translation)
198        })
199    }
200
201    fn id(&self) -> Option<Id> {
202        self.element.with_data_mut(|e| e.as_widget_mut().id())
203    }
204
205    fn set_id(&mut self, id: Id) {
206        self.element.with_data_mut(|e| e.as_widget_mut().set_id(id));
207    }
208
209    fn drag_destinations(
210        &self,
211        state: &tree::Tree,
212        layout: crate::iced_core::Layout<'_>,
213        renderer: &crate::Renderer,
214        dnd_rectangles: &mut crate::iced_core::clipboard::DndDestinationRectangles,
215    ) {
216        self.element.with_data_mut(|e| {
217            e.as_widget_mut()
218                .drag_destinations(state, layout, renderer, dnd_rectangles);
219        });
220    }
221}
222
223impl<Message: 'static> From<RcElementWrapper<Message>> for Element<'static, Message> {
224    fn from(wrapper: RcElementWrapper<Message>) -> Self {
225        Element::new(wrapper)
226    }
227}
228
229impl<Message: 'static> From<Element<'static, Message>> for RcElementWrapper<Message> {
230    fn from(e: Element<'static, Message>) -> Self {
231        RcElementWrapper::new(e)
232    }
233}