Skip to main content

gtk/subclass/
cell_renderer.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use libc::{c_char, c_int};
4use std::mem;
5
6use glib::object::IsA;
7use glib::subclass::prelude::*;
8use glib::translate::*;
9use glib::Cast;
10use glib::GString;
11
12use crate::CellEditable;
13use crate::CellRenderer;
14use crate::CellRendererState;
15use crate::SizeRequestMode;
16use crate::Widget;
17
18pub trait CellRendererImpl: CellRendererImplExt + ObjectImpl {
19    /// Gets whether the cell renderer prefers a height-for-width layout
20    /// or a width-for-height layout.
21    ///
22    /// # Returns
23    ///
24    /// The [`SizeRequestMode`][crate::SizeRequestMode] preferred by this renderer.
25    fn request_mode(&self) -> SizeRequestMode {
26        self.parent_request_mode()
27    }
28
29    /// Retreives a renderer’s natural size when rendered to `widget`.
30    /// ## `widget`
31    /// the [`Widget`][crate::Widget] this cell will be rendering to
32    ///
33    /// # Returns
34    ///
35    ///
36    /// ## `minimum_size`
37    /// location to store the minimum size, or [`None`]
38    ///
39    /// ## `natural_size`
40    /// location to store the natural size, or [`None`]
41    fn preferred_width<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
42        self.parent_preferred_width(widget)
43    }
44
45    /// Retreives a cell renderers’s minimum and natural width if it were rendered to
46    /// `widget` with the specified `height`.
47    /// ## `widget`
48    /// the [`Widget`][crate::Widget] this cell will be rendering to
49    /// ## `height`
50    /// the size which is available for allocation
51    ///
52    /// # Returns
53    ///
54    ///
55    /// ## `minimum_width`
56    /// location for storing the minimum size, or [`None`]
57    ///
58    /// ## `natural_width`
59    /// location for storing the preferred size, or [`None`]
60    #[doc(alias = "get_preferred_width_for_height")]
61    fn preferred_width_for_height<P: IsA<Widget>>(&self, widget: &P, height: i32) -> (i32, i32) {
62        self.parent_preferred_width_for_height(widget, height)
63    }
64
65    /// Retreives a renderer’s natural size when rendered to `widget`.
66    /// ## `widget`
67    /// the [`Widget`][crate::Widget] this cell will be rendering to
68    ///
69    /// # Returns
70    ///
71    ///
72    /// ## `minimum_size`
73    /// location to store the minimum size, or [`None`]
74    ///
75    /// ## `natural_size`
76    /// location to store the natural size, or [`None`]
77    #[doc(alias = "get_preferred_height")]
78    fn preferred_height<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
79        self.parent_preferred_height(widget)
80    }
81
82    /// Retreives a cell renderers’s minimum and natural height if it were rendered to
83    /// `widget` with the specified `width`.
84    /// ## `widget`
85    /// the [`Widget`][crate::Widget] this cell will be rendering to
86    /// ## `width`
87    /// the size which is available for allocation
88    ///
89    /// # Returns
90    ///
91    ///
92    /// ## `minimum_height`
93    /// location for storing the minimum size, or [`None`]
94    ///
95    /// ## `natural_height`
96    /// location for storing the preferred size, or [`None`]
97    #[doc(alias = "get_preferred_height_for_width")]
98    fn preferred_height_for_width<P: IsA<Widget>>(&self, widget: &P, width: i32) -> (i32, i32) {
99        self.parent_preferred_height_for_width(widget, width)
100    }
101
102    /// Gets the aligned area used by `self` inside `cell_area`. Used for finding
103    /// the appropriate edit and focus rectangle.
104    /// ## `widget`
105    /// the [`Widget`][crate::Widget] this cell will be rendering to
106    /// ## `flags`
107    /// render flags
108    /// ## `cell_area`
109    /// cell area which would be passed to [`CellRendererExt::render()`][crate::prelude::CellRendererExt::render()]
110    ///
111    /// # Returns
112    ///
113    ///
114    /// ## `aligned_area`
115    /// the return location for the space inside `cell_area`
116    ///  that would acually be used to render.
117    #[doc(alias = "get_aligned_area")]
118    fn aligned_area<P: IsA<Widget>>(
119        &self,
120        widget: &P,
121        flags: CellRendererState,
122        cell_area: &gdk::Rectangle,
123    ) -> gdk::Rectangle {
124        self.parent_aligned_area(widget, flags, cell_area)
125    }
126
127    /// Invokes the virtual render function of the [`CellRenderer`][crate::CellRenderer]. The three
128    /// passed-in rectangles are areas in `cr`. Most renderers will draw within
129    /// `cell_area`; the xalign, yalign, xpad, and ypad fields of the [`CellRenderer`][crate::CellRenderer]
130    /// should be honored with respect to `cell_area`. `background_area` includes the
131    /// blank space around the cell, and also the area containing the tree expander;
132    /// so the `background_area` rectangles for all cells tile to cover the entire
133    /// `window`.
134    /// ## `cr`
135    /// a cairo context to draw to
136    /// ## `widget`
137    /// the widget owning `window`
138    /// ## `background_area`
139    /// entire cell area (including tree expanders and maybe
140    ///  padding on the sides)
141    /// ## `cell_area`
142    /// area normally rendered by a cell renderer
143    /// ## `flags`
144    /// flags that affect rendering
145    fn render<P: IsA<Widget>>(
146        &self,
147        cr: &cairo::Context,
148        widget: &P,
149        background_area: &gdk::Rectangle,
150        cell_area: &gdk::Rectangle,
151        flags: CellRendererState,
152    ) {
153        self.parent_render(cr, widget, background_area, cell_area, flags);
154    }
155
156    /// Passes an activate event to the cell renderer for possible processing.
157    /// Some cell renderers may use events; for example, [`CellRendererToggle`][crate::CellRendererToggle]
158    /// toggles when it gets a mouse click.
159    /// ## `event`
160    /// a `GdkEvent`
161    /// ## `widget`
162    /// widget that received the event
163    /// ## `path`
164    /// widget-dependent string representation of the event location;
165    ///  e.g. for [`TreeView`][crate::TreeView], a string representation of [`TreePath`][crate::TreePath]
166    /// ## `background_area`
167    /// background area as passed to [`CellRendererExt::render()`][crate::prelude::CellRendererExt::render()]
168    /// ## `cell_area`
169    /// cell area as passed to [`CellRendererExt::render()`][crate::prelude::CellRendererExt::render()]
170    /// ## `flags`
171    /// render flags
172    ///
173    /// # Returns
174    ///
175    /// [`true`] if the event was consumed/handled
176    fn activate<P: IsA<Widget>>(
177        &self,
178        event: Option<&gdk::Event>,
179        widget: &P,
180        path: &str,
181        background_area: &gdk::Rectangle,
182        cell_area: &gdk::Rectangle,
183        flags: CellRendererState,
184    ) -> bool {
185        self.parent_activate(event, widget, path, background_area, cell_area, flags)
186    }
187
188    /// Starts editing the contents of this `self`, through a new [`CellEditable`][crate::CellEditable]
189    /// widget created by the `GtkCellRendererClass.start_editing` virtual function.
190    /// ## `event`
191    /// a `GdkEvent`
192    /// ## `widget`
193    /// widget that received the event
194    /// ## `path`
195    /// widget-dependent string representation of the event location;
196    ///  e.g. for [`TreeView`][crate::TreeView], a string representation of [`TreePath`][crate::TreePath]
197    /// ## `background_area`
198    /// background area as passed to [`CellRendererExt::render()`][crate::prelude::CellRendererExt::render()]
199    /// ## `cell_area`
200    /// cell area as passed to [`CellRendererExt::render()`][crate::prelude::CellRendererExt::render()]
201    /// ## `flags`
202    /// render flags
203    ///
204    /// # Returns
205    ///
206    /// A new [`CellEditable`][crate::CellEditable] for editing this
207    ///  `self`, or [`None`] if editing is not possible
208    fn start_editing<P: IsA<Widget>>(
209        &self,
210        event: Option<&gdk::Event>,
211        widget: &P,
212        path: &str,
213        background_area: &gdk::Rectangle,
214        cell_area: &gdk::Rectangle,
215        flags: CellRendererState,
216    ) -> Option<CellEditable> {
217        self.parent_start_editing(event, widget, path, background_area, cell_area, flags)
218    }
219
220    fn editing_canceled(&self) {
221        self.parent_editing_canceled()
222    }
223
224    fn editing_started(&self, editable: &CellEditable, path: &str) {
225        self.parent_editing_started(editable, path)
226    }
227}
228
229mod sealed {
230    pub trait Sealed {}
231    impl<T: super::CellRendererImpl> Sealed for T {}
232}
233
234pub trait CellRendererImplExt: ObjectSubclass + sealed::Sealed {
235    fn parent_request_mode(&self) -> SizeRequestMode {
236        unsafe {
237            let data = Self::type_data();
238            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
239            let f = (*parent_class).get_request_mode.unwrap();
240            from_glib(f(self
241                .obj()
242                .unsafe_cast_ref::<CellRenderer>()
243                .to_glib_none()
244                .0))
245        }
246    }
247    fn parent_preferred_width<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
248        unsafe {
249            let data = Self::type_data();
250            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
251            let f = (*parent_class).get_preferred_width.unwrap();
252
253            let mut minimum_size = mem::MaybeUninit::uninit();
254            let mut natural_size = mem::MaybeUninit::uninit();
255            f(
256                self.obj()
257                    .unsafe_cast_ref::<CellRenderer>()
258                    .to_glib_none()
259                    .0,
260                widget.as_ref().to_glib_none().0,
261                minimum_size.as_mut_ptr(),
262                natural_size.as_mut_ptr(),
263            );
264            (minimum_size.assume_init(), natural_size.assume_init())
265        }
266    }
267    fn parent_preferred_width_for_height<P: IsA<Widget>>(
268        &self,
269        widget: &P,
270        height: i32,
271    ) -> (i32, i32) {
272        unsafe {
273            let data = Self::type_data();
274            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
275            let f = (*parent_class).get_preferred_width_for_height.unwrap();
276
277            let mut minimum_size = mem::MaybeUninit::uninit();
278            let mut natural_size = mem::MaybeUninit::uninit();
279            f(
280                self.obj()
281                    .unsafe_cast_ref::<CellRenderer>()
282                    .to_glib_none()
283                    .0,
284                widget.as_ref().to_glib_none().0,
285                height,
286                minimum_size.as_mut_ptr(),
287                natural_size.as_mut_ptr(),
288            );
289            (minimum_size.assume_init(), natural_size.assume_init())
290        }
291    }
292    fn parent_preferred_height<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
293        unsafe {
294            let data = Self::type_data();
295            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
296            let f = (*parent_class).get_preferred_height.unwrap();
297            let mut minimum_size = mem::MaybeUninit::uninit();
298            let mut natural_size = mem::MaybeUninit::uninit();
299            f(
300                self.obj()
301                    .unsafe_cast_ref::<CellRenderer>()
302                    .to_glib_none()
303                    .0,
304                widget.as_ref().to_glib_none().0,
305                minimum_size.as_mut_ptr(),
306                natural_size.as_mut_ptr(),
307            );
308            (minimum_size.assume_init(), natural_size.assume_init())
309        }
310    }
311    fn parent_preferred_height_for_width<P: IsA<Widget>>(
312        &self,
313        widget: &P,
314        width: i32,
315    ) -> (i32, i32) {
316        unsafe {
317            let data = Self::type_data();
318            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
319            let f = (*parent_class).get_preferred_height_for_width.unwrap();
320            let mut minimum_size = mem::MaybeUninit::uninit();
321            let mut natural_size = mem::MaybeUninit::uninit();
322            f(
323                self.obj()
324                    .unsafe_cast_ref::<CellRenderer>()
325                    .to_glib_none()
326                    .0,
327                widget.as_ref().to_glib_none().0,
328                width,
329                minimum_size.as_mut_ptr(),
330                natural_size.as_mut_ptr(),
331            );
332            (minimum_size.assume_init(), natural_size.assume_init())
333        }
334    }
335    fn parent_aligned_area<P: IsA<Widget>>(
336        &self,
337        widget: &P,
338        flags: CellRendererState,
339        cell_area: &gdk::Rectangle,
340    ) -> gdk::Rectangle {
341        unsafe {
342            let data = Self::type_data();
343            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
344            let mut aligned_area = gdk::Rectangle::uninitialized();
345            let f = (*parent_class).get_aligned_area.unwrap();
346            f(
347                self.obj()
348                    .unsafe_cast_ref::<CellRenderer>()
349                    .to_glib_none()
350                    .0,
351                widget.as_ref().to_glib_none().0,
352                flags.into_glib(),
353                cell_area.to_glib_none().0,
354                aligned_area.to_glib_none_mut().0,
355            );
356            aligned_area
357        }
358    }
359    fn parent_render<P: IsA<Widget>>(
360        &self,
361        cr: &cairo::Context,
362        widget: &P,
363        background_area: &gdk::Rectangle,
364        cell_area: &gdk::Rectangle,
365        flags: CellRendererState,
366    ) {
367        unsafe {
368            let data = Self::type_data();
369            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
370            if let Some(f) = (*parent_class).render {
371                f(
372                    self.obj()
373                        .unsafe_cast_ref::<CellRenderer>()
374                        .to_glib_none()
375                        .0,
376                    cr.to_glib_none().0,
377                    widget.as_ref().to_glib_none().0,
378                    background_area.to_glib_none().0,
379                    cell_area.to_glib_none().0,
380                    flags.into_glib(),
381                )
382            }
383        }
384    }
385    fn parent_activate<P: IsA<Widget>>(
386        &self,
387        event: Option<&gdk::Event>,
388        widget: &P,
389        path: &str,
390        background_area: &gdk::Rectangle,
391        cell_area: &gdk::Rectangle,
392        flags: CellRendererState,
393    ) -> bool {
394        unsafe {
395            let data = Self::type_data();
396            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
397            if let Some(f) = (*parent_class).activate {
398                from_glib(f(
399                    self.obj()
400                        .unsafe_cast_ref::<CellRenderer>()
401                        .to_glib_none()
402                        .0,
403                    mut_override(event.to_glib_none().0),
404                    widget.as_ref().to_glib_none().0,
405                    path.to_glib_none().0,
406                    background_area.to_glib_none().0,
407                    cell_area.to_glib_none().0,
408                    flags.into_glib(),
409                ))
410            } else {
411                false
412            }
413        }
414    }
415    fn parent_start_editing<P: IsA<Widget>>(
416        &self,
417        event: Option<&gdk::Event>,
418        widget: &P,
419        path: &str,
420        background_area: &gdk::Rectangle,
421        cell_area: &gdk::Rectangle,
422        flags: CellRendererState,
423    ) -> Option<CellEditable> {
424        unsafe {
425            let data = Self::type_data();
426            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
427            if let Some(f) = (*parent_class).start_editing {
428                from_glib_none(f(
429                    self.obj()
430                        .unsafe_cast_ref::<CellRenderer>()
431                        .to_glib_none()
432                        .0,
433                    mut_override(event.to_glib_none().0),
434                    widget.as_ref().to_glib_none().0,
435                    path.to_glib_none().0,
436                    background_area.to_glib_none().0,
437                    cell_area.to_glib_none().0,
438                    flags.into_glib(),
439                ))
440            } else {
441                None
442            }
443        }
444    }
445    fn parent_editing_canceled(&self) {
446        unsafe {
447            let data = Self::type_data();
448            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
449            if let Some(f) = (*parent_class).editing_canceled {
450                f(self
451                    .obj()
452                    .unsafe_cast_ref::<CellRenderer>()
453                    .to_glib_none()
454                    .0)
455            }
456        }
457    }
458    fn parent_editing_started(&self, editable: &CellEditable, path: &str) {
459        unsafe {
460            let data = Self::type_data();
461            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
462            if let Some(f) = (*parent_class).editing_started {
463                f(
464                    self.obj()
465                        .unsafe_cast_ref::<CellRenderer>()
466                        .to_glib_none()
467                        .0,
468                    editable.to_glib_none().0,
469                    path.to_glib_none().0,
470                )
471            }
472        }
473    }
474}
475
476impl<T: CellRendererImpl> CellRendererImplExt for T {}
477
478unsafe impl<T: CellRendererImpl> IsSubclassable<T> for CellRenderer {
479    fn class_init(class: &mut ::glib::Class<Self>) {
480        Self::parent_class_init::<T>(class);
481
482        if !crate::rt::is_initialized() {
483            panic!("GTK has to be initialized first");
484        }
485
486        let klass = class.as_mut();
487        klass.get_request_mode = Some(cell_renderer_get_request_mode::<T>);
488        klass.get_preferred_width = Some(cell_renderer_get_preferred_width::<T>);
489        klass.get_preferred_height_for_width =
490            Some(cell_renderer_get_preferred_height_for_width::<T>);
491        klass.get_preferred_height = Some(cell_renderer_get_preferred_height::<T>);
492        klass.get_preferred_width_for_height =
493            Some(cell_renderer_get_preferred_width_for_height::<T>);
494        klass.get_aligned_area = Some(cell_renderer_get_aligned_area::<T>);
495        klass.render = Some(cell_renderer_render::<T>);
496        klass.activate = Some(cell_renderer_activate::<T>);
497        klass.start_editing = Some(cell_renderer_start_editing::<T>);
498        klass.editing_started = Some(cell_renderer_editing_started::<T>);
499        klass.editing_canceled = Some(cell_renderer_editing_canceled::<T>);
500    }
501}
502
503unsafe extern "C" fn cell_renderer_get_request_mode<T: CellRendererImpl>(
504    ptr: *mut ffi::GtkCellRenderer,
505) -> ffi::GtkSizeRequestMode {
506    let instance = &*(ptr as *mut T::Instance);
507    let imp = instance.imp();
508
509    imp.request_mode().into_glib()
510}
511
512unsafe extern "C" fn cell_renderer_get_preferred_width<T: CellRendererImpl>(
513    ptr: *mut ffi::GtkCellRenderer,
514    wdgtptr: *mut ffi::GtkWidget,
515    minptr: *mut c_int,
516    natptr: *mut c_int,
517) {
518    let instance = &*(ptr as *mut T::Instance);
519    let imp = instance.imp();
520    let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
521
522    let (min_size, nat_size) = imp.preferred_width(&*widget);
523    if !minptr.is_null() {
524        *minptr = min_size;
525    }
526    if !natptr.is_null() {
527        *natptr = nat_size;
528    }
529}
530
531unsafe extern "C" fn cell_renderer_get_preferred_height_for_width<T: CellRendererImpl>(
532    ptr: *mut ffi::GtkCellRenderer,
533    wdgtptr: *mut ffi::GtkWidget,
534    width: c_int,
535    min_height_ptr: *mut c_int,
536    nat_height_ptr: *mut c_int,
537) {
538    let instance = &*(ptr as *mut T::Instance);
539    let imp = instance.imp();
540    let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
541
542    let (min_height, nat_height) = imp.preferred_height_for_width(&*widget, width);
543    if !min_height_ptr.is_null() {
544        *min_height_ptr = min_height;
545    }
546    if !nat_height_ptr.is_null() {
547        *nat_height_ptr = nat_height;
548    }
549}
550
551unsafe extern "C" fn cell_renderer_get_preferred_height<T: CellRendererImpl>(
552    ptr: *mut ffi::GtkCellRenderer,
553    wdgtptr: *mut ffi::GtkWidget,
554    minptr: *mut c_int,
555    natptr: *mut c_int,
556) {
557    let instance = &*(ptr as *mut T::Instance);
558    let imp = instance.imp();
559    let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
560
561    let (min_size, nat_size) = imp.preferred_height(&*widget);
562    if !minptr.is_null() {
563        *minptr = min_size;
564    }
565    if !natptr.is_null() {
566        *natptr = nat_size;
567    }
568}
569
570unsafe extern "C" fn cell_renderer_get_preferred_width_for_height<T: CellRendererImpl>(
571    ptr: *mut ffi::GtkCellRenderer,
572    wdgtptr: *mut ffi::GtkWidget,
573    height: c_int,
574    min_width_ptr: *mut c_int,
575    nat_width_ptr: *mut c_int,
576) {
577    let instance = &*(ptr as *mut T::Instance);
578    let imp = instance.imp();
579    let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
580
581    let (min_width, nat_width) = imp.preferred_width_for_height(&*widget, height);
582    if !min_width_ptr.is_null() {
583        *min_width_ptr = min_width;
584    }
585    if !nat_width_ptr.is_null() {
586        *nat_width_ptr = nat_width;
587    }
588}
589
590unsafe extern "C" fn cell_renderer_get_aligned_area<T: CellRendererImpl>(
591    ptr: *mut ffi::GtkCellRenderer,
592    wdgtptr: *mut ffi::GtkWidget,
593    flags: ffi::GtkCellRendererState,
594    cellarea: *const gdk::ffi::GdkRectangle,
595    alignedptr: *mut gdk::ffi::GdkRectangle,
596) {
597    let instance = &*(ptr as *mut T::Instance);
598    let imp = instance.imp();
599    let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
600
601    let rectangle = imp.aligned_area(&*widget, from_glib(flags), &from_glib_borrow(cellarea));
602    *alignedptr = *rectangle.to_glib_none().0;
603}
604
605unsafe extern "C" fn cell_renderer_render<T: CellRendererImpl>(
606    ptr: *mut ffi::GtkCellRenderer,
607    crptr: *mut cairo::ffi::cairo_t,
608    wdgtptr: *mut ffi::GtkWidget,
609    bgptr: *const gdk::ffi::GdkRectangle,
610    cellptr: *const gdk::ffi::GdkRectangle,
611    flags: ffi::GtkCellRendererState,
612) {
613    let instance = &*(ptr as *mut T::Instance);
614    let imp = instance.imp();
615    let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
616    let cr: Borrowed<cairo::Context> = from_glib_borrow(crptr);
617
618    imp.render(
619        &cr,
620        &*widget,
621        &from_glib_borrow(bgptr),
622        &from_glib_borrow(cellptr),
623        from_glib(flags),
624    );
625}
626
627unsafe extern "C" fn cell_renderer_activate<T: CellRendererImpl>(
628    ptr: *mut ffi::GtkCellRenderer,
629    evtptr: *mut gdk::ffi::GdkEvent,
630    wdgtptr: *mut ffi::GtkWidget,
631    pathptr: *const c_char,
632    bgptr: *const gdk::ffi::GdkRectangle,
633    cellptr: *const gdk::ffi::GdkRectangle,
634    flags: ffi::GtkCellRendererState,
635) -> glib::ffi::gboolean {
636    let instance = &*(ptr as *mut T::Instance);
637    let imp = instance.imp();
638    let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
639    let evt: Borrowed<Option<gdk::Event>> = from_glib_borrow(evtptr);
640
641    imp.activate(
642        evt.as_ref().as_ref(),
643        &*widget,
644        &GString::from_glib_borrow(pathptr),
645        &from_glib_borrow(bgptr),
646        &from_glib_borrow(cellptr),
647        from_glib(flags),
648    )
649    .into_glib()
650}
651
652unsafe extern "C" fn cell_renderer_start_editing<T: CellRendererImpl>(
653    ptr: *mut ffi::GtkCellRenderer,
654    evtptr: *mut gdk::ffi::GdkEvent,
655    wdgtptr: *mut ffi::GtkWidget,
656    pathptr: *const c_char,
657    bgptr: *const gdk::ffi::GdkRectangle,
658    cellptr: *const gdk::ffi::GdkRectangle,
659    flags: ffi::GtkCellRendererState,
660) -> *mut ffi::GtkCellEditable {
661    let instance = &*(ptr as *mut T::Instance);
662    let imp = instance.imp();
663    let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
664    let evt: Borrowed<Option<gdk::Event>> = from_glib_borrow(evtptr);
665
666    imp.start_editing(
667        evt.as_ref().as_ref(),
668        &*widget,
669        &GString::from_glib_borrow(pathptr),
670        &from_glib_borrow(bgptr),
671        &from_glib_borrow(cellptr),
672        from_glib(flags),
673    )
674    .to_glib_none()
675    .0
676}
677
678unsafe extern "C" fn cell_renderer_editing_canceled<T: CellRendererImpl>(
679    ptr: *mut ffi::GtkCellRenderer,
680) {
681    let instance = &*(ptr as *mut T::Instance);
682    let imp = instance.imp();
683
684    imp.editing_canceled();
685}
686
687unsafe extern "C" fn cell_renderer_editing_started<T: CellRendererImpl>(
688    ptr: *mut ffi::GtkCellRenderer,
689    editableptr: *mut ffi::GtkCellEditable,
690    pathptr: *const c_char,
691) {
692    let instance = &*(ptr as *mut T::Instance);
693    let imp = instance.imp();
694    let editable = from_glib_borrow(editableptr);
695
696    imp.editing_started(&editable, &GString::from_glib_borrow(pathptr));
697}