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