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