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