Skip to main content

gtk4/
tree_sortable.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, mem};
4
5use glib::translate::*;
6
7use crate::{Ordering, SortType, TreeIter, TreeModel, TreeSortable, ffi, prelude::*};
8
9#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
10#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
11#[allow(deprecated)]
12pub enum SortColumn {
13    #[doc(alias = "GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID")]
14    Default,
15    Index(u32),
16}
17
18#[doc(hidden)]
19impl IntoGlib for SortColumn {
20    type GlibType = i32;
21
22    #[inline]
23    fn into_glib(self) -> i32 {
24        match self {
25            SortColumn::Default => ffi::GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
26            SortColumn::Index(x) => {
27                assert!(x <= i32::MAX as u32, "column index is too big");
28                x as i32
29            }
30        }
31    }
32}
33
34#[doc(hidden)]
35impl FromGlib<i32> for SortColumn {
36    #[inline]
37    unsafe fn from_glib(val: i32) -> Self {
38        skip_assert_initialized!();
39        match val {
40            ffi::GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID => Self::Default,
41            x => {
42                assert!(x >= 0, "invalid column index");
43                Self::Index(x as u32)
44            }
45        }
46    }
47}
48
49impl fmt::Display for SortColumn {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        write!(
52            f,
53            "SortColumn::{}",
54            match *self {
55                SortColumn::Default => "Default",
56                SortColumn::Index(_) => "Index",
57            }
58        )
59    }
60}
61
62// rustdoc-stripper-ignore-next
63/// Trait containing manually implemented methods of
64/// [`TreeSortable`](crate::TreeSortable).
65#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
66#[allow(deprecated)]
67pub trait TreeSortableExtManual: IsA<TreeSortable> + 'static {
68    /// t go back to the
69    /// default state. In this case, when the current sort column id of @self
70    /// is `GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID`, the model will be unsorted.
71    ///
72    /// # Deprecated since 4.10
73    ///
74    /// ## `sort_func`
75    /// The comparison function
76    #[doc(alias = "gtk_tree_sortable_set_default_sort_func")]
77    fn set_default_sort_func<F>(&self, sort_func: F)
78    where
79        F: Fn(&Self, &TreeIter, &TreeIter) -> Ordering + 'static,
80    {
81        unsafe {
82            ffi::gtk_tree_sortable_set_default_sort_func(
83                self.as_ref().to_glib_none().0,
84                Some(trampoline::<Self, F>),
85                into_raw(sort_func),
86                Some(destroy_closure::<Self, F>),
87            )
88        }
89    }
90    /// Sets the comparison function used when sorting to be @sort_func. If the
91    /// current sort column id of @self is the same as @sort_column_id, then
92    /// the model will sort using this function.
93    ///
94    /// # Deprecated since 4.10
95    ///
96    /// ## `sort_column_id`
97    /// the sort column id to set the function for
98    /// ## `sort_func`
99    /// The comparison function
100    #[doc(alias = "gtk_tree_sortable_set_sort_func")]
101    fn set_sort_func<F>(&self, sort_column_id: SortColumn, sort_func: F)
102    where
103        F: Fn(&Self, &TreeIter, &TreeIter) -> Ordering + 'static,
104    {
105        unsafe {
106            ffi::gtk_tree_sortable_set_sort_func(
107                self.as_ref().to_glib_none().0,
108                sort_column_id.into_glib(),
109                Some(trampoline::<Self, F>),
110                into_raw(sort_func),
111                Some(destroy_closure::<Self, F>),
112            )
113        }
114    }
115    /// Fills in @sort_column_id and @order with the current sort column and the
116    /// order. It returns [`true`] unless the @sort_column_id is
117    /// `GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID` or
118    /// `GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID`.
119    ///
120    /// # Deprecated since 4.10
121    ///
122    ///
123    /// # Returns
124    ///
125    /// [`true`] if the sort column is not one of the special sort
126    ///   column ids.
127    ///
128    /// ## `sort_column_id`
129    /// The sort column id to be filled in
130    ///
131    /// ## `order`
132    /// The [`SortType`][crate::SortType] to be filled in
133    #[doc(alias = "gtk_tree_sortable_get_sort_column_id")]
134    #[doc(alias = "get_sort_column_id")]
135    fn sort_column_id(&self) -> Option<(SortColumn, SortType)> {
136        unsafe {
137            let mut sort_column_id = mem::MaybeUninit::uninit();
138            let mut order = mem::MaybeUninit::uninit();
139            ffi::gtk_tree_sortable_get_sort_column_id(
140                self.as_ref().to_glib_none().0,
141                sort_column_id.as_mut_ptr(),
142                order.as_mut_ptr(),
143            );
144            let sort_column_id = sort_column_id.assume_init();
145            if sort_column_id != ffi::GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID {
146                Some((from_glib(sort_column_id), from_glib(order.assume_init())))
147            } else {
148                None
149            }
150        }
151    }
152    /// Sets the current sort column to be @sort_column_id. The @self will
153    /// resort itself to reflect this change, after emitting a
154    /// `GtkTreeSortable::sort-column-changed` signal. @sort_column_id may either be
155    /// a regular column id, or one of the following special values:
156    ///
157    /// - `GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID`: the default sort function
158    ///   will be used, if it is set
159    ///
160    /// - `GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID`: no sorting will occur
161    ///
162    /// # Deprecated since 4.10
163    ///
164    /// ## `sort_column_id`
165    /// the sort column id to set
166    /// ## `order`
167    /// The sort order of the column
168    #[doc(alias = "gtk_tree_sortable_set_sort_column_id")]
169    fn set_sort_column_id(&self, sort_column_id: SortColumn, order: SortType) {
170        unsafe {
171            ffi::gtk_tree_sortable_set_sort_column_id(
172                self.as_ref().to_glib_none().0,
173                sort_column_id.into_glib(),
174                order.into_glib(),
175            );
176        }
177    }
178    #[doc(alias = "gtk_tree_sortable_set_sort_column_id")]
179    fn set_unsorted(&self) {
180        unsafe {
181            ffi::gtk_tree_sortable_set_sort_column_id(
182                self.as_ref().to_glib_none().0,
183                ffi::GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
184                SortType::Ascending.into_glib(),
185            );
186        }
187    }
188}
189
190unsafe extern "C" fn trampoline<T, F: Fn(&T, &TreeIter, &TreeIter) -> Ordering>(
191    this: *mut ffi::GtkTreeModel,
192    iter: *mut ffi::GtkTreeIter,
193    iter2: *mut ffi::GtkTreeIter,
194    f: glib::ffi::gpointer,
195) -> i32
196where
197    T: IsA<TreeSortable>,
198{
199    unsafe {
200        let f: &F = &*(f as *const F);
201        f(
202            &TreeModel::from_glib_none(this).unsafe_cast(),
203            &from_glib_borrow(iter),
204            &from_glib_borrow(iter2),
205        )
206        .into_glib()
207    }
208}
209
210unsafe extern "C" fn destroy_closure<T, F: Fn(&T, &TreeIter, &TreeIter) -> Ordering>(
211    ptr: glib::ffi::gpointer,
212) {
213    unsafe {
214        let _ = Box::<F>::from_raw(ptr as *mut _);
215    }
216}
217
218fn into_raw<F, T>(func: F) -> glib::ffi::gpointer
219where
220    F: Fn(&T, &TreeIter, &TreeIter) -> Ordering + 'static,
221{
222    skip_assert_initialized!();
223    let func: Box<F> = Box::new(func);
224    Box::into_raw(func) as glib::ffi::gpointer
225}
226
227impl<O: IsA<TreeSortable>> TreeSortableExtManual for O {}