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