Skip to main content

gtk4/subclass/
cell_area.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 [`CellArea`].
5
6use std::mem;
7
8use glib::{ParamSpec, Value, translate::*};
9
10use crate::{
11    Buildable, CellArea, CellAreaContext, CellLayout, CellRenderer, CellRendererState,
12    DirectionType, SizeRequestMode, Snapshot, TreeIter, TreeModel, Widget, ffi, prelude::*,
13    subclass::prelude::*,
14};
15
16#[derive(Debug)]
17pub struct CellCallback {
18    callback: ffi::GtkCellCallback,
19    user_data: glib::ffi::gpointer,
20}
21
22impl CellCallback {
23    pub fn call<R: IsA<CellRenderer>>(&self, cell_renderer: &R) -> glib::ControlFlow {
24        unsafe {
25            if let Some(callback) = self.callback {
26                from_glib(callback(
27                    cell_renderer.as_ref().to_glib_none().0,
28                    self.user_data,
29                ))
30            } else {
31                glib::ControlFlow::Break
32            }
33        }
34    }
35}
36
37#[derive(Debug)]
38pub struct CellCallbackAllocate {
39    callback: ffi::GtkCellAllocCallback,
40    user_data: glib::ffi::gpointer,
41}
42
43impl CellCallbackAllocate {
44    pub fn call<R: IsA<CellRenderer>>(
45        &self,
46        cell_renderer: &R,
47        cell_area: &gdk::Rectangle,
48        cell_background: &gdk::Rectangle,
49    ) -> glib::ControlFlow {
50        unsafe {
51            if let Some(callback) = self.callback {
52                from_glib(callback(
53                    cell_renderer.as_ref().to_glib_none().0,
54                    cell_area.to_glib_none().0,
55                    cell_background.to_glib_none().0,
56                    self.user_data,
57                ))
58            } else {
59                glib::ControlFlow::Break
60            }
61        }
62    }
63}
64
65#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
66#[allow(deprecated)]
67pub trait CellAreaImpl:
68    ObjectImpl + ObjectSubclass<Type: IsA<CellArea> + IsA<Buildable> + IsA<CellLayout>>
69{
70    fn cell_properties() -> &'static [ParamSpec] {
71        &[]
72    }
73
74    /// This should be implemented to handle changes in child
75    ///   cell properties for a given [`CellRenderer`][crate::CellRenderer] that were previously
76    ///   installed on the [`CellAreaClass`][crate::CellAreaClass] with gtk_cell_area_class_install_cell_property().
77    fn set_cell_property<R: IsA<CellRenderer>>(
78        &self,
79        _renderer: &R,
80        _id: usize,
81        _value: &Value,
82        _pspec: &ParamSpec,
83    ) {
84        unimplemented!()
85    }
86
87    /// This should be implemented to report the values of
88    ///   child cell properties for a given child [`CellRenderer`][crate::CellRenderer].
89    fn cell_property<R: IsA<CellRenderer>>(
90        &self,
91        _renderer: &R,
92        _id: usize,
93        _pspec: &ParamSpec,
94    ) -> Value {
95        unimplemented!()
96    }
97
98    /// Activates @area, usually by activating the currently focused
99    /// cell, however some subclasses which embed widgets in the area
100    /// can also activate a widget if it currently has the focus.
101    ///
102    /// # Deprecated since 4.10
103    ///
104    /// ## `context`
105    /// the [`CellArea`][crate::CellArea]Context in context with the current row data
106    /// ## `widget`
107    /// the [`Widget`][crate::Widget] that @area is rendering on
108    /// ## `cell_area`
109    /// s allocation
110    /// ## `flags`
111    /// the [`CellRenderer`][crate::CellRenderer]State flags for @area for this row of data.
112    /// ## `edit_only`
113    /// if [`true`] then only cell renderers that are [`CellRendererMode::Editable`][crate::CellRendererMode::Editable]
114    ///             will be activated.
115    ///
116    /// # Returns
117    ///
118    /// Whether @area was successfully activated.
119    fn activate<P: IsA<CellAreaContext>, W: IsA<Widget>>(
120        &self,
121        context: &P,
122        widget: &W,
123        area: &gdk::Rectangle,
124        flags: CellRendererState,
125        edit_only: bool,
126    ) -> bool {
127        self.parent_activate(context, widget, area, flags, edit_only)
128    }
129
130    /// Adds @renderer to @area with the default child cell properties.
131    ///
132    /// # Deprecated since 4.10
133    ///
134    /// ## `renderer`
135    /// the [`CellRenderer`][crate::CellRenderer] to add to @area
136    fn add<R: IsA<CellRenderer>>(&self, renderer: &R) {
137        self.parent_add(renderer)
138    }
139
140    /// Applies any connected attributes to the renderers in
141    /// @area by pulling the values from @tree_model.
142    ///
143    /// # Deprecated since 4.10
144    ///
145    /// ## `tree_model`
146    /// the [`TreeModel`][crate::TreeModel] to pull values from
147    /// ## `iter`
148    /// the [`TreeIter`][crate::TreeIter] in @tree_model to apply values for
149    /// ## `is_expander`
150    /// whether @iter has children
151    /// ## `is_expanded`
152    /// whether @iter is expanded in the view and
153    ///               children are visible
154    fn apply_attributes<M: IsA<TreeModel>>(
155        &self,
156        tree_model: &M,
157        iter: &TreeIter,
158        is_expander: bool,
159        is_expanded: bool,
160    ) {
161        self.parent_apply_attributes(tree_model, iter, is_expander, is_expanded)
162    }
163
164    /// Creates a [`CellArea`][crate::CellArea]Context to be used with @area for
165    /// all purposes. [`CellArea`][crate::CellArea]Context stores geometry information
166    /// for rows for which it was operated on, it is important to use
167    /// the same context for the same row of data at all times (i.e.
168    /// one should render and handle events with the same [`CellArea`][crate::CellArea]Context
169    /// which was used to request the size of those rows of data).
170    ///
171    /// # Deprecated since 4.10
172    ///
173    ///
174    /// # Returns
175    ///
176    /// a newly created [`CellArea`][crate::CellArea]Context which can be used with @area.
177    fn create_context(&self) -> Option<CellAreaContext> {
178        self.parent_create_context()
179    }
180
181    /// This is sometimes needed for cases where rows need to share
182    /// alignments in one orientation but may be separately grouped
183    /// in the opposing orientation.
184    ///
185    /// For instance, [`IconView`][crate::IconView] creates all icons (rows) to have
186    /// the same width and the cells theirin to have the same
187    /// horizontal alignments. However each row of icons may have
188    /// a separate collective height. [`IconView`][crate::IconView] uses this to
189    /// request the heights of each row based on a context which
190    /// was already used to request all the row widths that are
191    /// to be displayed.
192    ///
193    /// # Deprecated since 4.10
194    ///
195    /// ## `context`
196    /// the [`CellArea`][crate::CellArea]Context to copy
197    ///
198    /// # Returns
199    ///
200    /// a newly created [`CellArea`][crate::CellArea]Context copy of @context.
201    fn copy_context<P: IsA<CellAreaContext>>(&self, context: &P) -> Option<CellAreaContext> {
202        self.parent_copy_context(context)
203    }
204
205    /// Delegates event handling to a [`CellArea`][crate::CellArea].
206    ///
207    /// # Deprecated since 4.10
208    ///
209    /// ## `context`
210    /// the [`CellArea`][crate::CellArea]Context for this row of data.
211    /// ## `widget`
212    /// the [`Widget`][crate::Widget] that @area is rendering to
213    /// ## `event`
214    /// the [`gdk::Event`][crate::gdk::Event] to handle
215    /// ## `cell_area`
216    /// the @widget relative coordinates for @area
217    /// ## `flags`
218    /// the [`CellRenderer`][crate::CellRenderer]State for @area in this row.
219    ///
220    /// # Returns
221    ///
222    /// [`true`] if the event was handled by @area.
223    fn event<W: IsA<Widget>, P: IsA<CellAreaContext>>(
224        &self,
225        context: &P,
226        widget: &W,
227        event: &gdk::Event,
228        area: &gdk::Rectangle,
229        flags: CellRendererState,
230    ) -> bool {
231        self.parent_event(context, widget, event, area, flags)
232    }
233
234    /// Calls @callback for every [`CellRenderer`][crate::CellRenderer] in @area.
235    ///
236    /// # Deprecated since 4.10
237    ///
238    /// ## `callback`
239    /// the `GtkCellCallback` to call
240    /// ## `callback_data`
241    /// user provided data pointer
242    fn foreach(&self, callback: &CellCallback) {
243        self.parent_foreach(callback);
244    }
245
246    /// Calls @callback for every [`CellRenderer`][crate::CellRenderer] in @area with the
247    /// allocated rectangle inside @cell_area.
248    ///
249    /// # Deprecated since 4.10
250    ///
251    /// ## `context`
252    /// the [`CellArea`][crate::CellArea]Context for this row of data.
253    /// ## `widget`
254    /// the [`Widget`][crate::Widget] that @area is rendering to
255    /// ## `cell_area`
256    /// the @widget relative coordinates and size for @area
257    /// ## `background_area`
258    /// the @widget relative coordinates of the background area
259    /// ## `callback`
260    /// the `GtkCellAllocCallback` to call
261    /// ## `callback_data`
262    /// user provided data pointer
263    fn foreach_alloc<P: IsA<CellAreaContext>, W: IsA<Widget>>(
264        &self,
265        context: &P,
266        widget: &W,
267        area: &gdk::Rectangle,
268        bg_area: &gdk::Rectangle,
269        callback: &CellCallbackAllocate,
270    ) {
271        self.parent_foreach_alloc(context, widget, area, bg_area, callback)
272    }
273
274    /// Removes @renderer from @area.
275    ///
276    /// # Deprecated since 4.10
277    ///
278    /// ## `renderer`
279    /// the [`CellRenderer`][crate::CellRenderer] to remove from @area
280    fn remove<R: IsA<CellRenderer>>(&self, renderer: &R) {
281        self.parent_remove(renderer)
282    }
283
284    /// Returns whether the area can do anything when activated,
285    /// after applying new attributes to @area.
286    ///
287    /// # Deprecated since 4.10
288    ///
289    ///
290    /// # Returns
291    ///
292    /// whether @area can do anything when activated.
293    fn is_activatable(&self) -> bool {
294        self.parent_is_activatable()
295    }
296
297    /// s owning layout widget
298    /// when focus is to be passed to @area, or moved within @area
299    /// for a given @direction and row data.
300    ///
301    /// Implementing [`CellArea`][crate::CellArea] classes should implement this
302    /// method to receive and navigate focus in its own way particular
303    /// to how it lays out cells.
304    ///
305    /// # Deprecated since 4.10
306    ///
307    /// ## `direction`
308    /// the [`DirectionType`][crate::DirectionType]
309    ///
310    /// # Returns
311    ///
312    /// [`true`] if focus remains inside @area as a result of this call.
313    fn focus(&self, direction_type: DirectionType) -> bool {
314        self.parent_focus(direction_type)
315    }
316
317    /// Gets whether the area prefers a height-for-width layout
318    /// or a width-for-height layout.
319    ///
320    /// # Deprecated since 4.10
321    ///
322    ///
323    /// # Returns
324    ///
325    /// The [`SizeRequestMode`][crate::SizeRequestMode] preferred by @area.
326    fn request_mode(&self) -> SizeRequestMode {
327        self.parent_request_mode()
328    }
329
330    /// s not important
331    /// to check the @minimum_width and @natural_width of this call but rather to
332    /// consult gtk_cell_area_context_get_preferred_width() after a series of
333    /// requests.
334    ///
335    /// # Deprecated since 4.10
336    ///
337    /// ## `context`
338    /// the [`CellArea`][crate::CellArea]Context to perform this request with
339    /// ## `widget`
340    /// the [`Widget`][crate::Widget] where @area will be rendering
341    ///
342    /// # Returns
343    ///
344    ///
345    /// ## `minimum_width`
346    /// location to store the minimum width
347    ///
348    /// ## `natural_width`
349    /// location to store the natural width
350    fn preferred_width<P: IsA<CellAreaContext>, W: IsA<Widget>>(
351        &self,
352        context: &P,
353        widget: &W,
354    ) -> (i32, i32) {
355        self.parent_preferred_width(context, widget)
356    }
357
358    /// s important to
359    /// perform a series of gtk_cell_area_get_preferred_height() requests with
360    /// @context first and then call gtk_cell_area_get_preferred_width_for_height()
361    /// on each cell area individually to get the height for width of each
362    /// fully requested row.
363    ///
364    /// If at some point, the height of a single row changes, it should be
365    /// requested with gtk_cell_area_get_preferred_height() again and then
366    /// the full height of the requested rows checked again with
367    /// gtk_cell_area_context_get_preferred_height().
368    ///
369    /// # Deprecated since 4.10
370    ///
371    /// ## `context`
372    /// the [`CellArea`][crate::CellArea]Context which has already been requested for widths.
373    /// ## `widget`
374    /// the [`Widget`][crate::Widget] where @area will be rendering
375    /// ## `height`
376    /// the height for which to check the width of this area
377    ///
378    /// # Returns
379    ///
380    ///
381    /// ## `minimum_width`
382    /// location to store the minimum width
383    ///
384    /// ## `natural_width`
385    /// location to store the natural width
386    fn preferred_width_for_height<P: IsA<CellAreaContext>, W: IsA<Widget>>(
387        &self,
388        context: &P,
389        widget: &W,
390        height: i32,
391    ) -> (i32, i32) {
392        self.parent_preferred_width_for_height(context, widget, height)
393    }
394
395    /// s not important
396    /// to check the @minimum_height and @natural_height of this call but rather to
397    /// consult gtk_cell_area_context_get_preferred_height() after a series of
398    /// requests.
399    ///
400    /// # Deprecated since 4.10
401    ///
402    /// ## `context`
403    /// the [`CellArea`][crate::CellArea]Context to perform this request with
404    /// ## `widget`
405    /// the [`Widget`][crate::Widget] where @area will be rendering
406    ///
407    /// # Returns
408    ///
409    ///
410    /// ## `minimum_height`
411    /// location to store the minimum height
412    ///
413    /// ## `natural_height`
414    /// location to store the natural height
415    fn preferred_height<P: IsA<CellAreaContext>, W: IsA<Widget>>(
416        &self,
417        context: &P,
418        widget: &W,
419    ) -> (i32, i32) {
420        self.parent_preferred_height(context, widget)
421    }
422
423    /// s important to
424    /// perform a series of gtk_cell_area_get_preferred_width() requests with
425    /// @context first and then call gtk_cell_area_get_preferred_height_for_width()
426    /// on each cell area individually to get the height for width of each
427    /// fully requested row.
428    ///
429    /// If at some point, the width of a single row changes, it should be
430    /// requested with gtk_cell_area_get_preferred_width() again and then
431    /// the full width of the requested rows checked again with
432    /// gtk_cell_area_context_get_preferred_width().
433    ///
434    /// # Deprecated since 4.10
435    ///
436    /// ## `context`
437    /// the [`CellArea`][crate::CellArea]Context which has already been requested for widths.
438    /// ## `widget`
439    /// the [`Widget`][crate::Widget] where @area will be rendering
440    /// ## `width`
441    /// the width for which to check the height of this area
442    ///
443    /// # Returns
444    ///
445    ///
446    /// ## `minimum_height`
447    /// location to store the minimum height
448    ///
449    /// ## `natural_height`
450    /// location to store the natural height
451    fn preferred_height_for_width<P: IsA<CellAreaContext>, W: IsA<Widget>>(
452        &self,
453        context: &P,
454        widget: &W,
455        width: i32,
456    ) -> (i32, i32) {
457        self.parent_preferred_height_for_width(context, widget, width)
458    }
459
460    /// s layout onto at
461    /// the given coordinates.
462    ///
463    /// # Deprecated since 4.10
464    ///
465    /// ## `context`
466    /// the [`CellArea`][crate::CellArea]Context for this row of data.
467    /// ## `widget`
468    /// the [`Widget`][crate::Widget] that @area is rendering to
469    /// ## `snapshot`
470    /// the [`Snapshot`][crate::Snapshot] to draw to
471    /// ## `background_area`
472    /// s background
473    /// ## `cell_area`
474    /// the @widget relative coordinates for @area
475    /// ## `flags`
476    /// the [`CellRenderer`][crate::CellRenderer]State for @area in this row.
477    /// ## `paint_focus`
478    /// whether @area should paint focus on focused cells for focused rows or not.
479    #[allow(clippy::too_many_arguments)]
480    fn snapshot<P: IsA<CellAreaContext>, W: IsA<Widget>>(
481        &self,
482        context: &P,
483        snapshot: &Snapshot,
484        widget: &W,
485        background_area: &gdk::Rectangle,
486        cellarea: &gdk::Rectangle,
487        flags: CellRendererState,
488        paint_focus: bool,
489    ) {
490        self.parent_snapshot(
491            context,
492            snapshot,
493            widget,
494            background_area,
495            cellarea,
496            flags,
497            paint_focus,
498        );
499    }
500}
501
502#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
503#[allow(deprecated)]
504pub trait CellAreaImplExt: CellAreaImpl {
505    // Returns true if the area was successfully activated
506    fn parent_activate<P: IsA<CellAreaContext>, W: IsA<Widget>>(
507        &self,
508        context: &P,
509        widget: &W,
510        area: &gdk::Rectangle,
511        flags: CellRendererState,
512        edit_only: bool,
513    ) -> bool {
514        unsafe {
515            let data = Self::type_data();
516            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
517            if let Some(f) = (*parent_class).activate {
518                from_glib(f(
519                    self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
520                    context.as_ref().to_glib_none().0,
521                    widget.as_ref().to_glib_none().0,
522                    area.to_glib_none().0,
523                    flags.into_glib(),
524                    edit_only.into_glib(),
525                ))
526            } else {
527                false
528            }
529        }
530    }
531
532    fn parent_add<R: IsA<CellRenderer>>(&self, renderer: &R) {
533        unsafe {
534            let data = Self::type_data();
535            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
536            if let Some(f) = (*parent_class).add {
537                f(
538                    self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
539                    renderer.as_ref().to_glib_none().0,
540                )
541            }
542        }
543    }
544
545    fn parent_apply_attributes<M: IsA<TreeModel>>(
546        &self,
547        tree_model: &M,
548        iter: &TreeIter,
549        is_expander: bool,
550        is_expanded: bool,
551    ) {
552        unsafe {
553            let data = Self::type_data();
554            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
555            if let Some(f) = (*parent_class).apply_attributes {
556                f(
557                    self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
558                    tree_model.as_ref().to_glib_none().0,
559                    iter.to_glib_none().0 as *mut _,
560                    is_expander.into_glib(),
561                    is_expanded.into_glib(),
562                )
563            }
564        }
565    }
566
567    fn parent_create_context(&self) -> Option<CellAreaContext> {
568        unsafe {
569            let data = Self::type_data();
570            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
571            let f = (*parent_class)
572                .create_context
573                .expect("No parent class impl for \"create_context\"");
574
575            let ret = f(self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0);
576            Some(from_glib_full(ret))
577        }
578    }
579
580    fn parent_copy_context<P: IsA<CellAreaContext>>(&self, context: &P) -> Option<CellAreaContext> {
581        unsafe {
582            let data = Self::type_data();
583            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
584            let f = (*parent_class)
585                .copy_context
586                .expect("No parent class impl for \"copy_context\"");
587
588            let ret = f(
589                self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
590                context.as_ref().to_glib_none().0,
591            );
592            Some(from_glib_full(ret))
593        }
594    }
595
596    // returns true only if the event is handled
597    fn parent_event<W: IsA<Widget>, P: IsA<CellAreaContext>>(
598        &self,
599        context: &P,
600        widget: &W,
601        event: &gdk::Event,
602        area: &gdk::Rectangle,
603        flags: CellRendererState,
604    ) -> bool {
605        unsafe {
606            let data = Self::type_data();
607            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
608            if let Some(f) = (*parent_class).event {
609                from_glib(f(
610                    self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
611                    context.as_ref().to_glib_none().0,
612                    widget.as_ref().to_glib_none().0,
613                    event.to_glib_none().0,
614                    area.to_glib_none().0,
615                    flags.into_glib(),
616                ))
617            } else {
618                false
619            }
620        }
621    }
622
623    fn parent_foreach(&self, callback: &CellCallback) {
624        unsafe {
625            let data = Self::type_data();
626            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
627            if let Some(f) = (*parent_class).foreach {
628                f(
629                    self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
630                    callback.callback,
631                    callback.user_data,
632                )
633            }
634        }
635    }
636
637    fn parent_foreach_alloc<P: IsA<CellAreaContext>, W: IsA<Widget>>(
638        &self,
639        context: &P,
640        widget: &W,
641        area: &gdk::Rectangle,
642        bg_area: &gdk::Rectangle,
643        callback: &CellCallbackAllocate,
644    ) {
645        unsafe {
646            let data = Self::type_data();
647            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
648            if let Some(f) = (*parent_class).foreach_alloc {
649                f(
650                    self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
651                    context.as_ref().to_glib_none().0,
652                    widget.as_ref().to_glib_none().0,
653                    area.to_glib_none().0,
654                    bg_area.to_glib_none().0,
655                    callback.callback,
656                    callback.user_data,
657                )
658            }
659        }
660    }
661
662    fn parent_remove<R: IsA<CellRenderer>>(&self, renderer: &R) {
663        unsafe {
664            let data = Self::type_data();
665            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
666            if let Some(f) = (*parent_class).remove {
667                f(
668                    self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
669                    renderer.as_ref().to_glib_none().0,
670                )
671            }
672        }
673    }
674
675    // Whether the cell is activatable
676    fn parent_is_activatable(&self) -> bool {
677        unsafe {
678            let data = Self::type_data();
679            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
680            if let Some(f) = (*parent_class).is_activatable {
681                from_glib(f(self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0))
682            } else {
683                false
684            }
685        }
686    }
687
688    // TRUE if focus remains inside area as a result of this call.
689    fn parent_focus(&self, direction_type: DirectionType) -> bool {
690        unsafe {
691            let data = Self::type_data();
692            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
693            if let Some(f) = (*parent_class).focus {
694                from_glib(f(
695                    self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
696                    direction_type.into_glib(),
697                ))
698            } else {
699                false
700            }
701        }
702    }
703
704    fn parent_request_mode(&self) -> SizeRequestMode {
705        unsafe {
706            let data = Self::type_data();
707            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
708            let f = (*parent_class)
709                .get_request_mode
710                .expect("No parent class impl for \"get_request_mode\"");
711            from_glib(f(self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0))
712        }
713    }
714
715    fn parent_preferred_width<P: IsA<CellAreaContext>, W: IsA<Widget>>(
716        &self,
717        cell_area_context: &P,
718        widget: &W,
719    ) -> (i32, i32) {
720        unsafe {
721            let data = Self::type_data();
722            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
723            let f = (*parent_class).get_preferred_width.unwrap();
724
725            let mut minimum_size = mem::MaybeUninit::uninit();
726            let mut natural_size = mem::MaybeUninit::uninit();
727            f(
728                self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
729                cell_area_context.as_ref().to_glib_none().0,
730                widget.as_ref().to_glib_none().0,
731                minimum_size.as_mut_ptr(),
732                natural_size.as_mut_ptr(),
733            );
734            (minimum_size.assume_init(), natural_size.assume_init())
735        }
736    }
737
738    fn parent_preferred_height<P: IsA<CellAreaContext>, W: IsA<Widget>>(
739        &self,
740        cell_area_context: &P,
741        widget: &W,
742    ) -> (i32, i32) {
743        unsafe {
744            let data = Self::type_data();
745            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
746            let f = (*parent_class).get_preferred_height.unwrap();
747
748            let mut minimum_size = mem::MaybeUninit::uninit();
749            let mut natural_size = mem::MaybeUninit::uninit();
750            f(
751                self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
752                cell_area_context.as_ref().to_glib_none().0,
753                widget.as_ref().to_glib_none().0,
754                minimum_size.as_mut_ptr(),
755                natural_size.as_mut_ptr(),
756            );
757            (minimum_size.assume_init(), natural_size.assume_init())
758        }
759    }
760
761    fn parent_preferred_width_for_height<P: IsA<CellAreaContext>, W: IsA<Widget>>(
762        &self,
763        cell_area_context: &P,
764        widget: &W,
765        height: i32,
766    ) -> (i32, i32) {
767        unsafe {
768            let data = Self::type_data();
769            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
770            let f = (*parent_class).get_preferred_width_for_height.unwrap();
771
772            let mut minimum_size = mem::MaybeUninit::uninit();
773            let mut natural_size = mem::MaybeUninit::uninit();
774            f(
775                self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
776                cell_area_context.as_ref().to_glib_none().0,
777                widget.as_ref().to_glib_none().0,
778                height,
779                minimum_size.as_mut_ptr(),
780                natural_size.as_mut_ptr(),
781            );
782            (minimum_size.assume_init(), natural_size.assume_init())
783        }
784    }
785
786    fn parent_preferred_height_for_width<P: IsA<CellAreaContext>, W: IsA<Widget>>(
787        &self,
788        cell_area_context: &P,
789        widget: &W,
790        width: i32,
791    ) -> (i32, i32) {
792        unsafe {
793            let data = Self::type_data();
794            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
795            let f = (*parent_class).get_preferred_height_for_width.unwrap();
796            let mut minimum_size = mem::MaybeUninit::uninit();
797            let mut natural_size = mem::MaybeUninit::uninit();
798            f(
799                self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
800                cell_area_context.as_ref().to_glib_none().0,
801                widget.as_ref().to_glib_none().0,
802                width,
803                minimum_size.as_mut_ptr(),
804                natural_size.as_mut_ptr(),
805            );
806            (minimum_size.assume_init(), natural_size.assume_init())
807        }
808    }
809
810    #[allow(clippy::too_many_arguments)]
811    fn parent_snapshot<P: IsA<CellAreaContext>, W: IsA<Widget>>(
812        &self,
813        context: &P,
814        snapshot: &Snapshot,
815        widget: &W,
816        background_area: &gdk::Rectangle,
817        cellarea: &gdk::Rectangle,
818        flags: CellRendererState,
819        paint_focus: bool,
820    ) {
821        unsafe {
822            let data = Self::type_data();
823            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellAreaClass;
824            if let Some(f) = (*parent_class).snapshot {
825                f(
826                    self.obj().unsafe_cast_ref::<CellArea>().to_glib_none().0,
827                    context.as_ref().to_glib_none().0,
828                    widget.as_ref().to_glib_none().0,
829                    snapshot.to_glib_none().0,
830                    background_area.to_glib_none().0,
831                    cellarea.to_glib_none().0,
832                    flags.into_glib(),
833                    paint_focus.into_glib(),
834                )
835            }
836        }
837    }
838}
839
840impl<T: CellAreaImpl> CellAreaImplExt for T {}
841
842unsafe impl<T: CellAreaImpl> IsSubclassable<T> for CellArea {
843    fn class_init(class: &mut glib::Class<Self>) {
844        Self::parent_class_init::<T>(class);
845        let klass = class.as_mut();
846
847        assert_initialized_main_thread!();
848
849        let pspecs = <T as CellAreaImpl>::cell_properties();
850        if !pspecs.is_empty() {
851            unsafe {
852                for (prop_id, pspec) in pspecs.iter().enumerate() {
853                    ffi::gtk_cell_area_class_install_cell_property(
854                        klass,
855                        prop_id as u32,
856                        pspec.to_glib_none().0,
857                    );
858                }
859            }
860        }
861        klass.activate = Some(cell_area_activate::<T>);
862        klass.add = Some(cell_area_add::<T>);
863        klass.apply_attributes = Some(cell_area_apply_attributes::<T>);
864        klass.create_context = Some(cell_area_create_context::<T>);
865        klass.copy_context = Some(cell_area_copy_context::<T>);
866        klass.event = Some(cell_area_event::<T>);
867        klass.foreach = Some(cell_area_foreach::<T>);
868        klass.foreach_alloc = Some(cell_area_foreach_alloc::<T>);
869        klass.remove = Some(cell_area_remove::<T>);
870        klass.is_activatable = Some(cell_area_is_activatable::<T>);
871        klass.focus = Some(cell_area_focus::<T>);
872        klass.get_request_mode = Some(cell_area_get_request_mode::<T>);
873        klass.get_preferred_width = Some(cell_area_get_preferred_width::<T>);
874        klass.get_preferred_width_for_height = Some(cell_area_get_preferred_width_for_height::<T>);
875        klass.get_preferred_height = Some(cell_area_get_preferred_height::<T>);
876        klass.get_preferred_height_for_width = Some(cell_area_get_preferred_height_for_width::<T>);
877        klass.snapshot = Some(cell_area_snapshot::<T>);
878        klass.set_cell_property = Some(cell_area_set_cell_property::<T>);
879        klass.get_cell_property = Some(cell_area_get_cell_property::<T>);
880    }
881}
882
883unsafe extern "C" fn cell_area_set_cell_property<T: CellAreaImpl>(
884    ptr: *mut ffi::GtkCellArea,
885    rendererptr: *mut ffi::GtkCellRenderer,
886    id: u32,
887    valueptr: *mut glib::gobject_ffi::GValue,
888    pspecptr: *mut glib::gobject_ffi::GParamSpec,
889) {
890    unsafe {
891        let instance = &*(ptr as *mut T::Instance);
892        let imp = instance.imp();
893        imp.set_cell_property(
894            &*from_glib_borrow::<_, CellRenderer>(rendererptr),
895            id as usize,
896            &*(valueptr as *mut Value),
897            &from_glib_borrow(pspecptr),
898        );
899    }
900}
901
902unsafe extern "C" fn cell_area_get_cell_property<T: CellAreaImpl>(
903    ptr: *mut ffi::GtkCellArea,
904    rendererptr: *mut ffi::GtkCellRenderer,
905    id: u32,
906    valueptr: *mut glib::gobject_ffi::GValue,
907    pspecptr: *mut glib::gobject_ffi::GParamSpec,
908) {
909    unsafe {
910        let instance = &*(ptr as *mut T::Instance);
911        let imp = instance.imp();
912
913        let value = imp.cell_property(
914            &*from_glib_borrow::<_, CellRenderer>(rendererptr),
915            id as usize,
916            &from_glib_borrow(pspecptr),
917        );
918
919        // See glib::subclass::ObjectImpl::property for the reasoning behind
920        glib::gobject_ffi::g_value_unset(valueptr);
921        let value = mem::ManuallyDrop::new(value);
922        std::ptr::write(valueptr, std::ptr::read(value.to_glib_none().0));
923    }
924}
925
926unsafe extern "C" fn cell_area_add<T: CellAreaImpl>(
927    ptr: *mut ffi::GtkCellArea,
928    rendererptr: *mut ffi::GtkCellRenderer,
929) {
930    unsafe {
931        let instance = &*(ptr as *mut T::Instance);
932        let imp = instance.imp();
933        let renderer: Borrowed<CellRenderer> = from_glib_borrow(rendererptr);
934
935        imp.add(&*renderer)
936    }
937}
938
939unsafe extern "C" fn cell_area_apply_attributes<T: CellAreaImpl>(
940    ptr: *mut ffi::GtkCellArea,
941    modelptr: *mut ffi::GtkTreeModel,
942    iterptr: *mut ffi::GtkTreeIter,
943    is_expander: glib::ffi::gboolean,
944    is_expanded: glib::ffi::gboolean,
945) {
946    unsafe {
947        let instance = &*(ptr as *mut T::Instance);
948        let imp = instance.imp();
949        let model: Borrowed<TreeModel> = from_glib_borrow(modelptr);
950        let iter: Borrowed<TreeIter> = from_glib_borrow(iterptr);
951
952        imp.apply_attributes(
953            &*model,
954            &iter,
955            from_glib(is_expander),
956            from_glib(is_expanded),
957        )
958    }
959}
960
961unsafe extern "C" fn cell_area_remove<T: CellAreaImpl>(
962    ptr: *mut ffi::GtkCellArea,
963    rendererptr: *mut ffi::GtkCellRenderer,
964) {
965    unsafe {
966        let instance = &*(ptr as *mut T::Instance);
967        let imp = instance.imp();
968        let renderer: Borrowed<CellRenderer> = from_glib_borrow(rendererptr);
969
970        imp.remove(&*renderer)
971    }
972}
973
974unsafe extern "C" fn cell_area_is_activatable<T: CellAreaImpl>(
975    ptr: *mut ffi::GtkCellArea,
976) -> glib::ffi::gboolean {
977    unsafe {
978        let instance = &*(ptr as *mut T::Instance);
979        let imp = instance.imp();
980
981        imp.is_activatable().into_glib()
982    }
983}
984
985unsafe extern "C" fn cell_area_focus<T: CellAreaImpl>(
986    ptr: *mut ffi::GtkCellArea,
987    directionptr: ffi::GtkDirectionType,
988) -> glib::ffi::gboolean {
989    unsafe {
990        let instance = &*(ptr as *mut T::Instance);
991        let imp = instance.imp();
992
993        imp.focus(from_glib(directionptr)).into_glib()
994    }
995}
996
997unsafe extern "C" fn cell_area_get_request_mode<T: CellAreaImpl>(
998    ptr: *mut ffi::GtkCellArea,
999) -> ffi::GtkSizeRequestMode {
1000    unsafe {
1001        let instance = &*(ptr as *mut T::Instance);
1002        let imp = instance.imp();
1003
1004        imp.request_mode().into_glib()
1005    }
1006}
1007
1008unsafe extern "C" fn cell_area_get_preferred_height<T: CellAreaImpl>(
1009    ptr: *mut ffi::GtkCellArea,
1010    contextptr: *mut ffi::GtkCellAreaContext,
1011    wdgtptr: *mut ffi::GtkWidget,
1012    minptr: *mut libc::c_int,
1013    natptr: *mut libc::c_int,
1014) {
1015    unsafe {
1016        let instance = &*(ptr as *mut T::Instance);
1017        let imp = instance.imp();
1018        let context: Borrowed<CellAreaContext> = from_glib_borrow(contextptr);
1019        let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
1020
1021        let (min_size, nat_size) = imp.preferred_height(&*context, &*widget);
1022        if !minptr.is_null() {
1023            *minptr = min_size;
1024        }
1025        if !natptr.is_null() {
1026            *natptr = nat_size;
1027        }
1028    }
1029}
1030
1031unsafe extern "C" fn cell_area_get_preferred_width<T: CellAreaImpl>(
1032    ptr: *mut ffi::GtkCellArea,
1033    contextptr: *mut ffi::GtkCellAreaContext,
1034    wdgtptr: *mut ffi::GtkWidget,
1035    minptr: *mut libc::c_int,
1036    natptr: *mut libc::c_int,
1037) {
1038    unsafe {
1039        let instance = &*(ptr as *mut T::Instance);
1040        let imp = instance.imp();
1041        let context: Borrowed<CellAreaContext> = from_glib_borrow(contextptr);
1042        let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
1043
1044        let (min_size, nat_size) = imp.preferred_width(&*context, &*widget);
1045        if !minptr.is_null() {
1046            *minptr = min_size;
1047        }
1048        if !natptr.is_null() {
1049            *natptr = nat_size;
1050        }
1051    }
1052}
1053
1054unsafe extern "C" fn cell_area_get_preferred_width_for_height<T: CellAreaImpl>(
1055    ptr: *mut ffi::GtkCellArea,
1056    contextptr: *mut ffi::GtkCellAreaContext,
1057    wdgtptr: *mut ffi::GtkWidget,
1058    height: i32,
1059    min_width_ptr: *mut libc::c_int,
1060    nat_width_ptr: *mut libc::c_int,
1061) {
1062    unsafe {
1063        let instance = &*(ptr as *mut T::Instance);
1064        let imp = instance.imp();
1065        let context: Borrowed<CellAreaContext> = from_glib_borrow(contextptr);
1066        let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
1067
1068        let (min_width, nat_width) = imp.preferred_width_for_height(&*context, &*widget, height);
1069        if !min_width_ptr.is_null() {
1070            *min_width_ptr = min_width;
1071        }
1072        if !nat_width_ptr.is_null() {
1073            *nat_width_ptr = nat_width;
1074        }
1075    }
1076}
1077
1078unsafe extern "C" fn cell_area_get_preferred_height_for_width<T: CellAreaImpl>(
1079    ptr: *mut ffi::GtkCellArea,
1080    contextptr: *mut ffi::GtkCellAreaContext,
1081    wdgtptr: *mut ffi::GtkWidget,
1082    width: i32,
1083    min_height_ptr: *mut libc::c_int,
1084    nat_height_ptr: *mut libc::c_int,
1085) {
1086    unsafe {
1087        let instance = &*(ptr as *mut T::Instance);
1088        let imp = instance.imp();
1089        let context: Borrowed<CellAreaContext> = from_glib_borrow(contextptr);
1090        let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
1091
1092        let (min_height, nat_height) = imp.preferred_height_for_width(&*context, &*widget, width);
1093        if !min_height_ptr.is_null() {
1094            *min_height_ptr = min_height;
1095        }
1096        if !nat_height_ptr.is_null() {
1097            *nat_height_ptr = nat_height;
1098        }
1099    }
1100}
1101
1102unsafe extern "C" fn cell_area_activate<T: CellAreaImpl>(
1103    ptr: *mut ffi::GtkCellArea,
1104    contextptr: *mut ffi::GtkCellAreaContext,
1105    wdgtptr: *mut ffi::GtkWidget,
1106    cellptr: *const gdk::ffi::GdkRectangle,
1107    flags: ffi::GtkCellRendererState,
1108    edit_only: glib::ffi::gboolean,
1109) -> glib::ffi::gboolean {
1110    unsafe {
1111        let instance = &*(ptr as *mut T::Instance);
1112        let imp = instance.imp();
1113        let context: Borrowed<CellAreaContext> = from_glib_borrow(contextptr);
1114        let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
1115
1116        imp.activate(
1117            &*context,
1118            &*widget,
1119            &from_glib_borrow(cellptr),
1120            from_glib(flags),
1121            from_glib(edit_only),
1122        )
1123        .into_glib()
1124    }
1125}
1126
1127unsafe extern "C" fn cell_area_snapshot<T: CellAreaImpl>(
1128    ptr: *mut ffi::GtkCellArea,
1129    contextptr: *mut ffi::GtkCellAreaContext,
1130    wdgtptr: *mut ffi::GtkWidget,
1131    snapshotptr: *mut ffi::GtkSnapshot,
1132    bgptr: *const gdk::ffi::GdkRectangle,
1133    cellptr: *const gdk::ffi::GdkRectangle,
1134    flags: ffi::GtkCellRendererState,
1135    paint_focus: glib::ffi::gboolean,
1136) {
1137    unsafe {
1138        let instance = &*(ptr as *mut T::Instance);
1139        let imp = instance.imp();
1140        let context: Borrowed<CellAreaContext> = from_glib_borrow(contextptr);
1141        let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
1142        let snapshot: Borrowed<Snapshot> = from_glib_borrow(snapshotptr);
1143
1144        imp.snapshot(
1145            &*context,
1146            &snapshot,
1147            &*widget,
1148            &from_glib_borrow(bgptr),
1149            &from_glib_borrow(cellptr),
1150            from_glib(flags),
1151            from_glib(paint_focus),
1152        )
1153    }
1154}
1155
1156unsafe extern "C" fn cell_area_create_context<T: CellAreaImpl>(
1157    ptr: *mut ffi::GtkCellArea,
1158) -> *mut ffi::GtkCellAreaContext {
1159    unsafe {
1160        let instance = &*(ptr as *mut T::Instance);
1161        let imp = instance.imp();
1162
1163        imp.create_context().into_glib_ptr()
1164    }
1165}
1166
1167unsafe extern "C" fn cell_area_copy_context<T: CellAreaImpl>(
1168    ptr: *mut ffi::GtkCellArea,
1169    contextptr: *mut ffi::GtkCellAreaContext,
1170) -> *mut ffi::GtkCellAreaContext {
1171    unsafe {
1172        let instance = &*(ptr as *mut T::Instance);
1173        let imp = instance.imp();
1174        let context: Borrowed<CellAreaContext> = from_glib_borrow(contextptr);
1175
1176        imp.copy_context(&*context).into_glib_ptr()
1177    }
1178}
1179
1180unsafe extern "C" fn cell_area_event<T: CellAreaImpl>(
1181    ptr: *mut ffi::GtkCellArea,
1182    contextptr: *mut ffi::GtkCellAreaContext,
1183    widgetptr: *mut ffi::GtkWidget,
1184    eventptr: *mut gdk::ffi::GdkEvent,
1185    rectangleptr: *const gdk::ffi::GdkRectangle,
1186    flags: ffi::GtkCellRendererState,
1187) -> glib::ffi::gboolean {
1188    unsafe {
1189        let instance = &*(ptr as *mut T::Instance);
1190        let imp = instance.imp();
1191        let context: Borrowed<CellAreaContext> = from_glib_borrow(contextptr);
1192        let widget: Borrowed<Widget> = from_glib_borrow(widgetptr);
1193        let event: Borrowed<gdk::Event> = from_glib_borrow(eventptr);
1194        let rectangle: Borrowed<gdk::Rectangle> = from_glib_borrow(rectangleptr);
1195
1196        imp.event(&*context, &*widget, &event, &rectangle, from_glib(flags))
1197            .into_glib()
1198    }
1199}
1200
1201unsafe extern "C" fn cell_area_foreach<T: CellAreaImpl>(
1202    ptr: *mut ffi::GtkCellArea,
1203    callback: ffi::GtkCellCallback,
1204    user_data: glib::ffi::gpointer,
1205) {
1206    unsafe {
1207        let instance = &*(ptr as *mut T::Instance);
1208        let imp = instance.imp();
1209
1210        let callback = CellCallback {
1211            callback,
1212            user_data,
1213        };
1214
1215        imp.foreach(&callback)
1216    }
1217}
1218
1219unsafe extern "C" fn cell_area_foreach_alloc<T: CellAreaImpl>(
1220    ptr: *mut ffi::GtkCellArea,
1221    contextptr: *mut ffi::GtkCellAreaContext,
1222    widgetptr: *mut ffi::GtkWidget,
1223    areaptr: *const gdk::ffi::GdkRectangle,
1224    rectangleptr: *const gdk::ffi::GdkRectangle,
1225    callback: ffi::GtkCellAllocCallback,
1226    user_data: glib::ffi::gpointer,
1227) {
1228    unsafe {
1229        let instance = &*(ptr as *mut T::Instance);
1230        let imp = instance.imp();
1231        let context: Borrowed<CellAreaContext> = from_glib_borrow(contextptr);
1232        let widget: Borrowed<Widget> = from_glib_borrow(widgetptr);
1233        let rectangle: Borrowed<gdk::Rectangle> = from_glib_borrow(rectangleptr);
1234        let area: Borrowed<gdk::Rectangle> = from_glib_borrow(areaptr);
1235
1236        let callback = CellCallbackAllocate {
1237            callback,
1238            user_data,
1239        };
1240
1241        imp.foreach_alloc(&*context, &*widget, &area, &rectangle, &callback)
1242    }
1243}
1244
1245#[allow(clippy::missing_safety_doc)]
1246pub unsafe trait CellAreaClassExt: ClassStruct {
1247    /// Finds a cell property of a cell area class by name.
1248    ///
1249    /// # Deprecated since 4.10
1250    ///
1251    /// ## `property_name`
1252    /// the name of the child property to find
1253    ///
1254    /// # Returns
1255    ///
1256    /// the `GParamSpec` of the child property
1257    #[doc(alias = "gtk_cell_area_class_find_cell_property")]
1258    fn find_cell_property(&self, property_name: &str) -> Option<ParamSpec> {
1259        unsafe {
1260            let cell_area_class = self as *const _ as *mut ffi::GtkCellAreaClass;
1261            from_glib_none(ffi::gtk_cell_area_class_find_cell_property(
1262                cell_area_class,
1263                property_name.to_glib_none().0,
1264            ))
1265        }
1266    }
1267
1268    /// Returns all cell properties of a cell area class.
1269    ///
1270    /// # Deprecated since 4.10
1271    ///
1272    ///
1273    /// # Returns
1274    ///
1275    /// a newly
1276    ///     allocated [`None`]-terminated array of `GParamSpec`*.  The array
1277    ///     must be freed with g_free().
1278    #[doc(alias = "gtk_cell_area_class_list_cell_properties")]
1279    fn list_cell_properties(&self) -> Vec<ParamSpec> {
1280        unsafe {
1281            let cell_area_class = self as *const _ as *mut ffi::GtkCellAreaClass;
1282            let mut n_properties = std::mem::MaybeUninit::uninit();
1283            let props = ffi::gtk_cell_area_class_list_cell_properties(
1284                cell_area_class,
1285                n_properties.as_mut_ptr(),
1286            );
1287            FromGlibContainer::from_glib_none_num(props, n_properties.assume_init() as usize)
1288        }
1289    }
1290}
1291
1292unsafe impl<T: ClassStruct> CellAreaClassExt for T {}