gtk4/subclass/
tree_drag_source.rs

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