Skip to main content

iced_widget/
responsive.rs

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, Event, Length, Rectangle, Shell, Size, Vector, Widget};
8
9/// A widget that is aware of its dimensions.
10///
11/// A [`Responsive`] widget will always try to fill all the available space of
12/// its parent.
13pub struct Responsive<'a, W> {
14    view: Box<dyn Fn(Size) -> W + 'a>,
15    width: Length,
16    height: Length,
17    content: Option<W>,
18}
19
20impl<'a, W> Responsive<'a, W> {
21    /// Creates a new [`Responsive`] widget with a closure that produces its
22    /// contents.
23    ///
24    /// The `view` closure will receive the maximum available space for
25    /// the [`Responsive`] during layout. You can use this [`Size`] to
26    /// conditionally build the contents.
27    pub fn new(view: impl Fn(Size) -> W + 'a) -> Self {
28        Self {
29            view: Box::new(view),
30            width: Length::Fill,
31            height: Length::Fill,
32            content: None,
33        }
34    }
35
36    /// Sets the width of the [`Responsive`].
37    pub fn width(mut self, width: impl Into<Length>) -> Self {
38        self.width = width.into();
39        self
40    }
41
42    /// Sets the height of the [`Responsive`].
43    pub fn height(mut self, height: impl Into<Length>) -> Self {
44        self.height = height.into();
45        self
46    }
47}
48
49impl<W> widget::Meta for Responsive<'_, W> {}
50
51impl<W, Message, Theme, Renderer> Widget<Message, Theme, Renderer> for Responsive<'_, W>
52where
53    Renderer: core::Renderer,
54    W: Widget<Message, Theme, Renderer>,
55{
56    fn diff(&mut self, _tree: &mut Tree) {
57        // Diff is deferred to layout
58    }
59
60    fn size(&self) -> Size<Length> {
61        Size {
62            width: self.width,
63            height: self.height,
64        }
65    }
66
67    fn layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits) {
68        let limits = limits.width(self.width).height(self.height);
69        let size = limits.bounds();
70
71        self.content = Some((self.view)(size));
72        tree.diff_children(std::slice::from_mut(&mut self.content));
73
74        self.content
75            .layout(&mut tree.children[0], renderer, &limits.loose());
76
77        tree.size = limits.resolve(self.width, self.height, tree.children[0].size);
78    }
79
80    fn update(
81        &mut self,
82        tree: &mut Tree,
83        event: &Event,
84        layout: Layout,
85        cursor: mouse::Cursor,
86        renderer: &Renderer,
87        shell: &mut Shell<'_, Message>,
88        viewport: &Rectangle,
89    ) {
90        let (layout, tree) = layout.iter_mut(&mut tree.children).next().unwrap();
91
92        self.content
93            .update(tree, event, layout, cursor, renderer, shell, viewport);
94    }
95
96    fn draw(
97        &self,
98        tree: &Tree,
99        renderer: &mut Renderer,
100        theme: &Theme,
101        style: &renderer::Style,
102        layout: Layout,
103        cursor: mouse::Cursor,
104        viewport: &Rectangle,
105    ) {
106        let (layout, tree) = layout.iter(&tree.children).next().unwrap();
107
108        self.content
109            .draw(tree, renderer, theme, style, layout, cursor, viewport);
110    }
111
112    fn mouse_interaction(
113        &self,
114        tree: &Tree,
115        layout: Layout,
116        cursor: mouse::Cursor,
117        viewport: &Rectangle,
118        renderer: &Renderer,
119    ) -> mouse::Interaction {
120        let (layout, tree) = layout.iter(&tree.children).next().unwrap();
121
122        self.content
123            .mouse_interaction(tree, layout, cursor, viewport, renderer)
124    }
125
126    fn operate(
127        &mut self,
128        tree: &mut Tree,
129        layout: Layout,
130        viewport: &Rectangle,
131        renderer: &Renderer,
132        operation: &mut dyn widget::Operation,
133    ) {
134        let (layout, tree) = layout.iter_mut(&mut tree.children).next().unwrap();
135
136        self.content
137            .operate(tree, layout, viewport, renderer, operation);
138    }
139
140    fn overlay<'a>(
141        &'a mut self,
142        tree: &'a mut Tree,
143        layout: Layout,
144        renderer: &Renderer,
145        viewport: &Rectangle,
146        translation: Vector,
147        window: Size,
148    ) -> Vec<overlay::Element<'a, Message, Theme, Renderer>> {
149        let (layout, tree) = layout.iter_mut(&mut tree.children).next().unwrap();
150
151        self.content
152            .overlay(tree, layout, renderer, viewport, translation, window)
153    }
154}