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 children(&self) -> Vec<widget::Tree> {
123 self.content.as_widget().children()
124 }
125
126 fn diff(&self, tree: &mut widget::Tree) {
127 self.content.as_widget().diff(tree);
128 }
129
130 fn size(&self) -> Size<Length> {
131 Size {
132 width: self.width,
133 height: self.height,
134 }
135 }
136
137 fn layout(
138 &mut self,
139 tree: &mut widget::Tree,
140 renderer: &Renderer,
141 limits: &layout::Limits,
142 ) -> layout::Node {
143 let limits = limits.width(self.width).height(self.height);
144
145 let available = limits.max() - Size::new(self.position.x, self.position.y);
146
147 let node = self
148 .content
149 .as_widget_mut()
150 .layout(tree, renderer, &layout::Limits::new(Size::ZERO, available))
151 .move_to(self.position);
152
153 let size = limits.resolve(self.width, self.height, node.size());
154 layout::Node::with_children(size, vec![node])
155 }
156
157 fn operate(
158 &mut self,
159 tree: &mut widget::Tree,
160 layout: Layout<'_>,
161 renderer: &Renderer,
162 operation: &mut dyn widget::Operation,
163 ) {
164 self.content.as_widget_mut().operate(
165 tree,
166 layout.children().next().unwrap(),
167 renderer,
168 operation,
169 );
170 }
171
172 fn update(
173 &mut self,
174 tree: &mut widget::Tree,
175 event: &Event,
176 layout: Layout<'_>,
177 cursor: mouse::Cursor,
178 renderer: &Renderer,
179 shell: &mut Shell<'_, Message>,
180 viewport: &Rectangle,
181 ) {
182 self.content.as_widget_mut().update(
183 tree,
184 event,
185 layout.children().next().unwrap(),
186 cursor,
187 renderer,
188 shell,
189 viewport,
190 );
191 }
192
193 fn mouse_interaction(
194 &self,
195 tree: &widget::Tree,
196 layout: Layout<'_>,
197 cursor: mouse::Cursor,
198 viewport: &Rectangle,
199 renderer: &Renderer,
200 ) -> mouse::Interaction {
201 self.content.as_widget().mouse_interaction(
202 tree,
203 layout.children().next().unwrap(),
204 cursor,
205 viewport,
206 renderer,
207 )
208 }
209
210 fn draw(
211 &self,
212 tree: &widget::Tree,
213 renderer: &mut Renderer,
214 theme: &Theme,
215 style: &renderer::Style,
216 layout: Layout<'_>,
217 cursor: mouse::Cursor,
218 viewport: &Rectangle,
219 ) {
220 let bounds = layout.bounds();
221
222 if let Some(clipped_viewport) = bounds.intersection(viewport) {
223 self.content.as_widget().draw(
224 tree,
225 renderer,
226 theme,
227 style,
228 layout.children().next().unwrap(),
229 cursor,
230 &clipped_viewport,
231 );
232 }
233 }
234
235 fn overlay<'b>(
236 &'b mut self,
237 tree: &'b mut widget::Tree,
238 layout: Layout<'b>,
239 renderer: &Renderer,
240 viewport: &Rectangle,
241 translation: Vector,
242 ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
243 self.content.as_widget_mut().overlay(
244 tree,
245 layout.children().next().unwrap(),
246 renderer,
247 viewport,
248 translation,
249 )
250 }
251}
252
253impl<'a, Message, Theme, Renderer> From<Pin<'a, Message, Theme, Renderer>>
254 for Element<'a, Message, Theme, Renderer>
255where
256 Message: 'a,
257 Theme: 'a,
258 Renderer: core::Renderer + 'a,
259{
260 fn from(pin: Pin<'a, Message, Theme, Renderer>) -> Element<'a, Message, Theme, Renderer> {
261 Element::new(pin)
262 }
263}