Skip to main content

gtk4/
custom_sorter.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ptr;
4
5use glib::translate::*;
6
7use crate::{CustomSorter, Ordering, ffi};
8
9impl CustomSorter {
10    /// Creates a new [`Sorter`][crate::Sorter] that works by calling
11    /// @sort_func to compare items.
12    ///
13    /// If @sort_func is [`None`], all items are considered equal.
14    /// ## `sort_func`
15    /// the `GCompareDataFunc` to use for sorting
16    ///
17    /// # Returns
18    ///
19    /// a new [`CustomSorter`][crate::CustomSorter]
20    #[doc(alias = "gtk_custom_sorter_new")]
21    pub fn new<F>(sort_func: F) -> Self
22    where
23        F: Fn(&glib::Object, &glib::Object) -> Ordering + 'static,
24    {
25        assert_initialized_main_thread!();
26        unsafe {
27            from_glib_full(ffi::gtk_custom_sorter_new(
28                Some(trampoline::<F>),
29                Box::into_raw(Box::new(sort_func)) as *mut _,
30                Some(destroy_closure::<F>),
31            ))
32        }
33    }
34
35    /// Sets (or unsets) the function used for sorting items.
36    ///
37    /// If @sort_func is [`None`], all items are considered equal.
38    ///
39    /// If the sort func changes its sorting behavior,
40    /// gtk_sorter_changed() needs to be called.
41    ///
42    /// If a previous function was set, its @user_destroy will be
43    /// called now.
44    /// ## `sort_func`
45    /// function to sort items
46    #[doc(alias = "gtk_custom_sorter_set_sort_func")]
47    pub fn set_sort_func<F>(&self, sort_func: F)
48    where
49        F: Fn(&glib::Object, &glib::Object) -> Ordering + 'static,
50    {
51        unsafe {
52            ffi::gtk_custom_sorter_set_sort_func(
53                self.to_glib_none().0,
54                Some(trampoline::<F>),
55                Box::into_raw(Box::new(sort_func)) as *mut _,
56                Some(destroy_closure::<F>),
57            )
58        }
59    }
60
61    #[doc(alias = "gtk_custom_sorter_set_sort_func")]
62    #[doc(alias = "set_sort_func")]
63    pub fn unset_sort_func(&self) {
64        unsafe {
65            ffi::gtk_custom_sorter_set_sort_func(self.to_glib_none().0, None, ptr::null_mut(), None)
66        }
67    }
68}
69
70impl Default for CustomSorter {
71    fn default() -> Self {
72        assert_initialized_main_thread!();
73        unsafe { from_glib_full(ffi::gtk_custom_sorter_new(None, ptr::null_mut(), None)) }
74    }
75}
76
77unsafe extern "C" fn destroy_closure<F: Fn(&glib::Object, &glib::Object) -> Ordering + 'static>(
78    ptr: glib::ffi::gpointer,
79) {
80    unsafe {
81        let _ = Box::<F>::from_raw(ptr as *mut _);
82    }
83}
84
85unsafe extern "C" fn trampoline<F: Fn(&glib::Object, &glib::Object) -> Ordering + 'static>(
86    a: glib::ffi::gconstpointer,
87    b: glib::ffi::gconstpointer,
88    f: glib::ffi::gpointer,
89) -> i32 {
90    unsafe {
91        let f: &F = &*(f as *const F);
92        f(
93            &from_glib_borrow(a as *mut glib::gobject_ffi::GObject),
94            &from_glib_borrow(b as *mut glib::gobject_ffi::GObject),
95        )
96        .into_glib()
97    }
98}