libadwaita/subclass/
swipeable.rs1use 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}