1use crate::core::layout::{self, Layout};
2use crate::core::mouse;
3use crate::core::overlay;
4use crate::core::renderer;
5use crate::core::widget;
6use crate::core::widget::Tree;
7use crate::core::{
8 self, Clipboard, Element, Event, Length, Rectangle, Shell, Size, Vector,
9 Widget,
10};
11use crate::space;
12
13pub struct Responsive<
18 'a,
19 Message,
20 Theme = crate::Theme,
21 Renderer = crate::Renderer,
22> {
23 view: Box<dyn Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a>,
24 width: Length,
25 height: Length,
26 content: Element<'a, Message, Theme, Renderer>,
27}
28
29impl<'a, Message, Theme, Renderer> Responsive<'a, Message, Theme, Renderer>
30where
31 Renderer: core::Renderer,
32{
33 pub fn new(
40 view: impl Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a,
41 ) -> Self {
42 Self {
43 view: Box::new(view),
44 width: Length::Fill,
45 height: Length::Fill,
46 content: Element::new(space()),
47 }
48 }
49
50 pub fn width(mut self, width: impl Into<Length>) -> Self {
52 self.width = width.into();
53 self
54 }
55
56 pub fn height(mut self, height: impl Into<Length>) -> Self {
58 self.height = height.into();
59 self
60 }
61}
62
63impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
64 for Responsive<'_, Message, Theme, Renderer>
65where
66 Renderer: core::Renderer,
67{
68 fn diff(&self, _tree: &mut Tree) {
69 }
71
72 fn size(&self) -> Size<Length> {
73 Size {
74 width: self.width,
75 height: self.height,
76 }
77 }
78
79 fn layout(
80 &mut self,
81 tree: &mut Tree,
82 renderer: &Renderer,
83 limits: &layout::Limits,
84 ) -> layout::Node {
85 let limits = limits.width(self.width).height(self.height);
86 let size = limits.max();
87
88 self.content = (self.view)(size);
89 tree.diff_children(std::slice::from_ref(&self.content));
90
91 let node = self.content.as_widget_mut().layout(
92 &mut tree.children[0],
93 renderer,
94 &limits.loose(),
95 );
96
97 let size = limits.resolve(self.width, self.height, node.size());
98
99 layout::Node::with_children(size, vec![node])
100 }
101
102 fn update(
103 &mut self,
104 tree: &mut Tree,
105 event: &Event,
106 layout: Layout<'_>,
107 cursor: mouse::Cursor,
108 renderer: &Renderer,
109 clipboard: &mut dyn Clipboard,
110 shell: &mut Shell<'_, Message>,
111 viewport: &Rectangle,
112 ) {
113 self.content.as_widget_mut().update(
114 &mut tree.children[0],
115 event,
116 layout.children().next().unwrap(),
117 cursor,
118 renderer,
119 clipboard,
120 shell,
121 viewport,
122 );
123 }
124
125 fn draw(
126 &self,
127 tree: &Tree,
128 renderer: &mut Renderer,
129 theme: &Theme,
130 style: &renderer::Style,
131 layout: Layout<'_>,
132 cursor: mouse::Cursor,
133 viewport: &Rectangle,
134 ) {
135 self.content.as_widget().draw(
136 &tree.children[0],
137 renderer,
138 theme,
139 style,
140 layout.children().next().unwrap(),
141 cursor,
142 viewport,
143 );
144 }
145
146 fn mouse_interaction(
147 &self,
148 tree: &Tree,
149 layout: Layout<'_>,
150 cursor: mouse::Cursor,
151 viewport: &Rectangle,
152 renderer: &Renderer,
153 ) -> mouse::Interaction {
154 self.content.as_widget().mouse_interaction(
155 &tree.children[0],
156 layout.children().next().unwrap(),
157 cursor,
158 viewport,
159 renderer,
160 )
161 }
162
163 fn operate(
164 &mut self,
165 tree: &mut Tree,
166 layout: Layout<'_>,
167 renderer: &Renderer,
168 operation: &mut dyn widget::Operation,
169 ) {
170 self.content.as_widget_mut().operate(
171 &mut tree.children[0],
172 layout.children().next().unwrap(),
173 renderer,
174 operation,
175 );
176 }
177
178 fn overlay<'a>(
179 &'a mut self,
180 tree: &'a mut Tree,
181 layout: Layout<'a>,
182 renderer: &Renderer,
183 viewport: &Rectangle,
184 translation: Vector,
185 ) -> Option<overlay::Element<'a, Message, Theme, Renderer>> {
186 self.content.as_widget_mut().overlay(
187 &mut tree.children[0],
188 layout.children().next().unwrap(),
189 renderer,
190 viewport,
191 translation,
192 )
193 }
194}
195
196impl<'a, Message, Theme, Renderer>
197 From<Responsive<'a, Message, Theme, Renderer>>
198 for Element<'a, Message, Theme, Renderer>
199where
200 Message: 'a,
201 Theme: 'a,
202 Renderer: core::Renderer + 'a,
203{
204 fn from(responsive: Responsive<'a, Message, Theme, Renderer>) -> Self {
205 Self::new(responsive)
206 }
207}