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 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 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 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}