Skip to main content

gtk/subclass/
scrolled_window.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4
5use glib::subclass::prelude::*;
6
7use glib::object::Cast;
8
9use super::bin::BinImpl;
10use crate::ScrollType;
11use crate::ScrolledWindow;
12use crate::{DirectionType, ffi};
13
14pub trait ScrolledWindowImpl: ScrolledWindowImplExt + BinImpl {
15    /// Keybinding signal which gets emitted when focus is
16    ///  moved away from the scrolled window by a keybinding.
17    fn move_focus_out(&self, direction_type: DirectionType) {
18        self.parent_move_focus_out(direction_type)
19    }
20
21    /// Keybinding signal which gets emitted when a
22    ///  keybinding that scrolls is pressed.
23    fn scroll_child(&self, scroll: ScrollType, horizontal: bool) -> bool {
24        self.parent_scroll_child(scroll, horizontal)
25    }
26}
27
28mod sealed {
29    pub trait Sealed {}
30    impl<T: super::ScrolledWindowImpl> Sealed for T {}
31}
32
33pub trait ScrolledWindowImplExt: ObjectSubclass + sealed::Sealed {
34    fn parent_move_focus_out(&self, direction_type: DirectionType) {
35        unsafe {
36            let data = Self::type_data();
37            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkScrolledWindowClass;
38            if let Some(f) = (*parent_class).move_focus_out {
39                f(
40                    self.obj()
41                        .unsafe_cast_ref::<ScrolledWindow>()
42                        .to_glib_none()
43                        .0,
44                    direction_type.into_glib(),
45                )
46            }
47        }
48    }
49    fn parent_scroll_child(&self, scroll: ScrollType, horizontal: bool) -> bool {
50        unsafe {
51            let data = Self::type_data();
52            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkScrolledWindowClass;
53            if let Some(f) = (*parent_class).scroll_child {
54                from_glib(f(
55                    self.obj()
56                        .unsafe_cast_ref::<ScrolledWindow>()
57                        .to_glib_none()
58                        .0,
59                    scroll.into_glib(),
60                    horizontal.into_glib(),
61                ))
62            } else {
63                false
64            }
65        }
66    }
67}
68
69impl<T: ScrolledWindowImpl> ScrolledWindowImplExt for T {}
70
71unsafe impl<T: ScrolledWindowImpl> IsSubclassable<T> for ScrolledWindow {
72    fn class_init(class: &mut ::glib::Class<Self>) {
73        Self::parent_class_init::<T>(class);
74
75        let klass = class.as_mut();
76        klass.move_focus_out = Some(window_move_focus_out::<T>);
77        klass.scroll_child = Some(window_scroll_child::<T>);
78    }
79}
80
81unsafe extern "C" fn window_move_focus_out<T: ScrolledWindowImpl>(
82    ptr: *mut ffi::GtkScrolledWindow,
83    directiontypeptr: ffi::GtkDirectionType,
84) {
85    unsafe {
86        let instance = &*(ptr as *mut T::Instance);
87        let imp = instance.imp();
88        let direction_type: DirectionType = from_glib(directiontypeptr);
89
90        imp.move_focus_out(direction_type)
91    }
92}
93
94unsafe extern "C" fn window_scroll_child<T: ScrolledWindowImpl>(
95    ptr: *mut ffi::GtkScrolledWindow,
96    scrollptr: ffi::GtkScrollType,
97    horizontalptr: glib::ffi::gboolean,
98) -> glib::ffi::gboolean {
99    unsafe {
100        let instance = &*(ptr as *mut T::Instance);
101        let imp = instance.imp();
102        let scroll: ScrollType = from_glib(scrollptr);
103        let horizontal: bool = from_glib(horizontalptr);
104
105        imp.scroll_child(scroll, horizontal).into_glib()
106    }
107}