pebble_skip/user_interface/window/
mod.rs1use super::window_stack;
2use crate::{graphics::graphics_types::Color8, Box, Handle, SpecialDrop};
3use core::{
4 marker::PhantomData,
5 mem::ManuallyDrop,
6 ops::{Deref, DerefMut},
7};
8use debugless_unwrap::DebuglessUnwrapNone as _;
9#[allow(clippy::wildcard_imports)]
10use pebble_sys::{
11 standard_c::memory::void,
12 user_interface::window::{Window as sysWindow, WindowHandlers as sysWindowHandlers, *},
13};
14use unsafe_unwrap::UnsafeUnwrap;
15
16pub mod number_window;
17
18#[repr(transparent)] pub struct Window<T: ?Sized>(pub(crate) Handle<'static, sysWindow>, PhantomData<T>);
20
21#[repr(transparent)]
22pub struct WindowRef<'a>(Handle<'a, sysWindow>);
23
24#[repr(transparent)]
25pub struct WindowRefMut<'a>(Handle<'a, sysWindow>);
26
27pub struct WindowHandlers<L: FnMut() -> T, A: FnMut(&mut T), D: FnMut(&mut T), U: FnMut(T), T> {
28 pub load: L,
29 pub appear: A,
30 pub disappear: D,
31 pub unload: U,
32}
33
34trait WindowHandlersTrait<T> {
35 fn load(&mut self) -> T;
36 fn appear(&mut self, data: &mut T);
37 fn disappear(&mut self, data: &mut T);
38 fn unload(&mut self, data: T);
39}
40
41impl<L: FnMut() -> T, A: FnMut(&mut T), D: FnMut(&mut T), U: FnMut(T), T> WindowHandlersTrait<T>
42 for WindowHandlers<L, A, D, U, T>
43{
44 fn load(&mut self) -> T {
45 (self.load)()
46 }
47
48 fn appear(&mut self, data: &mut T) {
49 (self.appear)(data)
50 }
51
52 fn disappear(&mut self, data: &mut T) {
53 (self.disappear)(data)
54 }
55
56 fn unload(&mut self, data: T) {
57 (self.unload)(data)
58 }
59}
60
61struct WindowData<'a, T> {
62 user_data: Option<T>,
63 window_handlers: Box<'a, dyn 'a + WindowHandlersTrait<T>>,
64}
65
66pub struct WindowCreationError<L: FnMut() -> T, A: FnMut(&mut T), D: FnMut(&mut T), U: FnMut(T), T>
67{
68 pub window_handlers: WindowHandlers<L, A, D, U, T>,
69}
70
71impl<T> Window<T> {
72 pub fn new<
81 'a,
82 L: 'a + FnMut() -> T,
83 A: 'a + FnMut(&mut T),
84 D: 'a + FnMut(&mut T),
85 U: 'a + FnMut(T),
86 >(
87 window_handlers: WindowHandlers<L, A, D, U, T>,
88 ) -> Result<Self, WindowCreationError<L, A, D, U, T>>
89 where
90 T: 'a,
91 {
92 #![allow(clippy::items_after_statements)]
93
94 let window_data = Box::new(WindowData {
95 user_data: None,
96 window_handlers: Box::new(window_handlers)
97 .map_err(|window_handlers| WindowCreationError { window_handlers })?,
98 })
99 .map_err(|window_data| WindowCreationError::<_, _, _, _, T> {
100 window_handlers: Box::into_inner(unsafe {
101 Box::downcast_unchecked(window_data.window_handlers)
102 }),
103 })?;
104 let raw_window = match unsafe { window_create() } {
105 Some(raw_window) => raw_window,
106 None => {
107 return Err(WindowCreationError {
108 window_handlers: Box::into_inner(unsafe {
109 Box::downcast_unchecked(Box::into_inner(window_data).window_handlers)
110 }),
111 });
112 }
113 };
114
115 extern "C" fn raw_load<T>(raw_window: &mut sysWindow) {
116 let window_data = unsafe {
117 window_get_user_data(raw_window)
118 .cast::<WindowData<T>>()
119 .as_mut()
120 .unsafe_unwrap()
121 };
122 window_data
123 .user_data
124 .replace(window_data.window_handlers.load())
125 .debugless_unwrap_none();
126 }
127 extern "C" fn raw_appear<T>(raw_window: &mut sysWindow) {
128 let window_data = unsafe {
129 window_get_user_data(raw_window)
130 .cast::<WindowData<T>>()
131 .as_mut()
132 .unsafe_unwrap()
133 };
134 window_data
135 .window_handlers
136 .appear(unsafe { window_data.user_data.as_mut().unsafe_unwrap() });
137 }
138 extern "C" fn raw_disappear<T>(raw_window: &mut sysWindow) {
139 let window_data = unsafe {
140 window_get_user_data(raw_window)
141 .cast::<WindowData<T>>()
142 .as_mut()
143 .unsafe_unwrap()
144 };
145 window_data
146 .window_handlers
147 .disappear(unsafe { window_data.user_data.as_mut().unsafe_unwrap() });
148 }
149 extern "C" fn raw_unload<T>(raw_window: &mut sysWindow) {
150 let window_data = unsafe {
151 window_get_user_data(raw_window)
152 .cast::<WindowData<T>>()
153 .as_mut()
154 .unsafe_unwrap()
155 };
156 window_data
157 .window_handlers
158 .unload(unsafe { window_data.user_data.take().unsafe_unwrap() });
159 }
160
161 unsafe {
162 window_set_user_data(raw_window, {
164 let mem: &mut void = Box::leak(window_data).into();
165 mem
166 });
167 window_set_window_handlers(
168 raw_window,
169 sysWindowHandlers {
170 load: Some(raw_load::<T>),
171 appear: Some(raw_appear::<T>),
172 disappear: Some(raw_disappear::<T>),
173 unload: Some(raw_unload::<T>),
174 },
175 )
176 }
177 Ok(Self(Handle::new(raw_window), PhantomData))
178 }
179
180 pub unsafe fn from_raw(raw_window: &'static mut sysWindow) -> Self {
191 Self(Handle::new(raw_window), PhantomData)
192 }
193
194 #[must_use = "Not reassembling the `Window<T>` later causes a memory leak."]
200 pub fn leak(self) -> &'static mut sysWindow
201 where
202 T: 'static,
203 {
204 unsafe { ManuallyDrop::new(self).0.duplicate().unwrap() }
205 }
206}
207
208impl<T: ?Sized> Window<T> {
209 #[allow(clippy::must_use_candidate)] pub fn hide(&self, animated: bool) -> bool {
211 window_stack::remove(self, animated)
212 }
213
214 #[must_use]
215 pub fn is_loaded(&self) -> bool {
216 unsafe { window_is_loaded(self.0.as_mut_unchecked()) }
219 }
220
221 pub fn show(&self, animated: bool) {
227 window_stack::push(self, animated)
228 }
229
230 pub fn set_background_color(&self, background_color: Color8) {
231 unsafe { window_set_background_color(self.0.as_mut_unchecked(), background_color) }
232 }
233}
234
235impl<T: ?Sized> Drop for Window<T> {
236 fn drop(&mut self) {
237 self.special_drop()
238 }
239}
240
241impl<T: ?Sized> SpecialDrop for Window<T> {
242 default fn special_drop(&mut self) {
243 panic!("Dropping unsized `Window<T>`s is illegal")
244 }
245}
246
247impl<T: Sized> SpecialDrop for Window<T> {
248 fn special_drop(&mut self) {
249 unsafe {
250 let window_data = window_get_user_data(&*self.0).cast();
253 window_destroy(self.0.duplicate().unwrap());
254 Box::<WindowData<T>>::from_raw(&mut *window_data);
255 }
256 }
257}
258
259impl<'a> Deref for WindowRef<'a> {
260 type Target = Window<void>;
261
262 fn deref(&self) -> &Self::Target {
263 unsafe { &*(self as *const _ as *const Window<void>) }
265 }
266}
267
268impl<'a> Deref for WindowRefMut<'a> {
269 type Target = Window<void>;
270
271 fn deref(&self) -> &Self::Target {
272 unsafe { &*(self as *const _ as *const Window<void>) }
274 }
275}
276
277impl<'a> DerefMut for WindowRefMut<'a> {
278 fn deref_mut(&mut self) -> &mut Self::Target {
279 unsafe { &mut *(self as *mut _ as *mut Window<void>) }
281 }
282}