Skip to main content

sourceview5/subclass/
indenter.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 implementing the [`Indenter`](crate::Indenter) interface.
5
6use crate::{Indenter, View, prelude::*};
7use glib::subclass::prelude::*;
8use glib::translate::*;
9
10pub trait IndenterImpl: ObjectImpl + ObjectSubclass<Type: IsA<glib::Object>> {
11    fn is_trigger(
12        &self,
13        view: &View,
14        location: &gtk::TextIter,
15        state: gdk::ModifierType,
16        keyval: gdk::Key,
17    ) -> bool {
18        self.parent_is_trigger(view, location, state, keyval)
19    }
20
21    fn indent(&self, view: &View, iter: &mut gtk::TextIter) {
22        self.parent_indent(view, iter)
23    }
24}
25
26pub trait IndenterImplExt: IndenterImpl {
27    fn parent_is_trigger(
28        &self,
29        view: &View,
30        location: &gtk::TextIter,
31        state: gdk::ModifierType,
32        keyval: gdk::Key,
33    ) -> bool {
34        unsafe {
35            let type_data = Self::type_data();
36            let parent_iface = type_data.as_ref().parent_interface::<Indenter>()
37                as *const ffi::GtkSourceIndenterInterface;
38
39            let func = (*parent_iface)
40                .is_trigger
41                .expect("no parent \"is_trigger\" implementation");
42
43            from_glib(func(
44                self.obj().unsafe_cast_ref::<Indenter>().to_glib_none().0,
45                view.to_glib_none().0,
46                location.to_glib_none().0,
47                state.into_glib(),
48                keyval.into_glib(),
49            ))
50        }
51    }
52
53    fn parent_indent(&self, view: &View, iter: &mut gtk::TextIter) {
54        unsafe {
55            let type_data = Self::type_data();
56            let parent_iface = type_data.as_ref().parent_interface::<Indenter>()
57                as *const ffi::GtkSourceIndenterInterface;
58
59            let func = (*parent_iface)
60                .indent
61                .expect("no parent \"indent\" implementation");
62
63            func(
64                self.obj().unsafe_cast_ref::<Indenter>().to_glib_none().0,
65                view.to_glib_none().0,
66                iter.to_glib_none_mut().0,
67            )
68        }
69    }
70}
71impl<T: IndenterImpl> IndenterImplExt for T {}
72
73unsafe impl<T: IndenterImpl> IsImplementable<T> for Indenter {
74    fn interface_init(iface: &mut glib::Interface<Self>) {
75        let iface = iface.as_mut();
76
77        iface.is_trigger = Some(indenter_is_trigger::<T>);
78        iface.indent = Some(indenter_indent::<T>);
79    }
80}
81
82unsafe extern "C" fn indenter_is_trigger<T: IndenterImpl>(
83    indenter: *mut ffi::GtkSourceIndenter,
84    view: *mut ffi::GtkSourceView,
85    iter: *const gtk::ffi::GtkTextIter,
86    state: gdk::ffi::GdkModifierType,
87    keyval: u32,
88) -> glib::ffi::gboolean {
89    unsafe {
90        let instance = &*(indenter as *mut T::Instance);
91        let imp = instance.imp();
92
93        imp.is_trigger(
94            &from_glib_borrow(view),
95            &from_glib_borrow(iter),
96            from_glib(state),
97            from_glib(keyval),
98        )
99        .into_glib()
100    }
101}
102
103unsafe extern "C" fn indenter_indent<T: IndenterImpl>(
104    indenter: *mut ffi::GtkSourceIndenter,
105    view: *mut ffi::GtkSourceView,
106    iterptr: *mut gtk::ffi::GtkTextIter,
107) {
108    unsafe {
109        let instance = &*(indenter as *mut T::Instance);
110        let imp = instance.imp();
111        let mut iter = from_glib_full(iterptr);
112        imp.indent(&from_glib_borrow(view), &mut iter);
113        *iterptr = *iter.to_glib_full();
114    }
115}