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 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 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
63#[derive(Clone)]
64pub struct RcElementWrapper<M> {
65 pub(crate) element: RcWrapper<Element<'static, M>>,
66}
67
68impl<M> RcElementWrapper<M> {
69 #[must_use]
70 pub fn new(element: Element<'static, M>) -> Self {
71 RcElementWrapper {
72 element: RcWrapper::new(element),
73 }
74 }
75}
76
77impl<M: 'static> Borrow<dyn Widget<M, crate::Theme, crate::Renderer>> for RcElementWrapper<M> {
78 fn borrow(&self) -> &(dyn Widget<M, crate::Theme, crate::Renderer> + 'static) {
79 self
80 }
81}
82
83impl<M> Widget<M, crate::Theme, crate::Renderer> for RcElementWrapper<M> {
84 fn size(&self) -> Size<Length> {
85 self.element.with_data(|e| e.as_widget().size())
86 }
87
88 fn size_hint(&self) -> Size<Length> {
89 self.element.with_data(move |e| e.as_widget().size_hint())
90 }
91
92 fn layout(
93 &mut self,
94 tree: &mut tree::Tree,
95 renderer: &crate::Renderer,
96 limits: &iced_core::layout::Limits,
97 ) -> iced_core::layout::Node {
98 self.element
99 .with_data_mut(|e| e.as_widget_mut().layout(tree, renderer, limits))
100 }
101
102 fn draw(
103 &self,
104 tree: &tree::Tree,
105 renderer: &mut crate::Renderer,
106 theme: &crate::Theme,
107 style: &iced_core::renderer::Style,
108 layout: iced_core::Layout<'_>,
109 cursor: iced_core::mouse::Cursor,
110 viewport: &Rectangle,
111 ) {
112 self.element.with_data(move |e| {
113 e.as_widget()
114 .draw(tree, renderer, theme, style, layout, cursor, viewport);
115 });
116 }
117
118 fn tag(&self) -> tree::Tag {
119 self.element.with_data(|e| e.as_widget().tag())
120 }
121
122 fn state(&self) -> tree::State {
123 self.element.with_data(|e| e.as_widget().state())
124 }
125
126 fn children(&self) -> Vec<tree::Tree> {
127 self.element.with_data(|e| e.as_widget().children())
128 }
129
130 fn diff(&mut self, tree: &mut tree::Tree) {
131 self.element.with_data_mut(|e| e.as_widget_mut().diff(tree));
132 }
133
134 fn operate(
135 &mut self,
136 state: &mut tree::Tree,
137 layout: iced_core::Layout<'_>,
138 renderer: &crate::Renderer,
139 operation: &mut dyn widget::Operation,
140 ) {
141 self.element.with_data_mut(|e| {
142 e.as_widget_mut()
143 .operate(state, layout, renderer, operation);
144 });
145 }
146
147 fn update(
148 &mut self,
149 state: &mut tree::Tree,
150 event: &crate::iced::Event,
151 layout: iced_core::Layout<'_>,
152 cursor: iced_core::mouse::Cursor,
153 renderer: &crate::Renderer,
154 clipboard: &mut dyn iced_core::Clipboard,
155 shell: &mut iced_core::Shell<'_, M>,
156 viewport: &Rectangle,
157 ) {
158 self.element.with_data_mut(|e| {
159 e.as_widget_mut().update(
160 state, event, layout, cursor, renderer, clipboard, shell, viewport,
161 )
162 })
163 }
164
165 fn mouse_interaction(
166 &self,
167 state: &tree::Tree,
168 layout: iced_core::Layout<'_>,
169 cursor: iced_core::mouse::Cursor,
170 viewport: &Rectangle,
171 renderer: &crate::Renderer,
172 ) -> iced_core::mouse::Interaction {
173 self.element.with_data(|e| {
174 e.as_widget()
175 .mouse_interaction(state, layout, cursor, viewport, renderer)
176 })
177 }
178
179 fn overlay<'a>(
180 &'a mut self,
181 state: &'a mut tree::Tree,
182 layout: iced_core::Layout<'a>,
183 renderer: &crate::Renderer,
184 viewport: &Rectangle,
185 translation: iced_core::Vector,
186 ) -> Option<iced_core::overlay::Element<'a, M, crate::Theme, crate::Renderer>> {
187 assert_eq!(self.element.thread_id, thread::current().id());
188 Rc::get_mut(&mut self.element.data).and_then(|e| {
189 e.get_mut()
190 .as_widget_mut()
191 .overlay(state, layout, renderer, viewport, translation)
192 })
193 }
194
195 fn id(&self) -> Option<Id> {
196 self.element.with_data_mut(|e| e.as_widget_mut().id())
197 }
198
199 fn set_id(&mut self, id: Id) {
200 self.element.with_data_mut(|e| e.as_widget_mut().set_id(id));
201 }
202
203 fn drag_destinations(
204 &self,
205 state: &tree::Tree,
206 layout: iced_core::Layout<'_>,
207 renderer: &crate::Renderer,
208 dnd_rectangles: &mut iced_core::clipboard::DndDestinationRectangles,
209 ) {
210 self.element.with_data_mut(|e| {
211 e.as_widget_mut()
212 .drag_destinations(state, layout, renderer, dnd_rectangles);
213 });
214 }
215}
216
217impl<Message: 'static> From<RcElementWrapper<Message>> for Element<'static, Message> {
218 fn from(wrapper: RcElementWrapper<Message>) -> Self {
219 Element::new(wrapper)
220 }
221}
222
223impl<Message: 'static> From<Element<'static, Message>> for RcElementWrapper<Message> {
224 fn from(e: Element<'static, Message>) -> Self {
225 RcElementWrapper::new(e)
226 }
227}