cosmic/widget/context_drawer/
overlay.rs1use 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, Size, mouse};
11use iced_core::{Renderer, touch};
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_mut()
33 .layout(self.tree, renderer, &limits);
34 let node_size = node.size();
35
36 node.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 update(
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 ) {
59 self.content.as_widget_mut().update(
60 self.tree,
61 event,
62 layout,
63 cursor,
64 renderer,
65 clipboard,
66 shell,
67 &layout.bounds(),
68 );
69 match event {
70 Event::Mouse(e) if !matches!(e, mouse::Event::CursorLeft) => {
71 if cursor.is_over(layout.bounds()) {
72 shell.capture_event();
73 }
74 }
75 Event::Touch(e) if !matches!(e, touch::Event::FingerLost { .. }) => {
76 if cursor.is_over(layout.bounds()) {
77 shell.capture_event();
78 }
79 }
80 _ => {}
81 }
82 }
83
84 fn draw(
85 &self,
86 renderer: &mut crate::Renderer,
87 theme: &crate::Theme,
88 style: &renderer::Style,
89 layout: Layout<'_>,
90 cursor: mouse::Cursor,
91 ) {
92 renderer.with_layer(layout.bounds(), |renderer| {
93 self.content.as_widget().draw(
94 self.tree,
95 renderer,
96 theme,
97 style,
98 layout,
99 cursor,
100 &layout.bounds(),
101 );
102 });
103 }
104
105 fn operate(
106 &mut self,
107 layout: Layout<'_>,
108 renderer: &crate::Renderer,
109 operation: &mut dyn Operation<()>,
110 ) {
111 self.content
112 .as_widget_mut()
113 .operate(self.tree, layout, renderer, operation);
114 }
115
116 fn mouse_interaction(
117 &self,
118 layout: Layout<'_>,
119 cursor: mouse::Cursor,
120 renderer: &crate::Renderer,
121 ) -> mouse::Interaction {
122 let viewport = &layout.bounds();
124 let interaction = self
125 .content
126 .as_widget()
127 .mouse_interaction(self.tree, layout, cursor, viewport, renderer);
128 if let mouse::Interaction::None = interaction
129 && cursor.is_over(layout.bounds())
130 {
131 return mouse::Interaction::Idle;
132 }
133 interaction
134 }
135
136 fn overlay<'c>(
137 &'c mut self,
138 layout: Layout<'c>,
139 renderer: &crate::Renderer,
140 ) -> Option<overlay::Element<'c, Message, crate::Theme, crate::Renderer>> {
141 let viewport = &layout.bounds();
142
143 self.content.as_widget_mut().overlay(
144 self.tree,
145 layout,
146 renderer,
147 viewport,
148 iced::Vector::default(),
149 )
150 }
151}