gtk4/subclass/
tree_view.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 subclassing [`TreeView`](crate::TreeView).
5
6use glib::translate::*;
7
8use crate::{
9    ffi, prelude::*, subclass::prelude::*, MovementStep, TreeIter, TreePath, TreeView,
10    TreeViewColumn,
11};
12
13#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
14#[allow(deprecated)]
15pub trait TreeViewImpl: TreeViewImplExt + WidgetImpl {
16    fn columns_changed(&self) {
17        self.parent_columns_changed()
18    }
19
20    fn cursor_changed(&self) {
21        self.parent_cursor_changed()
22    }
23
24    fn expand_collapse_cursor_row(&self, logical: bool, expand: bool, open_all: bool) -> bool {
25        self.parent_expand_collapse_cursor_row(logical, expand, open_all)
26    }
27
28    fn move_cursor(&self, step: MovementStep, count: i32, expand: bool, modify: bool) -> bool {
29        self.parent_move_cursor(step, count, expand, modify)
30    }
31
32    /// Activates the cell determined by @path and @column.
33    ///
34    /// # Deprecated since 4.10
35    ///
36    /// Use [`ListView`][crate::ListView] or [`ColumnView`][crate::ColumnView] instead
37    /// ## `path`
38    /// The [`TreePath`][crate::TreePath] to be activated.
39    /// ## `column`
40    /// The [`TreeViewColumn`][crate::TreeViewColumn] to be activated.
41    fn row_activated(&self, path: &TreePath, column: &TreeViewColumn) {
42        self.parent_row_activated(path, column)
43    }
44
45    fn row_collapsed(&self, iter: &TreeIter, path: &TreePath) {
46        self.parent_row_collapsed(iter, path)
47    }
48
49    fn row_expanded(&self, iter: &TreeIter, path: &TreePath) {
50        self.parent_row_expanded(iter, path)
51    }
52
53    fn select_all(&self) -> bool {
54        self.parent_select_all()
55    }
56
57    fn select_cursor_parent(&self) -> bool {
58        self.parent_select_cursor_parent()
59    }
60
61    fn select_cursor_row(&self, start_editing: bool) -> bool {
62        self.parent_select_cursor_row(start_editing)
63    }
64
65    fn start_interactive_search(&self) -> bool {
66        self.parent_start_interactive_search()
67    }
68
69    fn test_collapse_row(&self, iter: &TreeIter, path: &TreePath) -> bool {
70        self.parent_test_collapse_row(iter, path)
71    }
72
73    fn test_expand_row(&self, iter: &TreeIter, path: &TreePath) -> bool {
74        self.parent_test_expand_row(iter, path)
75    }
76
77    fn toggle_cursor_row(&self) -> bool {
78        self.parent_toggle_cursor_row()
79    }
80
81    fn unselect_all(&self) -> bool {
82        self.parent_unselect_all()
83    }
84}
85
86mod sealed {
87    pub trait Sealed {}
88    impl<T: super::TreeViewImplExt> Sealed for T {}
89}
90
91#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
92#[allow(deprecated)]
93pub trait TreeViewImplExt: sealed::Sealed + ObjectSubclass {
94    fn parent_columns_changed(&self) {
95        unsafe {
96            let data = Self::type_data();
97            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
98            // columns-changed is a signal
99            if let Some(f) = (*parent_class).columns_changed {
100                f(self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0)
101            }
102        }
103    }
104
105    fn parent_cursor_changed(&self) {
106        unsafe {
107            let data = Self::type_data();
108            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
109            // cursor-changed is a signal
110            if let Some(f) = (*parent_class).cursor_changed {
111                f(self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0)
112            }
113        }
114    }
115
116    fn parent_expand_collapse_cursor_row(
117        &self,
118        logical: bool,
119        expand: bool,
120        open_all: bool,
121    ) -> bool {
122        unsafe {
123            let data = Self::type_data();
124            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
125            // expand-collapse-cursor-row is a signal
126            if let Some(f) = (*parent_class).expand_collapse_cursor_row {
127                from_glib(f(
128                    self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0,
129                    logical.into_glib(),
130                    expand.into_glib(),
131                    open_all.into_glib(),
132                ))
133            } else {
134                false
135            }
136        }
137    }
138
139    fn parent_move_cursor(
140        &self,
141        step: MovementStep,
142        count: i32,
143        extend: bool,
144        modify: bool,
145    ) -> bool {
146        unsafe {
147            let data = Self::type_data();
148            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
149            // move-cursor is a signal
150            if let Some(f) = (*parent_class).move_cursor {
151                from_glib(f(
152                    self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0,
153                    step.into_glib(),
154                    count,
155                    extend.into_glib(),
156                    modify.into_glib(),
157                ))
158            } else {
159                // return false if step is not supported
160                false
161            }
162        }
163    }
164
165    fn parent_row_activated(&self, path: &TreePath, column: &TreeViewColumn) {
166        unsafe {
167            let data = Self::type_data();
168            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
169            // row-activated is a signal
170            if let Some(f) = (*parent_class).row_activated {
171                f(
172                    self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0,
173                    path.to_glib_none().0,
174                    column.to_glib_none().0,
175                );
176            }
177        }
178    }
179
180    fn parent_row_collapsed(&self, iter: &TreeIter, path: &TreePath) {
181        unsafe {
182            let data = Self::type_data();
183            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
184            // row-collapsed is a signal
185            if let Some(f) = (*parent_class).row_collapsed {
186                f(
187                    self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0,
188                    iter.to_glib_none().0 as *mut _,
189                    path.to_glib_none().0,
190                )
191            }
192        }
193    }
194
195    fn parent_row_expanded(&self, iter: &TreeIter, path: &TreePath) {
196        unsafe {
197            let data = Self::type_data();
198            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
199            // row-expanded is a signal
200            if let Some(f) = (*parent_class).row_expanded {
201                f(
202                    self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0,
203                    iter.to_glib_none().0 as *mut _,
204                    path.to_glib_none().0,
205                )
206            }
207        }
208    }
209
210    fn parent_select_all(&self) -> bool {
211        unsafe {
212            let data = Self::type_data();
213            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
214            // select-all is a signal
215            if let Some(f) = (*parent_class).select_all {
216                from_glib(f(self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0))
217            } else {
218                false
219            }
220        }
221    }
222
223    fn parent_select_cursor_parent(&self) -> bool {
224        unsafe {
225            let data = Self::type_data();
226            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
227            // select-cursor-parent is a signal
228            if let Some(f) = (*parent_class).select_cursor_parent {
229                from_glib(f(self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0))
230            } else {
231                false
232            }
233        }
234    }
235
236    fn parent_select_cursor_row(&self, start_editing: bool) -> bool {
237        unsafe {
238            let data = Self::type_data();
239            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
240            // select-cursor-row is a signal
241            if let Some(f) = (*parent_class).select_cursor_row {
242                from_glib(f(
243                    self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0,
244                    start_editing.into_glib(),
245                ))
246            } else {
247                false
248            }
249        }
250    }
251
252    fn parent_start_interactive_search(&self) -> bool {
253        unsafe {
254            let data = Self::type_data();
255            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
256            // start-interactive-search is a signal
257            if let Some(f) = (*parent_class).start_interactive_search {
258                from_glib(f(self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0))
259            } else {
260                false
261            }
262        }
263    }
264
265    fn parent_test_collapse_row(&self, iter: &TreeIter, path: &TreePath) -> bool {
266        unsafe {
267            let data = Self::type_data();
268            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
269            // test-collapse-row is a signal
270            if let Some(f) = (*parent_class).test_collapse_row {
271                from_glib(f(
272                    self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0,
273                    iter.to_glib_none().0 as *mut _,
274                    path.to_glib_none().0,
275                ))
276            } else {
277                // false to allow collapsing, true to reject it
278                false
279            }
280        }
281    }
282
283    fn parent_test_expand_row(&self, iter: &TreeIter, path: &TreePath) -> bool {
284        unsafe {
285            let data = Self::type_data();
286            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
287            // test-expand-row is a signal
288            if let Some(f) = (*parent_class).test_expand_row {
289                from_glib(f(
290                    self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0,
291                    iter.to_glib_none().0 as *mut _,
292                    path.to_glib_none().0,
293                ))
294            } else {
295                // false to allow expanding, true to reject it
296                false
297            }
298        }
299    }
300
301    fn parent_toggle_cursor_row(&self) -> bool {
302        unsafe {
303            let data = Self::type_data();
304            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
305            // toggle-cursor-row is a signal
306            if let Some(f) = (*parent_class).toggle_cursor_row {
307                from_glib(f(self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0))
308            } else {
309                false
310            }
311        }
312    }
313
314    fn parent_unselect_all(&self) -> bool {
315        unsafe {
316            let data = Self::type_data();
317            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTreeViewClass;
318            // unselect-all is a signal
319            if let Some(f) = (*parent_class).unselect_all {
320                from_glib(f(self.obj().unsafe_cast_ref::<TreeView>().to_glib_none().0))
321            } else {
322                false
323            }
324        }
325    }
326}
327
328impl<T: TreeViewImpl> TreeViewImplExt for T {}
329
330unsafe impl<T: TreeViewImpl> IsSubclassable<T> for TreeView {
331    fn class_init(class: &mut glib::Class<Self>) {
332        Self::parent_class_init::<T>(class);
333
334        let klass = class.as_mut();
335        klass.columns_changed = Some(tree_view_columns_changed::<T>);
336        klass.cursor_changed = Some(tree_view_cursor_changed::<T>);
337        klass.expand_collapse_cursor_row = Some(tree_view_expand_collapse_cursor_row::<T>);
338        klass.move_cursor = Some(tree_view_move_cursor::<T>);
339        klass.row_activated = Some(tree_view_row_activated::<T>);
340        klass.row_collapsed = Some(tree_view_row_collapsed::<T>);
341        klass.row_expanded = Some(tree_view_row_expanded::<T>);
342        klass.select_all = Some(tree_view_select_all::<T>);
343        klass.select_cursor_parent = Some(tree_view_select_cursor_parent::<T>);
344        klass.select_cursor_row = Some(tree_view_select_cursor_row::<T>);
345        klass.start_interactive_search = Some(tree_view_start_interactive_search::<T>);
346        klass.test_collapse_row = Some(tree_view_test_collapse_row::<T>);
347        klass.test_expand_row = Some(tree_view_test_expand_row::<T>);
348        klass.toggle_cursor_row = Some(tree_view_toggle_cursor_row::<T>);
349        klass.unselect_all = Some(tree_view_unselect_all::<T>);
350    }
351}
352
353unsafe extern "C" fn tree_view_columns_changed<T: TreeViewImpl>(ptr: *mut ffi::GtkTreeView) {
354    let instance = &*(ptr as *mut T::Instance);
355    let imp = instance.imp();
356
357    imp.columns_changed()
358}
359
360unsafe extern "C" fn tree_view_cursor_changed<T: TreeViewImpl>(ptr: *mut ffi::GtkTreeView) {
361    let instance = &*(ptr as *mut T::Instance);
362    let imp = instance.imp();
363
364    imp.cursor_changed()
365}
366
367unsafe extern "C" fn tree_view_expand_collapse_cursor_row<T: TreeViewImpl>(
368    ptr: *mut ffi::GtkTreeView,
369    logical: glib::ffi::gboolean,
370    expand: glib::ffi::gboolean,
371    open_all: glib::ffi::gboolean,
372) -> glib::ffi::gboolean {
373    let instance = &*(ptr as *mut T::Instance);
374    let imp = instance.imp();
375
376    imp.expand_collapse_cursor_row(from_glib(logical), from_glib(expand), from_glib(open_all))
377        .into_glib()
378}
379
380unsafe extern "C" fn tree_view_move_cursor<T: TreeViewImpl>(
381    ptr: *mut ffi::GtkTreeView,
382    step: ffi::GtkMovementStep,
383    count: i32,
384    extend: glib::ffi::gboolean,
385    modify: glib::ffi::gboolean,
386) -> glib::ffi::gboolean {
387    let instance = &*(ptr as *mut T::Instance);
388    let imp = instance.imp();
389
390    imp.move_cursor(from_glib(step), count, from_glib(extend), from_glib(modify))
391        .into_glib()
392}
393
394unsafe extern "C" fn tree_view_row_activated<T: TreeViewImpl>(
395    ptr: *mut ffi::GtkTreeView,
396    pathptr: *mut ffi::GtkTreePath,
397    columnptr: *mut ffi::GtkTreeViewColumn,
398) {
399    let instance = &*(ptr as *mut T::Instance);
400    let imp = instance.imp();
401    let path: Borrowed<TreePath> = from_glib_borrow(pathptr);
402    let column: Borrowed<TreeViewColumn> = from_glib_borrow(columnptr);
403
404    imp.row_activated(&path, &column)
405}
406
407unsafe extern "C" fn tree_view_row_collapsed<T: TreeViewImpl>(
408    ptr: *mut ffi::GtkTreeView,
409    iterptr: *mut ffi::GtkTreeIter,
410    pathptr: *mut ffi::GtkTreePath,
411) {
412    let instance = &*(ptr as *mut T::Instance);
413    let imp = instance.imp();
414    let path: Borrowed<TreePath> = from_glib_borrow(pathptr);
415    let iter: Borrowed<TreeIter> = from_glib_borrow(iterptr);
416
417    imp.row_collapsed(&iter, &path)
418}
419
420unsafe extern "C" fn tree_view_row_expanded<T: TreeViewImpl>(
421    ptr: *mut ffi::GtkTreeView,
422    iterptr: *mut ffi::GtkTreeIter,
423    pathptr: *mut ffi::GtkTreePath,
424) {
425    let instance = &*(ptr as *mut T::Instance);
426    let imp = instance.imp();
427    let path: Borrowed<TreePath> = from_glib_borrow(pathptr);
428    let iter: Borrowed<TreeIter> = from_glib_borrow(iterptr);
429
430    imp.row_expanded(&iter, &path)
431}
432
433unsafe extern "C" fn tree_view_select_all<T: TreeViewImpl>(
434    ptr: *mut ffi::GtkTreeView,
435) -> glib::ffi::gboolean {
436    let instance = &*(ptr as *mut T::Instance);
437    let imp = instance.imp();
438
439    imp.select_all().into_glib()
440}
441
442unsafe extern "C" fn tree_view_select_cursor_parent<T: TreeViewImpl>(
443    ptr: *mut ffi::GtkTreeView,
444) -> glib::ffi::gboolean {
445    let instance = &*(ptr as *mut T::Instance);
446    let imp = instance.imp();
447
448    imp.select_cursor_parent().into_glib()
449}
450
451unsafe extern "C" fn tree_view_select_cursor_row<T: TreeViewImpl>(
452    ptr: *mut ffi::GtkTreeView,
453    start_editing: glib::ffi::gboolean,
454) -> glib::ffi::gboolean {
455    let instance = &*(ptr as *mut T::Instance);
456    let imp = instance.imp();
457
458    imp.select_cursor_row(from_glib(start_editing)).into_glib()
459}
460
461unsafe extern "C" fn tree_view_start_interactive_search<T: TreeViewImpl>(
462    ptr: *mut ffi::GtkTreeView,
463) -> glib::ffi::gboolean {
464    let instance = &*(ptr as *mut T::Instance);
465    let imp = instance.imp();
466
467    imp.start_interactive_search().into_glib()
468}
469
470unsafe extern "C" fn tree_view_test_collapse_row<T: TreeViewImpl>(
471    ptr: *mut ffi::GtkTreeView,
472    iterptr: *mut ffi::GtkTreeIter,
473    pathptr: *mut ffi::GtkTreePath,
474) -> glib::ffi::gboolean {
475    let instance = &*(ptr as *mut T::Instance);
476    let imp = instance.imp();
477    let path: Borrowed<TreePath> = from_glib_borrow(pathptr);
478    let iter: Borrowed<TreeIter> = from_glib_borrow(iterptr);
479
480    imp.test_collapse_row(&iter, &path).into_glib()
481}
482
483unsafe extern "C" fn tree_view_test_expand_row<T: TreeViewImpl>(
484    ptr: *mut ffi::GtkTreeView,
485    iterptr: *mut ffi::GtkTreeIter,
486    pathptr: *mut ffi::GtkTreePath,
487) -> glib::ffi::gboolean {
488    let instance = &*(ptr as *mut T::Instance);
489    let imp = instance.imp();
490    let path: Borrowed<TreePath> = from_glib_borrow(pathptr);
491    let iter: Borrowed<TreeIter> = from_glib_borrow(iterptr);
492
493    imp.test_expand_row(&iter, &path).into_glib()
494}
495
496unsafe extern "C" fn tree_view_toggle_cursor_row<T: TreeViewImpl>(
497    ptr: *mut ffi::GtkTreeView,
498) -> glib::ffi::gboolean {
499    let instance = &*(ptr as *mut T::Instance);
500    let imp = instance.imp();
501
502    imp.toggle_cursor_row().into_glib()
503}
504
505unsafe extern "C" fn tree_view_unselect_all<T: TreeViewImpl>(
506    ptr: *mut ffi::GtkTreeView,
507) -> glib::ffi::gboolean {
508    let instance = &*(ptr as *mut T::Instance);
509    let imp = instance.imp();
510
511    imp.unselect_all().into_glib()
512}