Skip to main content

cosmic/widget/
layer_container.rs

1use crate::Theme;
2use cosmic_theme::LayeredTheme;
3use iced::widget::Container;
4use iced_core::event::{self, Event};
5use iced_core::widget::Tree;
6use iced_core::{
7    Alignment, Clipboard, Element, Layout, Length, Padding, Rectangle, Shell, Vector, Widget,
8    layout, mouse, overlay, renderer,
9};
10pub use iced_widget::container::{Catalog, Style};
11
12pub fn layer_container<'a, Message: 'static, E>(
13    content: E,
14) -> LayerContainer<'a, Message, crate::Renderer>
15where
16    E: Into<Element<'a, Message, Theme, crate::Renderer>>,
17{
18    LayerContainer::new(content)
19}
20
21/// An element decorating some content.
22///
23/// It is normally used for alignment purposes.
24#[allow(missing_debug_implementations)]
25pub struct LayerContainer<'a, Message, Renderer>
26where
27    Renderer: iced_core::Renderer,
28{
29    layer: Option<cosmic_theme::Layer>,
30    container: Container<'a, Message, Theme, Renderer>,
31}
32
33impl<'a, Message, Renderer> LayerContainer<'a, Message, Renderer>
34where
35    Renderer: iced_core::Renderer,
36    // iced_widget::container::Style: From<crate::theme::Container>,
37{
38    /// Creates an empty [`Container`].
39    pub(crate) fn new<T>(content: T) -> Self
40    where
41        T: Into<Element<'a, Message, Theme, Renderer>>,
42    {
43        LayerContainer {
44            layer: None,
45            container: Container::new(content),
46        }
47    }
48
49    /// Sets the [`Layer`] of the [`LayerContainer`].
50    #[must_use]
51    pub fn layer(mut self, layer: cosmic_theme::Layer) -> Self {
52        self.layer = Some(layer);
53        self.class(match layer {
54            cosmic_theme::Layer::Background => crate::theme::Container::Background,
55            cosmic_theme::Layer::Primary => crate::theme::Container::Primary,
56            cosmic_theme::Layer::Secondary => crate::theme::Container::Secondary,
57        })
58    }
59
60    /// Sets the [`Padding`] of the [`LayerContainer`].
61    #[must_use]
62    pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
63        self.container = self.container.padding(padding);
64        self
65    }
66
67    /// Sets the width of the [`self.`].
68    #[must_use]
69    #[inline]
70    pub fn width(mut self, width: Length) -> Self {
71        self.container = self.container.width(width);
72        self
73    }
74
75    /// Sets the height of the [`LayerContainer`].
76    #[must_use]
77    #[inline]
78    pub fn height(mut self, height: Length) -> Self {
79        self.container = self.container.height(height);
80        self
81    }
82
83    /// Sets the maximum width of the [`LayerContainer`].
84    #[must_use]
85    #[inline]
86    pub fn max_width(mut self, max_width: f32) -> Self {
87        self.container = self.container.max_width(max_width);
88        self
89    }
90
91    /// Sets the maximum height of the [`LayerContainer`] in pixels.
92    #[must_use]
93    #[inline]
94    pub fn max_height(mut self, max_height: f32) -> Self {
95        self.container = self.container.max_height(max_height);
96        self
97    }
98
99    /// Sets the content alignment for the horizontal axis of the [`LayerContainer`].
100    #[must_use]
101    #[inline]
102    pub fn align_x(mut self, alignment: Alignment) -> Self {
103        self.container = self.container.align_x(alignment);
104        self
105    }
106
107    /// Sets the content alignment for the vertical axis of the [`LayerContainer`].
108    #[must_use]
109    #[inline]
110    pub fn align_y(mut self, alignment: Alignment) -> Self {
111        self.container = self.container.align_y(alignment);
112        self
113    }
114
115    /// Centers the contents in the horizontal axis of the [`LayerContainer`].
116    #[must_use]
117    #[inline]
118    pub fn center_x(mut self, width: Length) -> Self {
119        self.container = self.container.center_x(width);
120        self
121    }
122
123    /// Centers the contents in the vertical axis of the [`LayerContainer`].
124    #[must_use]
125    #[inline]
126    pub fn center_y(mut self, height: Length) -> Self {
127        self.container = self.container.center_y(height);
128        self
129    }
130
131    /// Centers the contents in the horizontal and vertical axis of the [`Container`].
132    #[must_use]
133    #[inline]
134    pub fn center(mut self, length: Length) -> Self {
135        self.container = self.container.center(length);
136        self
137    }
138
139    /// Sets the style of the [`LayerContainer`].
140    #[must_use]
141    pub fn class(mut self, style: impl Into<crate::style::iced::Container<'a>>) -> Self {
142        self.container = self.container.class(style);
143        self
144    }
145}
146
147impl<Message, Renderer> Widget<Message, Theme, Renderer> for LayerContainer<'_, Message, Renderer>
148where
149    Renderer: iced_core::Renderer,
150{
151    fn children(&self) -> Vec<Tree> {
152        self.container.children()
153    }
154
155    fn tag(&self) -> iced_core::widget::tree::Tag {
156        self.container.tag()
157    }
158
159    fn diff(&mut self, tree: &mut Tree) {
160        self.container.diff(tree);
161    }
162
163    fn state(&self) -> iced_core::widget::tree::State {
164        self.container.state()
165    }
166
167    fn size(&self) -> iced_core::Size<Length> {
168        self.container.size()
169    }
170
171    fn layout(
172        &mut self,
173        tree: &mut Tree,
174        renderer: &Renderer,
175        limits: &layout::Limits,
176    ) -> layout::Node {
177        self.container.layout(tree, renderer, limits)
178    }
179
180    fn operate(
181        &mut self,
182        tree: &mut Tree,
183        layout: Layout<'_>,
184        renderer: &Renderer,
185        operation: &mut dyn iced_core::widget::Operation<()>,
186    ) {
187        self.container.operate(tree, layout, renderer, operation);
188    }
189
190    fn update(
191        &mut self,
192        tree: &mut Tree,
193        event: &Event,
194        layout: Layout<'_>,
195        cursor_position: mouse::Cursor,
196        renderer: &Renderer,
197        clipboard: &mut dyn Clipboard,
198        shell: &mut Shell<'_, Message>,
199        viewport: &Rectangle,
200    ) {
201        self.container.update(
202            tree,
203            event,
204            layout,
205            cursor_position,
206            renderer,
207            clipboard,
208            shell,
209            viewport,
210        )
211    }
212
213    fn mouse_interaction(
214        &self,
215        tree: &Tree,
216        layout: Layout<'_>,
217        cursor_position: mouse::Cursor,
218        viewport: &Rectangle,
219        renderer: &Renderer,
220    ) -> mouse::Interaction {
221        self.container
222            .mouse_interaction(tree, layout, cursor_position, viewport, renderer)
223    }
224
225    fn draw(
226        &self,
227        tree: &Tree,
228        renderer: &mut Renderer,
229        theme: &Theme,
230        renderer_style: &renderer::Style,
231        layout: Layout<'_>,
232        cursor_position: mouse::Cursor,
233        viewport: &Rectangle,
234    ) {
235        let theme = if let Some(layer) = self.layer {
236            let mut theme = theme.clone();
237            theme.set_layer(layer);
238            theme
239        } else {
240            theme.clone()
241        };
242
243        self.container.draw(
244            tree,
245            renderer,
246            &theme,
247            renderer_style,
248            layout,
249            cursor_position,
250            viewport,
251        );
252    }
253
254    fn overlay<'b>(
255        &'b mut self,
256        tree: &'b mut Tree,
257        layout: Layout<'b>,
258        renderer: &Renderer,
259        viewport: &Rectangle,
260        translation: Vector,
261    ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
262        self.container
263            .overlay(tree, layout, renderer, viewport, translation)
264    }
265
266    fn drag_destinations(
267        &self,
268        state: &Tree,
269        layout: Layout<'_>,
270        renderer: &Renderer,
271        dnd_rectangles: &mut iced_core::clipboard::DndDestinationRectangles,
272    ) {
273        self.container
274            .drag_destinations(state, layout, renderer, dnd_rectangles);
275    }
276
277    fn id(&self) -> Option<crate::widget::Id> {
278        Widget::id(&self.container)
279    }
280
281    fn set_id(&mut self, id: crate::widget::Id) {
282        self.container.set_id(id);
283    }
284
285    #[cfg(feature = "a11y")]
286    /// get the a11y nodes for the widget
287    fn a11y_nodes(
288        &self,
289        layout: iced_core::Layout<'_>,
290        state: &Tree,
291        p: iced::mouse::Cursor,
292    ) -> iced_accessibility::A11yTree {
293        self.container.a11y_nodes(layout, state, p)
294    }
295}
296
297impl<'a, Message, Renderer> From<LayerContainer<'a, Message, Renderer>>
298    for Element<'a, Message, Theme, Renderer>
299where
300    Message: 'a,
301    Renderer: 'a + iced_core::Renderer,
302{
303    fn from(
304        column: LayerContainer<'a, Message, Renderer>,
305    ) -> Element<'a, Message, Theme, Renderer> {
306        Element::new(column)
307    }
308}