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