1pub mod action;
5#[cfg(wayland_platform)]
6pub mod corner_radius;
7
8use iced::{Limits, Size, Task};
9use std::any::Any;
10use std::sync::Arc;
11
12type BoxedSetting = Arc<Box<dyn Any + Send + Sync + 'static>>;
13
14pub type View<M> =
18 Arc<dyn Fn() -> crate::Element<'static, crate::Action<M>> + Send + Sync + 'static>;
19
20#[derive(Clone)]
25pub enum Action<M> {
26 AppSubsurface(BoxedSetting, BoxedSetting, Option<BoxedSetting>),
28 Subsurface(BoxedSetting, BoxedSetting, Option<View<M>>),
30 DestroySubsurface(iced::window::Id),
32 AppPopup(BoxedSetting, BoxedSetting, Option<BoxedSetting>),
34 Popup(BoxedSetting, BoxedSetting, Option<View<M>>),
36 DestroyPopup(iced::window::Id),
38 DestroyTooltipPopup,
40
41 AppWindow(
43 iced::window::Id,
44 BoxedSetting,
45 BoxedSetting,
46 Option<BoxedSetting>,
47 ),
48 Window(
50 iced::window::Id,
51 BoxedSetting,
52 BoxedSetting,
53 Option<View<M>>,
54 ),
55 DestroyWindow(iced::window::Id),
57
58 AppLayerShell(BoxedSetting, BoxedSetting, Option<BoxedSetting>),
60
61 LayerShell(BoxedSetting, BoxedSetting, Option<View<M>>),
63
64 DestroyLayerShell(iced::window::Id),
66
67 #[cfg(wayland_platform)]
68 Lock(
70 iced::window::Id,
71 cctk::wayland_client::protocol::wl_output::WlOutput,
72 BoxedSetting,
73 Option<View<M>>,
74 ),
75
76 DestroyLock(iced::window::Id),
78
79 ResponsiveMenuBar {
81 menu_bar: crate::widget::Id,
83 limits: Limits,
85 size: Size,
87 },
88 Ignore,
89 SyncLiveSettings(iced::window::Id),
90 Task(Arc<dyn Fn() -> Task<Action<M>> + Send + Sync>),
91}
92
93impl<M: 'static> Action<M> {
94 #[must_use]
99 pub fn map<N: 'static>(self, f: impl Fn(M) -> N + Clone + Send + Sync + 'static) -> Action<N> {
100 self.map_actions(move |action| action.map(f.clone()))
101 }
102
103 fn map_actions<N: 'static>(
104 self,
105 g: impl Fn(crate::Action<M>) -> crate::Action<N> + Clone + Send + Sync + 'static,
106 ) -> Action<N> {
107 let map_view = |view: Option<View<M>>| -> Option<View<N>> {
108 let view = view?;
109 let g = g.clone();
110 Some(Arc::new(move || view().map(g.clone())))
111 };
112 match self {
113 Action::AppSubsurface(a, b, c) => Action::AppSubsurface(a, b, c),
114 Action::Subsurface(a, b, view) => Action::Subsurface(a, b, map_view(view)),
115 Action::DestroySubsurface(id) => Action::DestroySubsurface(id),
116 Action::AppPopup(a, b, c) => Action::AppPopup(a, b, c),
117 Action::Popup(a, b, view) => Action::Popup(a, b, map_view(view)),
118 Action::DestroyPopup(id) => Action::DestroyPopup(id),
119 Action::DestroyTooltipPopup => Action::DestroyTooltipPopup,
120 Action::AppWindow(id, a, b, c) => Action::AppWindow(id, a, b, c),
121 Action::Window(id, a, b, view) => Action::Window(id, a, b, map_view(view)),
122 Action::DestroyWindow(id) => Action::DestroyWindow(id),
123 Action::AppLayerShell(a, b, c) => Action::AppLayerShell(a, b, c),
124 Action::LayerShell(a, b, view) => Action::LayerShell(a, b, map_view(view)),
125 Action::DestroyLayerShell(id) => Action::DestroyLayerShell(id),
126 #[cfg(wayland_platform)]
127 Action::Lock(id, output, a, view) => Action::Lock(id, output, a, map_view(view)),
128 Action::DestroyLock(id) => Action::DestroyLock(id),
129 Action::ResponsiveMenuBar {
130 menu_bar,
131 limits,
132 size,
133 } => Action::ResponsiveMenuBar {
134 menu_bar,
135 limits,
136 size,
137 },
138 Action::Ignore => Action::Ignore,
139 Action::SyncLiveSettings(id) => Action::SyncLiveSettings(id),
140 Action::Task(task) => Action::Task(Arc::new(move || {
141 let g = g.clone();
142 task().map(move |action| action.map_actions(g.clone()))
143 })),
144 }
145 }
146}
147
148impl<M: 'static> Action<crate::Action<M>> {
149 #[must_use]
150 pub fn flatten(self) -> Action<M> {
151 self.map_actions(crate::Action::flatten)
152 }
153}
154
155#[cfg(feature = "winit")]
156pub fn surface_task<M: Send + 'static>(action: Action<M>) -> Task<crate::Action<M>> {
157 crate::task::message(crate::Action::Surface(action))
158}
159
160impl<M> std::fmt::Debug for Action<M> {
161 #[cold]
162 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163 match self {
164 Self::AppSubsurface(arg0, arg1, arg2) => f
165 .debug_tuple("AppSubsurface")
166 .field(arg0)
167 .field(arg1)
168 .field(arg2)
169 .finish(),
170 Self::Subsurface(arg0, arg1, view) => f
171 .debug_tuple("Subsurface")
172 .field(arg0)
173 .field(arg1)
174 .field(&view.as_ref().map(|_| "view"))
175 .finish(),
176 Self::DestroySubsurface(arg0) => {
177 f.debug_tuple("DestroySubsurface").field(arg0).finish()
178 }
179 Self::AppPopup(arg0, arg1, arg2) => f
180 .debug_tuple("AppPopup")
181 .field(arg0)
182 .field(arg1)
183 .field(arg2)
184 .finish(),
185 Self::Popup(arg0, arg1, view) => f
186 .debug_tuple("Popup")
187 .field(arg0)
188 .field(arg1)
189 .field(&view.as_ref().map(|_| "view"))
190 .finish(),
191 Self::DestroyPopup(arg0) => f.debug_tuple("DestroyPopup").field(arg0).finish(),
192 Self::DestroyTooltipPopup => f.debug_tuple("DestroyTooltipPopup").finish(),
193 Self::ResponsiveMenuBar {
194 menu_bar,
195 limits,
196 size,
197 } => f
198 .debug_struct("ResponsiveMenuBar")
199 .field("menu_bar", menu_bar)
200 .field("limits", limits)
201 .field("size", size)
202 .finish(),
203 Self::Ignore => write!(f, "Ignore"),
204 Self::AppWindow(id, arg0, arg1, arg2) => f
205 .debug_tuple("AppWindow")
206 .field(id)
207 .field(arg0)
208 .field(arg1)
209 .field(arg2)
210 .finish(),
211 Self::Window(id, arg0, arg1, view) => f
212 .debug_tuple("Window")
213 .field(id)
214 .field(arg0)
215 .field(arg1)
216 .field(&view.as_ref().map(|_| "view"))
217 .finish(),
218 Self::DestroyWindow(arg0) => f.debug_tuple("DestroyWindow").field(arg0).finish(),
219 Self::Task(_) => f.debug_tuple("Future").finish(),
220 Self::AppLayerShell(arg, arg1, arg2) => f
221 .debug_tuple("AppLayerShell")
222 .field(arg)
223 .field(arg1)
224 .field(arg2)
225 .finish(),
226 Self::LayerShell(arg0, arg1, view) => f
227 .debug_tuple("LayerShell")
228 .field(arg0)
229 .field(arg1)
230 .field(&view.as_ref().map(|_| "view"))
231 .finish(),
232 Self::DestroyLayerShell(arg0) => {
233 f.debug_tuple("DestroyLayerShell").field(arg0).finish()
234 }
235 #[cfg(wayland_platform)]
236 Self::Lock(id, output, arg0, view) => f
237 .debug_tuple("Lock")
238 .field(id)
239 .field(output)
240 .field(arg0)
241 .field(&view.as_ref().map(|_| "view"))
242 .finish(),
243 Self::DestroyLock(arg0) => f.debug_tuple("DestroyLock").field(arg0).finish(),
244 Self::SyncLiveSettings(arg0) => f.debug_tuple("SyncLiveSettings").field(arg0).finish(),
245 }
246 }
247}