Skip to main content

polyhorn_ios_sys/polykit/
layout.rs

1use objc::runtime::*;
2use objc::*;
3
4use crate::coregraphics::CGRect;
5use crate::Raw;
6
7/// A dynamic layout that can be queried from Objective-C.
8pub struct PLYLayout {
9    object: *mut Object,
10}
11
12pub struct PLYLayoutData(Box<dyn FnMut() -> CGRect>);
13
14impl PLYLayout {
15    /// Initializes a newly allocated dynamic layout with the given closure.
16    pub fn new<F>(value: F) -> Self
17    where
18        F: FnMut() -> CGRect + 'static,
19    {
20        let data = PLYLayoutData(Box::new(value));
21
22        unsafe {
23            unsafe fn hook(data: *mut PLYLayoutData) -> CGRect {
24                data.as_mut().unwrap().0()
25            }
26
27            unsafe fn free(data: *mut PLYLayoutData) {
28                Box::from_raw(data);
29            }
30
31            let data = Box::into_raw(Box::new(data));
32
33            let mut object: *mut Object = msg_send![class!(PLYLayout), alloc];
34
35            object = msg_send![object, initWithHook: hook as usize
36                                               free: free as usize
37                                               data: data as usize];
38
39            PLYLayout::from_raw(object)
40        }
41    }
42}
43
44impl Raw for PLYLayout {
45    unsafe fn from_raw(object: *mut Object) -> Self {
46        PLYLayout { object }
47    }
48
49    unsafe fn as_raw(&self) -> *mut Object {
50        self.object
51    }
52}
53
54impl Drop for PLYLayout {
55    fn drop(&mut self) {
56        unsafe { objc_release(self.object) }
57    }
58}