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