Skip to main content

gtk/subclass/
tree_drag_source.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4
5use crate::{SelectionData, TreeDragSource, TreePath, ffi, prelude::*, subclass::prelude::*};
6
7pub trait TreeDragSourceImpl: ObjectImpl + ObjectSubclass<Type: IsA<TreeDragSource>> {
8    fn row_draggable(&self, path: &TreePath) -> bool {
9        self.parent_row_draggable(path)
10    }
11
12    fn drag_data_get(&self, path: &TreePath, selection_data: &SelectionData) -> bool;
13
14    fn drag_data_delete(&self, path: &TreePath) -> bool;
15}
16
17pub trait TreeDragSourceImplExt: TreeDragSourceImpl {
18    // Returns true if the row can be dragged
19    fn parent_row_draggable(&self, path: &TreePath) -> bool {
20        unsafe {
21            let type_data = Self::type_data();
22            let parent_iface = type_data.as_ref().parent_interface::<TreeDragSource>()
23                as *const ffi::GtkTreeDragSourceIface;
24
25            if let Some(func) = (*parent_iface).row_draggable {
26                from_glib(func(
27                    self.obj()
28                        .unsafe_cast_ref::<TreeDragSource>()
29                        .to_glib_none()
30                        .0,
31                    mut_override(path.to_glib_none().0),
32                ))
33            } else {
34                // Assume the row is draggable by default
35                true
36            }
37        }
38    }
39
40    fn parent_drag_data_get(&self, path: &TreePath, selection_data: &SelectionData) -> bool {
41        unsafe {
42            let type_data = Self::type_data();
43            let parent_iface = type_data.as_ref().parent_interface::<TreeDragSource>()
44                as *const ffi::GtkTreeDragSourceIface;
45
46            let func = (*parent_iface)
47                .drag_data_get
48                .expect("no parent \"drag_data_get\" implementation");
49
50            from_glib(func(
51                self.obj()
52                    .unsafe_cast_ref::<TreeDragSource>()
53                    .to_glib_none()
54                    .0,
55                mut_override(path.to_glib_none().0),
56                selection_data.to_glib_none().0,
57            ))
58        }
59    }
60
61    // True if the row was successfully deleted
62    fn parent_drag_data_delete(&self, path: &TreePath) -> bool {
63        unsafe {
64            let type_data = Self::type_data();
65            let parent_iface = type_data.as_ref().parent_interface::<TreeDragSource>()
66                as *const ffi::GtkTreeDragSourceIface;
67
68            let func = (*parent_iface)
69                .drag_data_delete
70                .expect("no parent \"drag_data_delete\" implementation");
71
72            from_glib(func(
73                self.obj()
74                    .unsafe_cast_ref::<TreeDragSource>()
75                    .to_glib_none()
76                    .0,
77                mut_override(path.to_glib_none().0),
78            ))
79        }
80    }
81}
82
83impl<T: TreeDragSourceImpl> TreeDragSourceImplExt for T {}
84
85unsafe impl<T: TreeDragSourceImpl> IsImplementable<T> for TreeDragSource {
86    fn interface_init(iface: &mut glib::Interface<Self>) {
87        let iface = iface.as_mut();
88
89        if !crate::rt::is_initialized() {
90            panic!("GTK has to be initialized first");
91        }
92
93        iface.row_draggable = Some(tree_drag_source_row_draggable::<T>);
94        iface.drag_data_get = Some(tree_drag_source_drag_data_get::<T>);
95        iface.drag_data_delete = Some(tree_drag_source_drag_data_delete::<T>);
96    }
97}
98
99unsafe extern "C" fn tree_drag_source_row_draggable<T: TreeDragSourceImpl>(
100    tree_drag_source: *mut ffi::GtkTreeDragSource,
101    pathptr: *mut ffi::GtkTreePath,
102) -> glib::ffi::gboolean {
103    unsafe {
104        let instance = &*(tree_drag_source as *mut T::Instance);
105        let imp = instance.imp();
106
107        let path: Borrowed<TreePath> = from_glib_borrow(pathptr);
108
109        imp.row_draggable(&path).into_glib()
110    }
111}
112
113unsafe extern "C" fn tree_drag_source_drag_data_get<T: TreeDragSourceImpl>(
114    tree_drag_source: *mut ffi::GtkTreeDragSource,
115    pathptr: *mut ffi::GtkTreePath,
116    selectiondataptr: *mut ffi::GtkSelectionData,
117) -> glib::ffi::gboolean {
118    unsafe {
119        let instance = &*(tree_drag_source as *mut T::Instance);
120        let imp = instance.imp();
121        let path: Borrowed<TreePath> = from_glib_borrow(pathptr);
122        let selection_data: Borrowed<SelectionData> = from_glib_borrow(selectiondataptr);
123
124        imp.drag_data_get(&path, &selection_data).into_glib()
125    }
126}
127
128unsafe extern "C" fn tree_drag_source_drag_data_delete<T: TreeDragSourceImpl>(
129    tree_drag_source: *mut ffi::GtkTreeDragSource,
130    pathptr: *mut ffi::GtkTreePath,
131) -> glib::ffi::gboolean {
132    unsafe {
133        let instance = &*(tree_drag_source as *mut T::Instance);
134        let imp = instance.imp();
135        let path: Borrowed<TreePath> = from_glib_borrow(pathptr);
136        imp.drag_data_delete(&path).into_glib()
137    }
138}