cosmic/widget/context_drawer/
overlay.rs

1// Copyright 2023 System76 <info@system76.com>
2// SPDX-License-Identifier: MPL-2.0
3
4use crate::Element;
5
6use iced::advanced::layout::{self, Layout};
7use iced::advanced::widget::{self, Operation};
8use iced::advanced::{Clipboard, Shell};
9use iced::advanced::{overlay, renderer};
10use iced::{Event, Point, Rectangle, Size, event, mouse};
11use iced_core::Renderer;
12
13pub(super) struct Overlay<'a, 'b, Message> {
14    pub(crate) position: Point,
15    pub(super) content: &'b mut Element<'a, Message>,
16    pub(super) tree: &'b mut widget::Tree,
17    pub(super) width: f32,
18}
19
20impl<Message> overlay::Overlay<Message, crate::Theme, crate::Renderer> for Overlay<'_, '_, Message>
21where
22    Message: Clone,
23{
24    fn layout(&mut self, renderer: &crate::Renderer, bounds: Size) -> layout::Node {
25        let position = self.position;
26        let limits = layout::Limits::new(Size::ZERO, bounds)
27            .width(self.width)
28            .height(bounds.height - 8.0 - position.y);
29
30        let node = self
31            .content
32            .as_widget()
33            .layout(self.tree, renderer, &limits);
34        let node_size = node.size();
35
36        node.clone().move_to(Point {
37            x: if bounds.width > node_size.width - 8.0 {
38                bounds.width - node_size.width - 8.0
39            } else {
40                0.0
41            },
42            y: if bounds.height > node_size.height - 8.0 {
43                bounds.height - node_size.height - 8.0
44            } else {
45                0.0
46            },
47        })
48    }
49
50    fn on_event(
51        &mut self,
52        event: Event,
53        layout: Layout<'_>,
54        cursor: mouse::Cursor,
55        renderer: &crate::Renderer,
56        clipboard: &mut dyn Clipboard,
57        shell: &mut Shell<'_, Message>,
58    ) -> event::Status {
59        self.content.as_widget_mut().on_event(
60            self.tree,
61            event,
62            layout,
63            cursor,
64            renderer,
65            clipboard,
66            shell,
67            &layout.bounds(),
68        )
69    }
70
71    fn draw(
72        &self,
73        renderer: &mut crate::Renderer,
74        theme: &crate::Theme,
75        style: &renderer::Style,
76        layout: Layout<'_>,
77        cursor: mouse::Cursor,
78    ) {
79        renderer.with_layer(layout.bounds(), |renderer| {
80            self.content.as_widget().draw(
81                self.tree,
82                renderer,
83                theme,
84                style,
85                layout,
86                cursor,
87                &layout.bounds(),
88            );
89        })
90    }
91
92    fn operate(
93        &mut self,
94        layout: Layout<'_>,
95        renderer: &crate::Renderer,
96        operation: &mut dyn Operation<()>,
97    ) {
98        self.content
99            .as_widget_mut()
100            .operate(self.tree, layout, renderer, operation);
101    }
102
103    fn mouse_interaction(
104        &self,
105        layout: Layout<'_>,
106        cursor: mouse::Cursor,
107        viewport: &Rectangle,
108        renderer: &crate::Renderer,
109    ) -> mouse::Interaction {
110        self.content
111            .as_widget()
112            .mouse_interaction(self.tree, layout, cursor, viewport, renderer)
113    }
114
115    fn overlay<'c>(
116        &'c mut self,
117        layout: Layout<'_>,
118        renderer: &crate::Renderer,
119    ) -> Option<overlay::Element<'c, Message, crate::Theme, crate::Renderer>> {
120        self.content
121            .as_widget_mut()
122            .overlay(self.tree, layout, renderer, iced::Vector::default())
123    }
124}