libadwaita/subclass/
swipeable.rs

1use crate::{prelude::*, NavigationDirection, Swipeable};
2use glib::translate::*;
3use gtk::subclass::prelude::*;
4
5pub trait SwipeableImpl: WidgetImpl + ObjectSubclass<Type: IsA<Swipeable>> {
6    fn cancel_progress(&self) -> f64 {
7        self.parent_cancel_progress()
8    }
9
10    fn distance(&self) -> f64 {
11        self.parent_distance()
12    }
13
14    fn progress(&self) -> f64 {
15        self.parent_progress()
16    }
17
18    fn snap_points(&self) -> Vec<f64> {
19        self.parent_snap_points()
20    }
21
22    fn swipe_area(
23        &self,
24        navigation_direction: NavigationDirection,
25        is_drag: bool,
26    ) -> gdk::Rectangle {
27        self.parent_swipe_area(navigation_direction, is_drag)
28    }
29}
30pub trait SwipeableImplExt: SwipeableImpl {
31    fn parent_cancel_progress(&self) -> f64 {
32        unsafe {
33            let type_data = Self::type_data();
34            let parent_iface = type_data.as_ref().parent_interface::<Swipeable>()
35                as *const ffi::AdwSwipeableInterface;
36
37            let func = (*parent_iface)
38                .get_cancel_progress
39                .expect("no parent \"get_cancel_progress\" implementation");
40
41            func(self.obj().unsafe_cast_ref::<Swipeable>().to_glib_none().0)
42        }
43    }
44
45    fn parent_distance(&self) -> f64 {
46        unsafe {
47            let type_data = Self::type_data();
48            let parent_iface = type_data.as_ref().parent_interface::<Swipeable>()
49                as *const ffi::AdwSwipeableInterface;
50
51            let func = (*parent_iface)
52                .get_distance
53                .expect("no parent \"get_distance\" implementation");
54
55            func(self.obj().unsafe_cast_ref::<Swipeable>().to_glib_none().0)
56        }
57    }
58
59    fn parent_progress(&self) -> f64 {
60        unsafe {
61            let type_data = Self::type_data();
62            let parent_iface = type_data.as_ref().parent_interface::<Swipeable>()
63                as *const ffi::AdwSwipeableInterface;
64
65            let func = (*parent_iface)
66                .get_progress
67                .expect("no parent \"get_progress\" implementation");
68
69            func(self.obj().unsafe_cast_ref::<Swipeable>().to_glib_none().0)
70        }
71    }
72
73    fn parent_snap_points(&self) -> Vec<f64> {
74        unsafe {
75            let type_data = Self::type_data();
76            let parent_iface = type_data.as_ref().parent_interface::<Swipeable>()
77                as *const ffi::AdwSwipeableInterface;
78
79            let func = (*parent_iface)
80                .get_snap_points
81                .expect("no parent \"get_snap_points\" implementation");
82
83            let mut n_points = std::mem::MaybeUninit::uninit();
84
85            let points = func(
86                self.obj().unsafe_cast_ref::<Swipeable>().to_glib_none().0,
87                n_points.as_mut_ptr(),
88            );
89
90            let size = n_points.assume_init() as usize;
91            Vec::from_raw_parts(points, size, size)
92        }
93    }
94
95    fn parent_swipe_area(
96        &self,
97        navigation_direction: NavigationDirection,
98        is_drag: bool,
99    ) -> gdk::Rectangle {
100        unsafe {
101            let type_data = Self::type_data();
102            let parent_iface = type_data.as_ref().parent_interface::<Swipeable>()
103                as *const ffi::AdwSwipeableInterface;
104
105            let func = (*parent_iface)
106                .get_swipe_area
107                .expect("no parent \"get_swipe_area\" implementation");
108
109            let mut rect = gdk::Rectangle::uninitialized();
110            func(
111                self.obj().unsafe_cast_ref::<Swipeable>().to_glib_none().0,
112                navigation_direction.into_glib(),
113                is_drag.into_glib(),
114                rect.to_glib_none_mut().0,
115            );
116
117            rect
118        }
119    }
120}
121
122impl<T: SwipeableImpl> SwipeableImplExt for T {}
123
124unsafe impl<T: SwipeableImpl> IsImplementable<T> for Swipeable {
125    fn interface_init(iface: &mut glib::Interface<Self>) {
126        let iface = iface.as_mut();
127
128        iface.get_cancel_progress = Some(swipeable_get_cancel_progress::<T>);
129        iface.get_distance = Some(swipeable_get_distance::<T>);
130        iface.get_progress = Some(swipeable_get_progress::<T>);
131        iface.get_snap_points = Some(swipeable_get_snap_points::<T>);
132        iface.get_swipe_area = Some(swipeable_get_swipe_area::<T>);
133    }
134}
135
136unsafe extern "C" fn swipeable_get_cancel_progress<T: SwipeableImpl>(
137    swipeable: *mut ffi::AdwSwipeable,
138) -> f64 {
139    let instance = unsafe { &*(swipeable as *mut T::Instance) };
140    let imp = instance.imp();
141
142    imp.cancel_progress()
143}
144
145unsafe extern "C" fn swipeable_get_distance<T: SwipeableImpl>(
146    swipeable: *mut ffi::AdwSwipeable,
147) -> f64 {
148    let instance = unsafe { &*(swipeable as *mut T::Instance) };
149    let imp = instance.imp();
150
151    imp.distance()
152}
153
154unsafe extern "C" fn swipeable_get_progress<T: SwipeableImpl>(
155    swipeable: *mut ffi::AdwSwipeable,
156) -> f64 {
157    let instance = unsafe { &*(swipeable as *mut T::Instance) };
158    let imp = instance.imp();
159
160    imp.progress()
161}
162
163unsafe extern "C" fn swipeable_get_snap_points<T: SwipeableImpl>(
164    swipeable: *mut ffi::AdwSwipeable,
165    n_pointsptr: *mut libc::c_int,
166) -> *mut f64 {
167    let instance = unsafe { &*(swipeable as *mut T::Instance) };
168    let imp = instance.imp();
169
170    let points = imp.snap_points();
171
172    unsafe {
173        n_pointsptr.write(points.len() as libc::c_int);
174    }
175    ToGlibContainerFromSlice::to_glib_full_from_slice(points.as_slice())
176}
177
178unsafe extern "C" fn swipeable_get_swipe_area<T: SwipeableImpl>(
179    swipeable: *mut ffi::AdwSwipeable,
180    navigation_direction: ffi::AdwNavigationDirection,
181    is_drag: i32,
182    area: *mut gdk::ffi::GdkRectangle,
183) {
184    unsafe {
185        let instance = &*(swipeable as *mut T::Instance);
186        let imp = instance.imp();
187
188        let swipe_area = imp.swipe_area(from_glib(navigation_direction), from_glib(is_drag));
189
190        *area = *swipe_area.to_glib_full();
191    }
192}