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