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