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