pebble_skip/user_interface/window/
number_window.rs1use crate::{
2 standard_c::{CStr, NotStack},
3 Box, Handle, SpecialDrop,
4};
5use core::{
6 marker::PhantomData,
7 mem::ManuallyDrop,
8 ops::{Deref, DerefMut},
9};
10#[allow(clippy::wildcard_imports)]
11use pebble_sys::{
12 prelude::*,
13 standard_c::memory::void,
14 user_interface::window::number_window::{NumberWindow as sysNumberWindow, *},
15};
16
17use super::{WindowRef, WindowRefMut};
18
19pub struct NumberWindow<'a, T: ?Sized>(
20 pub(crate) Handle<'a, sysNumberWindow<'a>>,
21 PhantomData<T>,
22 *mut NumberWindowDataWrapper<'a>,
23);
24
25pub struct NumberWindowData<
26 I: FnMut(&NumberWindow<void>, &mut T),
27 D: FnMut(&NumberWindow<void>, &mut T),
28 S: FnMut(&NumberWindow<void>, &mut T),
29 T,
30> {
31 pub incremented: I,
32 pub decremented: D,
33 pub selected: S,
34 pub context: T,
35}
36
37trait NumberWindowDataTrait {
38 fn incremented(&mut self, number_window: &NumberWindow<void>);
39 fn decremented(&mut self, number_window: &NumberWindow<void>);
40 fn selected(&mut self, number_window: &NumberWindow<void>);
41}
42
43impl<
44 I: FnMut(&NumberWindow<void>, &mut T),
45 D: FnMut(&NumberWindow<void>, &mut T),
46 S: FnMut(&NumberWindow<void>, &mut T),
47 T,
48 > NumberWindowDataTrait for NumberWindowData<I, D, S, T>
49{
50 fn incremented(&mut self, number_window: &NumberWindow<void>) {
51 (self.incremented)(number_window, &mut self.context)
52 }
53
54 fn decremented(&mut self, number_window: &NumberWindow<void>) {
55 (self.decremented)(number_window, &mut self.context)
56 }
57
58 fn selected(&mut self, number_window: &NumberWindow<void>) {
59 (self.selected)(number_window, &mut self.context)
60 }
61}
62
63pub struct NumberWindowDataWrapper<'a>(Box<'a, dyn 'a + NumberWindowDataTrait>);
64
65impl<'a, T> NumberWindow<'a, T> {
66 pub fn new<
72 I: 'a + FnMut(&NumberWindow<void>, &mut T),
73 D: 'a + FnMut(&NumberWindow<void>, &mut T),
74 S: 'a + FnMut(&NumberWindow<void>, &mut T),
75 >(
76 label: &'a CStr<impl NotStack>,
77 number_window_data: NumberWindowData<I, D, S, T>,
78 ) -> Result<Self, NumberWindowData<I, D, S, T>>
79 where
80 T: 'a,
81 {
82 #![allow(clippy::items_after_statements)]
83
84 let window_data_wrapper = Box::leak(
85 Box::new(NumberWindowDataWrapper(Box::new(number_window_data)?)).map_err(
86 |wrapper| Box::into_inner(unsafe { Box::downcast_unchecked(wrapper.0) }),
87 )?,
88 ) as *mut NumberWindowDataWrapper;
89
90 extern "C" fn raw_incremented<'a>(
91 raw_window: &'a mut sysNumberWindow<'a>,
92 context: &mut void,
93 ) {
94 let context = context as *mut void; let fake_window = unsafe {
96 #[allow(clippy::cast_ptr_alignment)]
99 NumberWindow::<void>::from_raw_unsized(
100 raw_window,
101 context as *mut _ as *mut NumberWindowDataWrapper,
102 )
103 };
104 unsafe {
105 let context = &mut *context;
108 context
109 .cast_unchecked_mut::<NumberWindowDataWrapper>()
110 .0
111 .incremented(&fake_window)
112 }
113 fake_window.abandon();
114 }
115 extern "C" fn raw_decremented<'a>(
116 raw_window: &'a mut sysNumberWindow<'a>,
117 context: &mut void,
118 ) {
119 let context = context as *mut void; let fake_window = unsafe {
121 #[allow(clippy::cast_ptr_alignment)]
124 NumberWindow::<void>::from_raw_unsized(
125 raw_window,
126 context as *mut _ as *mut NumberWindowDataWrapper,
127 )
128 };
129 unsafe {
130 let context = &mut *context;
133 context
134 .cast_unchecked_mut::<NumberWindowDataWrapper>()
135 .0
136 .decremented(&fake_window)
137 }
138 fake_window.abandon();
139 }
140 extern "C" fn raw_selected<'a>(
141 raw_window: &'a mut sysNumberWindow<'a>,
142 context: &mut void,
143 ) {
144 let context = context as *mut void; let fake_window = unsafe {
146 #[allow(clippy::cast_ptr_alignment)]
149 NumberWindow::<void>::from_raw_unsized(
150 raw_window,
151 context as *mut _ as *mut NumberWindowDataWrapper,
152 )
153 };
154 unsafe {
155 let context = &mut *context;
158 context
159 .cast_unchecked_mut::<NumberWindowDataWrapper>()
160 .0
161 .selected(&fake_window)
162 }
163 fake_window.abandon();
164 }
165
166 match unsafe {
167 number_window_create(
168 label.as_c_str(),
169 NumberWindowCallbacks {
170 incremented: Some(raw_incremented),
171 decremented: Some(raw_decremented),
172 selected: Some(raw_selected),
173 },
174 &mut *(window_data_wrapper as *mut _ as *mut void),
175 )
176 } {
177 Some(raw_window) => Ok(Self(
178 Handle::new(raw_window),
179 PhantomData,
180 window_data_wrapper,
181 )),
182 None => Err(Box::into_inner(unsafe {
183 Box::downcast_unchecked(
184 Box::into_inner(Box::<NumberWindowDataWrapper>::from_raw(
185 &mut *window_data_wrapper,
186 ))
187 .0,
188 )
189 })),
190 }
191 }
192
193 pub unsafe fn from_raw(
201 raw_window: &'a mut sysNumberWindow<'a>,
202 number_window_data_wrapper: *mut NumberWindowDataWrapper<'a>,
203 ) -> Self {
204 Self(
205 Handle::new(raw_window),
206 PhantomData,
207 number_window_data_wrapper,
208 )
209 }
210
211 #[must_use = "Not reassembling the `NumberWindow` later causes a memory leak."]
215 pub fn leak(
216 self,
217 ) -> (
218 &'a mut sysNumberWindow<'a>,
219 *mut NumberWindowDataWrapper<'a>,
220 )
221 where
222 T: 'a,
223 {
224 let undropped = ManuallyDrop::new(self);
225 unsafe { (undropped.0.duplicate().unwrap(), undropped.2) }
226 }
227}
228
229impl<'a, T: ?Sized> NumberWindow<'a, T> {
230 #[must_use]
231 pub fn window(&self) -> WindowRef<'_> {
232 WindowRef(Handle::new(unsafe {
233 number_window_get_window_mut(&mut *(self.0.as_mut_unchecked() as *mut _))
234 }))
235 }
236
237 #[must_use]
238 pub fn window_mut<'b: 'a>(&'b mut self) -> WindowRefMut<'b> {
239 WindowRefMut(Handle::new(unsafe {
240 number_window_get_window_mut(self.0.as_mut_unchecked())
241 }))
242 }
243
244 pub fn set_label(&self, label: &'a CStr<impl NotStack>) {
245 unsafe { number_window_set_label(self.0.as_mut_unchecked(), label.as_c_str()) }
246 }
247
248 pub fn set_max(&self, max: i32) {
249 unsafe { number_window_set_max(self.0.as_mut_unchecked(), max) }
250 }
251
252 pub fn set_min(&self, min: i32) {
253 unsafe { number_window_set_min(self.0.as_mut_unchecked(), min) }
254 }
255
256 pub fn set_value(&self, value: i32) {
257 unsafe { number_window_set_value(self.0.as_mut_unchecked(), value) }
258 }
259
260 pub fn set_step_size(&self, step_size: i32) {
261 unsafe { number_window_set_step_size(self.0.as_mut_unchecked(), step_size) }
262 }
263
264 #[must_use]
265 pub fn get_value(&self) -> i32 {
266 unsafe { number_window_get_value(&*self.0) }
267 }
268
269 unsafe fn from_raw_unsized(
276 raw_window: &'a mut sysNumberWindow<'a>,
277 number_window_data_wrapper: *mut NumberWindowDataWrapper<'a>,
278 ) -> Self {
279 Self(
280 Handle::new(raw_window),
281 PhantomData,
282 number_window_data_wrapper,
283 )
284 }
285
286 fn abandon(self) {
288 let _ = ManuallyDrop::new(self);
289 }
290}
291
292impl<'a, T> Deref for NumberWindow<'a, T> {
293 type Target = NumberWindow<'a, void>;
294
295 fn deref(&self) -> &Self::Target {
296 unsafe {
297 &*(self as *const _ as *const Self::Target)
299 }
300 }
301}
302
303impl<'a, T> DerefMut for NumberWindow<'a, T> {
304 fn deref_mut(&mut self) -> &mut Self::Target {
305 unsafe {
306 &mut *(self as *mut _ as *mut Self::Target)
308 }
309 }
310}
311
312impl<'a, T: ?Sized> Drop for NumberWindow<'a, T> {
313 fn drop(&mut self) {
314 self.special_drop()
315 }
316}
317
318impl<'a, T: ?Sized> SpecialDrop for NumberWindow<'a, T> {
319 default fn special_drop(&mut self) {
320 panic!("Dropping unsized `NumberWindow<T>`s is illegal")
321 }
322}
323
324impl<'a, T: Sized> SpecialDrop for NumberWindow<'a, T> {
325 fn special_drop(&mut self) {
326 unsafe {
327 let data_wrapper = self.2;
330 let sys_number_window = self.0.duplicate().unwrap() as *mut _ as *mut void as *mut _;
332
333 number_window_destroy(&mut *sys_number_window);
335 Box::<NumberWindowDataWrapper>::from_raw(&mut *data_wrapper);
336 }
337 }
338}