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