cosmic/widget/
wrapper.rs

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