1use crate::core::layout;
23use crate::core::mouse;
24use crate::core::overlay;
25use crate::core::renderer;
26use crate::core::widget;
27use crate::core::{
28 self, Clipboard, Element, Event, Layout, Length, Pixels, Point, Rectangle,
29 Shell, Size, Vector, Widget,
30};
31
32#[allow(missing_debug_implementations)]
56pub struct Pin<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer>
57where
58 Renderer: core::Renderer,
59{
60 content: Element<'a, Message, Theme, Renderer>,
61 width: Length,
62 height: Length,
63 position: Point,
64}
65
66impl<'a, Message, Theme, Renderer> Pin<'a, Message, Theme, Renderer>
67where
68 Renderer: core::Renderer,
69{
70 pub fn new(
72 content: impl Into<Element<'a, Message, Theme, Renderer>>,
73 ) -> Self {
74 Self {
75 content: content.into(),
76 width: Length::Fill,
77 height: Length::Fill,
78 position: Point::ORIGIN,
79 }
80 }
81
82 pub fn width(mut self, width: impl Into<Length>) -> Self {
84 self.width = width.into();
85 self
86 }
87
88 pub fn height(mut self, height: impl Into<Length>) -> Self {
90 self.height = height.into();
91 self
92 }
93
94 pub fn position(mut self, position: impl Into<Point>) -> Self {
96 self.position = position.into();
97 self
98 }
99
100 pub fn x(mut self, x: impl Into<Pixels>) -> Self {
102 self.position.x = x.into().0;
103 self
104 }
105
106 pub fn y(mut self, y: impl Into<Pixels>) -> Self {
108 self.position.y = y.into().0;
109 self
110 }
111}
112
113impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
114 for Pin<'_, Message, Theme, Renderer>
115where
116 Renderer: core::Renderer,
117{
118 fn tag(&self) -> widget::tree::Tag {
119 self.content.as_widget().tag()
120 }
121
122 fn state(&self) -> widget::tree::State {
123 self.content.as_widget().state()
124 }
125
126 fn children(&self) -> Vec<widget::Tree> {
127 self.content.as_widget().children()
128 }
129
130 fn diff(&self, tree: &mut widget::Tree) {
131 self.content.as_widget().diff(tree);
132 }
133
134 fn size(&self) -> Size<Length> {
135 Size {
136 width: self.width,
137 height: self.height,
138 }
139 }
140
141 fn layout(
142 &self,
143 tree: &mut widget::Tree,
144 renderer: &Renderer,
145 limits: &layout::Limits,
146 ) -> layout::Node {
147 let limits = limits.width(self.width).height(self.height);
148
149 let available =
150 limits.max() - Size::new(self.position.x, self.position.y);
151
152 let node = self
153 .content
154 .as_widget()
155 .layout(tree, renderer, &layout::Limits::new(Size::ZERO, available))
156 .move_to(self.position);
157
158 let size = limits.resolve(self.width, self.height, node.size());
159 layout::Node::with_children(size, vec![node])
160 }
161
162 fn operate(
163 &self,
164 tree: &mut widget::Tree,
165 layout: Layout<'_>,
166 renderer: &Renderer,
167 operation: &mut dyn widget::Operation,
168 ) {
169 self.content.as_widget().operate(
170 tree,
171 layout.children().next().unwrap(),
172 renderer,
173 operation,
174 );
175 }
176
177 fn update(
178 &mut self,
179 tree: &mut widget::Tree,
180 event: &Event,
181 layout: Layout<'_>,
182 cursor: mouse::Cursor,
183 renderer: &Renderer,
184 clipboard: &mut dyn Clipboard,
185 shell: &mut Shell<'_, Message>,
186 viewport: &Rectangle,
187 ) {
188 self.content.as_widget_mut().update(
189 tree,
190 event,
191 layout.children().next().unwrap(),
192 cursor,
193 renderer,
194 clipboard,
195 shell,
196 viewport,
197 );
198 }
199
200 fn mouse_interaction(
201 &self,
202 tree: &widget::Tree,
203 layout: Layout<'_>,
204 cursor: mouse::Cursor,
205 viewport: &Rectangle,
206 renderer: &Renderer,
207 ) -> mouse::Interaction {
208 self.content.as_widget().mouse_interaction(
209 tree,
210 layout.children().next().unwrap(),
211 cursor,
212 viewport,
213 renderer,
214 )
215 }
216
217 fn draw(
218 &self,
219 tree: &widget::Tree,
220 renderer: &mut Renderer,
221 theme: &Theme,
222 style: &renderer::Style,
223 layout: Layout<'_>,
224 cursor: mouse::Cursor,
225 viewport: &Rectangle,
226 ) {
227 let bounds = layout.bounds();
228
229 if let Some(clipped_viewport) = bounds.intersection(viewport) {
230 self.content.as_widget().draw(
231 tree,
232 renderer,
233 theme,
234 style,
235 layout.children().next().unwrap(),
236 cursor,
237 &clipped_viewport,
238 );
239 }
240 }
241
242 fn overlay<'b>(
243 &'b mut self,
244 tree: &'b mut widget::Tree,
245 layout: Layout<'_>,
246 renderer: &Renderer,
247 translation: Vector,
248 ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
249 self.content.as_widget_mut().overlay(
250 tree,
251 layout.children().next().unwrap(),
252 renderer,
253 translation,
254 )
255 }
256}
257
258impl<'a, Message, Theme, Renderer> From<Pin<'a, Message, Theme, Renderer>>
259 for Element<'a, Message, Theme, Renderer>
260where
261 Message: 'a,
262 Theme: 'a,
263 Renderer: core::Renderer + 'a,
264{
265 fn from(
266 pin: Pin<'a, Message, Theme, Renderer>,
267 ) -> Element<'a, Message, Theme, Renderer> {
268 Element::new(pin)
269 }
270}