Skip to main content

gtk4/subclass/
text_buffer.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 [`TextBuffer`].
5
6use glib::translate::*;
7
8use crate::{
9    TextBuffer, TextChildAnchor, TextIter, TextMark, TextTag, ffi, prelude::*, subclass::prelude::*,
10};
11
12pub trait TextBufferImpl: ObjectImpl + ObjectSubclass<Type: IsA<TextBuffer>> {
13    ///  signal on @buffer.
14    ///
15    /// The default handler for the signal applies
16    /// @tag to the given range. @start and @end do
17    /// not have to be in order.
18    /// ## `tag`
19    /// a [`TextTag`][crate::TextTag]
20    /// ## `start`
21    /// one bound of range to be tagged
22    /// ## `end`
23    /// other bound of range to be tagged
24    fn apply_tag(&self, tag: &TextTag, start: &TextIter, end: &TextIter) {
25        self.parent_apply_tag(tag, start, end)
26    }
27    ///  buffer mutation functions, such as
28    /// [`TextBufferExt::insert_interactive()`][crate::prelude::TextBufferExt::insert_interactive()], automatically call
29    /// begin/end user action around the buffer operations they perform,
30    /// so there's no need to add extra calls if you user action consists
31    /// solely of a single call to one of those functions.
32    fn begin_user_action(&self) {
33        self.parent_begin_user_action()
34    }
35    /// The class handler for the `GtkTextBuffer::changed` signal.
36    fn changed(&self) {
37        self.parent_changed()
38    }
39    /// The class handler for the `GtkTextBuffer::delete-range` signal.
40    fn delete_range(&self, start: &mut TextIter, end: &mut TextIter) {
41        self.parent_delete_range(start, end)
42    }
43    /// Ends a user-visible operation.
44    ///
45    /// Should be paired with a call to
46    /// [`TextBufferExt::begin_user_action()`][crate::prelude::TextBufferExt::begin_user_action()].
47    /// See that function for a full explanation.
48    fn end_user_action(&self) {
49        self.parent_end_user_action()
50    }
51    ///  variants do
52    /// not. E.g. see [`TextBufferExt::slice()`][crate::prelude::TextBufferExt::slice()] and
53    /// [`TextBufferExt::text()`][crate::prelude::TextBufferExt::text()].
54    ///
55    /// Consider [`TextBufferExt::create_child_anchor()`][crate::prelude::TextBufferExt::create_child_anchor()] as a more
56    /// convenient alternative to this function. The buffer will add a
57    /// reference to the anchor, so you can unref it after insertion.
58    /// ## `iter`
59    /// location to insert the anchor
60    /// ## `anchor`
61    /// a [`TextChildAnchor`][crate::TextChildAnchor]
62    fn insert_child_anchor(&self, iter: &mut TextIter, anchor: &TextChildAnchor) {
63        self.parent_insert_child_anchor(iter, anchor)
64    }
65    ///
66    /// variants do not. e.g. see [`TextBufferExt::slice()`][crate::prelude::TextBufferExt::slice()] and
67    /// [`TextBufferExt::text()`][crate::prelude::TextBufferExt::text()].
68    /// ## `iter`
69    /// location to insert the paintable
70    /// ## `paintable`
71    /// a [`gdk::Paintable`][crate::gdk::Paintable]
72    fn insert_paintable(&self, iter: &mut TextIter, paintable: &gdk::Paintable) {
73        self.parent_insert_paintable(iter, paintable)
74    }
75    /// The class handler for the `GtkTextBuffer::insert-text` signal.
76    fn insert_text(&self, iter: &mut TextIter, new_text: &str) {
77        self.parent_insert_text(iter, new_text)
78    }
79    /// The class handler for the `GtkTextBuffer::mark-deleted` signal.
80    fn mark_deleted(&self, mark: &TextMark) {
81        self.parent_mark_deleted(mark);
82    }
83    /// The class handler for the `GtkTextBuffer::mark-set` signal.
84    fn mark_set(&self, location: &TextIter, mark: &TextMark) {
85        self.parent_mark_set(location, mark)
86    }
87    /// The class handler for the `GtkTextBuffer::modified-changed` signal.
88    fn modified_changed(&self) {
89        self.parent_modified_changed();
90    }
91    /// The class handler for the `GtkTextBuffer::paste-done` signal.
92    fn paste_done(&self, clipboard: &gdk::Clipboard) {
93        self.parent_paste_done(clipboard)
94    }
95    /// Redoes the next redoable action on the buffer, if there is one.
96    fn redo(&self) {
97        self.parent_redo()
98    }
99    /// t have
100    /// to be in order.
101    /// ## `tag`
102    /// a [`TextTag`][crate::TextTag]
103    /// ## `start`
104    /// one bound of range to be untagged
105    /// ## `end`
106    /// other bound of range to be untagged
107    fn remove_tag(&self, tag: &TextTag, start: &TextIter, end: &TextIter) {
108        self.parent_remove_tag(tag, start, end)
109    }
110    /// Undoes the last undoable action on the buffer, if there is one.
111    fn undo(&self) {
112        self.parent_undo()
113    }
114}
115
116pub trait TextBufferImplExt: TextBufferImpl {
117    fn parent_apply_tag(&self, tag: &TextTag, start: &TextIter, end: &TextIter) {
118        unsafe {
119            let data = Self::type_data();
120            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
121            if let Some(f) = (*parent_class).apply_tag {
122                f(
123                    self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0,
124                    tag.to_glib_none().0,
125                    start.to_glib_none().0,
126                    end.to_glib_none().0,
127                )
128            }
129        }
130    }
131
132    fn parent_begin_user_action(&self) {
133        unsafe {
134            let data = Self::type_data();
135            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
136            if let Some(f) = (*parent_class).begin_user_action {
137                f(self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0)
138            }
139        }
140    }
141
142    fn parent_changed(&self) {
143        unsafe {
144            let data = Self::type_data();
145            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
146            if let Some(f) = (*parent_class).changed {
147                f(self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0)
148            }
149        }
150    }
151
152    fn parent_delete_range(&self, start: &mut TextIter, end: &mut TextIter) {
153        unsafe {
154            let data = Self::type_data();
155            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
156            if let Some(f) = (*parent_class).delete_range {
157                f(
158                    self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0,
159                    start.to_glib_none_mut().0,
160                    end.to_glib_none_mut().0,
161                )
162            }
163        }
164    }
165
166    fn parent_end_user_action(&self) {
167        unsafe {
168            let data = Self::type_data();
169            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
170            if let Some(f) = (*parent_class).end_user_action {
171                f(self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0)
172            }
173        }
174    }
175
176    fn parent_insert_child_anchor(&self, iter: &mut TextIter, anchor: &TextChildAnchor) {
177        unsafe {
178            let data = Self::type_data();
179            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
180            if let Some(f) = (*parent_class).insert_child_anchor {
181                f(
182                    self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0,
183                    iter.to_glib_none_mut().0,
184                    anchor.to_glib_none().0,
185                )
186            }
187        }
188    }
189
190    fn parent_insert_paintable(&self, iter: &mut TextIter, paintable: &gdk::Paintable) {
191        unsafe {
192            let data = Self::type_data();
193            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
194            if let Some(f) = (*parent_class).insert_paintable {
195                f(
196                    self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0,
197                    iter.to_glib_none_mut().0,
198                    paintable.to_glib_none().0,
199                )
200            }
201        }
202    }
203
204    fn parent_insert_text(&self, iter: &mut TextIter, new_text: &str) {
205        unsafe {
206            let data = Self::type_data();
207            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
208            if let Some(f) = (*parent_class).insert_text {
209                f(
210                    self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0,
211                    iter.to_glib_none_mut().0,
212                    new_text.to_glib_none().0,
213                    new_text.len() as i32,
214                )
215            }
216        }
217    }
218
219    fn parent_mark_deleted(&self, mark: &TextMark) {
220        unsafe {
221            let data = Self::type_data();
222            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
223            if let Some(f) = (*parent_class).mark_deleted {
224                f(
225                    self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0,
226                    mark.to_glib_none().0,
227                )
228            }
229        }
230    }
231
232    fn parent_mark_set(&self, location: &TextIter, mark: &TextMark) {
233        unsafe {
234            let data = Self::type_data();
235            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
236            if let Some(f) = (*parent_class).mark_set {
237                f(
238                    self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0,
239                    location.to_glib_none().0,
240                    mark.to_glib_none().0,
241                )
242            }
243        }
244    }
245
246    fn parent_modified_changed(&self) {
247        unsafe {
248            let data = Self::type_data();
249            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
250            if let Some(f) = (*parent_class).modified_changed {
251                f(self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0)
252            }
253        }
254    }
255
256    fn parent_paste_done(&self, clipboard: &gdk::Clipboard) {
257        unsafe {
258            let data = Self::type_data();
259            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
260            if let Some(f) = (*parent_class).paste_done {
261                f(
262                    self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0,
263                    clipboard.to_glib_none().0,
264                )
265            }
266        }
267    }
268
269    fn parent_redo(&self) {
270        unsafe {
271            let data = Self::type_data();
272            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
273            if let Some(f) = (*parent_class).redo {
274                f(self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0)
275            }
276        }
277    }
278
279    fn parent_remove_tag(&self, tag: &TextTag, start: &TextIter, end: &TextIter) {
280        unsafe {
281            let data = Self::type_data();
282            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
283            if let Some(f) = (*parent_class).remove_tag {
284                f(
285                    self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0,
286                    tag.to_glib_none().0,
287                    start.to_glib_none().0,
288                    end.to_glib_none().0,
289                )
290            }
291        }
292    }
293
294    fn parent_undo(&self) {
295        unsafe {
296            let data = Self::type_data();
297            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkTextBufferClass;
298            if let Some(f) = (*parent_class).undo {
299                f(self.obj().unsafe_cast_ref::<TextBuffer>().to_glib_none().0)
300            }
301        }
302    }
303}
304
305impl<T: TextBufferImpl> TextBufferImplExt for T {}
306
307unsafe impl<T: TextBufferImpl> IsSubclassable<T> for TextBuffer {
308    fn class_init(class: &mut glib::Class<Self>) {
309        Self::parent_class_init::<T>(class);
310
311        assert_initialized_main_thread!();
312
313        let klass = class.as_mut();
314        klass.apply_tag = Some(text_buffer_apply_tag::<T>);
315        klass.begin_user_action = Some(text_buffer_begin_user_action::<T>);
316        klass.changed = Some(text_buffer_changed::<T>);
317        klass.delete_range = Some(text_buffer_delete_range::<T>);
318        klass.end_user_action = Some(text_buffer_end_user_action::<T>);
319        klass.insert_child_anchor = Some(text_buffer_insert_child_anchor::<T>);
320        klass.insert_paintable = Some(text_buffer_insert_paintable::<T>);
321        klass.insert_text = Some(text_buffer_insert_text::<T>);
322        klass.mark_deleted = Some(text_buffer_mark_deleted::<T>);
323        klass.mark_set = Some(text_buffer_mark_set::<T>);
324        klass.modified_changed = Some(text_buffer_modified_changed::<T>);
325        klass.paste_done = Some(text_buffer_paste_done::<T>);
326        klass.remove_tag = Some(text_buffer_remove_tag::<T>);
327        klass.redo = Some(text_buffer_redo::<T>);
328        klass.undo = Some(text_buffer_undo::<T>);
329    }
330}
331
332unsafe extern "C" fn text_buffer_apply_tag<T: TextBufferImpl>(
333    ptr: *mut ffi::GtkTextBuffer,
334    tag_ptr: *mut ffi::GtkTextTag,
335    start_ptr: *const ffi::GtkTextIter,
336    end_ptr: *const ffi::GtkTextIter,
337) {
338    unsafe {
339        let instance = &*(ptr as *mut T::Instance);
340        let imp = instance.imp();
341
342        imp.apply_tag(
343            &from_glib_borrow(tag_ptr),
344            &from_glib_borrow(start_ptr),
345            &from_glib_borrow(end_ptr),
346        )
347    }
348}
349
350unsafe extern "C" fn text_buffer_begin_user_action<T: TextBufferImpl>(
351    ptr: *mut ffi::GtkTextBuffer,
352) {
353    unsafe {
354        let instance = &*(ptr as *mut T::Instance);
355        let imp = instance.imp();
356
357        imp.begin_user_action()
358    }
359}
360
361unsafe extern "C" fn text_buffer_changed<T: TextBufferImpl>(ptr: *mut ffi::GtkTextBuffer) {
362    unsafe {
363        let instance = &*(ptr as *mut T::Instance);
364        let imp = instance.imp();
365
366        imp.changed()
367    }
368}
369
370unsafe extern "C" fn text_buffer_delete_range<T: TextBufferImpl>(
371    ptr: *mut ffi::GtkTextBuffer,
372    start_ptr: *mut ffi::GtkTextIter,
373    end_ptr: *mut ffi::GtkTextIter,
374) {
375    unsafe {
376        let instance = &*(ptr as *mut T::Instance);
377        let imp = instance.imp();
378
379        let mut start_copy = from_glib_none(start_ptr);
380        let mut end_copy = from_glib_none(end_ptr);
381
382        imp.delete_range(&mut start_copy, &mut end_copy);
383
384        *start_ptr = *start_copy.to_glib_none().0;
385        *end_ptr = *end_copy.to_glib_none().0;
386    }
387}
388
389unsafe extern "C" fn text_buffer_end_user_action<T: TextBufferImpl>(ptr: *mut ffi::GtkTextBuffer) {
390    unsafe {
391        let instance = &*(ptr as *mut T::Instance);
392        let imp = instance.imp();
393
394        imp.end_user_action()
395    }
396}
397
398unsafe extern "C" fn text_buffer_insert_child_anchor<T: TextBufferImpl>(
399    ptr: *mut ffi::GtkTextBuffer,
400    iter_ptr: *mut ffi::GtkTextIter,
401    anchor_ptr: *mut ffi::GtkTextChildAnchor,
402) {
403    unsafe {
404        let instance = &*(ptr as *mut T::Instance);
405        let imp = instance.imp();
406
407        let mut iter = from_glib_none(iter_ptr);
408
409        imp.insert_child_anchor(&mut iter, &from_glib_borrow(anchor_ptr));
410        *iter_ptr = *iter.to_glib_none().0;
411    }
412}
413
414unsafe extern "C" fn text_buffer_insert_paintable<T: TextBufferImpl>(
415    ptr: *mut ffi::GtkTextBuffer,
416    iter_ptr: *mut ffi::GtkTextIter,
417    paintable_ptr: *mut gdk::ffi::GdkPaintable,
418) {
419    unsafe {
420        let instance = &*(ptr as *mut T::Instance);
421        let imp = instance.imp();
422
423        let mut iter = from_glib_none(iter_ptr);
424
425        imp.insert_paintable(&mut iter, &from_glib_borrow(paintable_ptr));
426        *iter_ptr = *iter.to_glib_none().0;
427    }
428}
429
430unsafe extern "C" fn text_buffer_insert_text<T: TextBufferImpl>(
431    ptr: *mut ffi::GtkTextBuffer,
432    iter_ptr: *mut ffi::GtkTextIter,
433    text_ptr: *const libc::c_char,
434    _length: libc::c_int,
435) {
436    unsafe {
437        let instance = &*(ptr as *mut T::Instance);
438        let imp = instance.imp();
439        let text: Borrowed<glib::GString> = from_glib_borrow(text_ptr);
440
441        let mut iter = from_glib_none(iter_ptr);
442
443        imp.insert_text(&mut iter, text.as_str());
444        *iter_ptr = *iter.to_glib_none().0;
445    }
446}
447
448unsafe extern "C" fn text_buffer_modified_changed<T: TextBufferImpl>(ptr: *mut ffi::GtkTextBuffer) {
449    unsafe {
450        let instance = &*(ptr as *mut T::Instance);
451        let imp = instance.imp();
452
453        imp.modified_changed()
454    }
455}
456
457unsafe extern "C" fn text_buffer_mark_deleted<T: TextBufferImpl>(
458    ptr: *mut ffi::GtkTextBuffer,
459    mark: *mut ffi::GtkTextMark,
460) {
461    unsafe {
462        let instance = &*(ptr as *mut T::Instance);
463        let imp = instance.imp();
464
465        imp.mark_deleted(&from_glib_borrow(mark))
466    }
467}
468
469unsafe extern "C" fn text_buffer_mark_set<T: TextBufferImpl>(
470    ptr: *mut ffi::GtkTextBuffer,
471    iter: *const ffi::GtkTextIter,
472    mark: *mut ffi::GtkTextMark,
473) {
474    unsafe {
475        let instance = &*(ptr as *mut T::Instance);
476        let imp = instance.imp();
477
478        imp.mark_set(&from_glib_borrow(iter), &from_glib_borrow(mark))
479    }
480}
481
482unsafe extern "C" fn text_buffer_paste_done<T: TextBufferImpl>(
483    ptr: *mut ffi::GtkTextBuffer,
484    clipboard_ptr: *mut gdk::ffi::GdkClipboard,
485) {
486    unsafe {
487        let instance = &*(ptr as *mut T::Instance);
488        let imp = instance.imp();
489
490        imp.paste_done(&from_glib_borrow(clipboard_ptr))
491    }
492}
493
494unsafe extern "C" fn text_buffer_redo<T: TextBufferImpl>(ptr: *mut ffi::GtkTextBuffer) {
495    unsafe {
496        let instance = &*(ptr as *mut T::Instance);
497        let imp = instance.imp();
498
499        imp.redo()
500    }
501}
502
503unsafe extern "C" fn text_buffer_remove_tag<T: TextBufferImpl>(
504    ptr: *mut ffi::GtkTextBuffer,
505    tag: *mut ffi::GtkTextTag,
506    start: *const ffi::GtkTextIter,
507    end: *const ffi::GtkTextIter,
508) {
509    unsafe {
510        let instance = &*(ptr as *mut T::Instance);
511        let imp = instance.imp();
512
513        imp.remove_tag(
514            &from_glib_borrow(tag),
515            &from_glib_borrow(start),
516            &from_glib_borrow(end),
517        )
518    }
519}
520
521unsafe extern "C" fn text_buffer_undo<T: TextBufferImpl>(ptr: *mut ffi::GtkTextBuffer) {
522    unsafe {
523        let instance = &*(ptr as *mut T::Instance);
524        let imp = instance.imp();
525
526        imp.undo()
527    }
528}