1use std::mem;
7
8use glib::{translate::*, GString};
9use libc::{c_char, c_int};
10
11use crate::{
12 ffi, prelude::*, subclass::prelude::*, CellEditable, CellRenderer, CellRendererState,
13 SizeRequestMode, Snapshot, Widget,
14};
15
16#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
17#[allow(deprecated)]
18pub trait CellRendererImpl: CellRendererImplExt + ObjectImpl {
19 fn activate<P: IsA<Widget>>(
43 &self,
44 event: Option<&gdk::Event>,
45 widget: &P,
46 path: &str,
47 background_area: &gdk::Rectangle,
48 cell_area: &gdk::Rectangle,
49 flags: CellRendererState,
50 ) -> bool {
51 self.parent_activate(event, widget, path, background_area, cell_area, flags)
52 }
53
54 fn editing_canceled(&self) {
56 self.parent_editing_canceled()
57 }
58
59 fn editing_started(&self, editable: &CellEditable, path: &str) {
61 self.parent_editing_started(editable, path)
62 }
63
64 #[doc(alias = "get_aligned_area")]
83 fn aligned_area<P: IsA<Widget>>(
84 &self,
85 widget: &P,
86 flags: CellRendererState,
87 cell_area: &gdk::Rectangle,
88 ) -> gdk::Rectangle {
89 self.parent_aligned_area(widget, flags, cell_area)
90 }
91
92 #[doc(alias = "get_preferred_height_for_width")]
111 fn preferred_height_for_width<P: IsA<Widget>>(&self, widget: &P, width: i32) -> (i32, i32) {
112 self.parent_preferred_height_for_width(widget, width)
113 }
114
115 #[doc(alias = "get_preferred_height")]
131 fn preferred_height<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
132 self.parent_preferred_height(widget)
133 }
134
135 #[doc(alias = "get_preferred_width_for_height")]
154 fn preferred_width_for_height<P: IsA<Widget>>(&self, widget: &P, height: i32) -> (i32, i32) {
155 self.parent_preferred_width_for_height(widget, height)
156 }
157
158 #[doc(alias = "get_preferred_width")]
174 fn preferred_width<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
175 self.parent_preferred_width(widget)
176 }
177
178 #[doc(alias = "get_request_mode")]
188 fn request_mode(&self) -> SizeRequestMode {
189 self.parent_request_mode()
190 }
191
192 fn snapshot<P: IsA<Widget>>(
214 &self,
215 snapshot: &Snapshot,
216 widget: &P,
217 background_area: &gdk::Rectangle,
218 cell_area: &gdk::Rectangle,
219 flags: CellRendererState,
220 ) {
221 self.parent_snapshot(snapshot, widget, background_area, cell_area, flags);
222 }
223
224 fn start_editing<P: IsA<Widget>>(
248 &self,
249 event: Option<&gdk::Event>,
250 widget: &P,
251 path: &str,
252 background_area: &gdk::Rectangle,
253 cell_area: &gdk::Rectangle,
254 flags: CellRendererState,
255 ) -> Option<CellEditable> {
256 self.parent_start_editing(event, widget, path, background_area, cell_area, flags)
257 }
258}
259
260mod sealed {
261 pub trait Sealed {}
262 impl<T: super::CellRendererImplExt> Sealed for T {}
263}
264
265#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
266#[allow(deprecated)]
267pub trait CellRendererImplExt: sealed::Sealed + ObjectSubclass {
268 fn parent_request_mode(&self) -> SizeRequestMode {
269 unsafe {
270 let data = Self::type_data();
271 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
272 let f = (*parent_class).get_request_mode.unwrap();
273 from_glib(f(self
274 .obj()
275 .unsafe_cast_ref::<CellRenderer>()
276 .to_glib_none()
277 .0))
278 }
279 }
280
281 fn parent_preferred_width<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
282 unsafe {
283 let data = Self::type_data();
284 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
285 let f = (*parent_class).get_preferred_width.unwrap();
286
287 let mut minimum_size = mem::MaybeUninit::uninit();
288 let mut natural_size = mem::MaybeUninit::uninit();
289 f(
290 self.obj()
291 .unsafe_cast_ref::<CellRenderer>()
292 .to_glib_none()
293 .0,
294 widget.as_ref().to_glib_none().0,
295 minimum_size.as_mut_ptr(),
296 natural_size.as_mut_ptr(),
297 );
298 (minimum_size.assume_init(), natural_size.assume_init())
299 }
300 }
301
302 fn parent_preferred_width_for_height<P: IsA<Widget>>(
303 &self,
304 widget: &P,
305 height: i32,
306 ) -> (i32, i32) {
307 unsafe {
308 let data = Self::type_data();
309 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
310 let f = (*parent_class).get_preferred_width_for_height.unwrap();
311
312 let mut minimum_size = mem::MaybeUninit::uninit();
313 let mut natural_size = mem::MaybeUninit::uninit();
314 f(
315 self.obj()
316 .unsafe_cast_ref::<CellRenderer>()
317 .to_glib_none()
318 .0,
319 widget.as_ref().to_glib_none().0,
320 height,
321 minimum_size.as_mut_ptr(),
322 natural_size.as_mut_ptr(),
323 );
324 (minimum_size.assume_init(), natural_size.assume_init())
325 }
326 }
327 fn parent_preferred_height<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
328 unsafe {
329 let data = Self::type_data();
330 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
331 let f = (*parent_class).get_preferred_height.unwrap();
332 let mut minimum_size = mem::MaybeUninit::uninit();
333 let mut natural_size = mem::MaybeUninit::uninit();
334 f(
335 self.obj()
336 .unsafe_cast_ref::<CellRenderer>()
337 .to_glib_none()
338 .0,
339 widget.as_ref().to_glib_none().0,
340 minimum_size.as_mut_ptr(),
341 natural_size.as_mut_ptr(),
342 );
343 (minimum_size.assume_init(), natural_size.assume_init())
344 }
345 }
346 fn parent_preferred_height_for_width<P: IsA<Widget>>(
347 &self,
348 widget: &P,
349 width: i32,
350 ) -> (i32, i32) {
351 unsafe {
352 let data = Self::type_data();
353 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
354 let f = (*parent_class).get_preferred_height_for_width.unwrap();
355 let mut minimum_size = mem::MaybeUninit::uninit();
356 let mut natural_size = mem::MaybeUninit::uninit();
357 f(
358 self.obj()
359 .unsafe_cast_ref::<CellRenderer>()
360 .to_glib_none()
361 .0,
362 widget.as_ref().to_glib_none().0,
363 width,
364 minimum_size.as_mut_ptr(),
365 natural_size.as_mut_ptr(),
366 );
367 (minimum_size.assume_init(), natural_size.assume_init())
368 }
369 }
370
371 fn parent_aligned_area<P: IsA<Widget>>(
372 &self,
373 widget: &P,
374 flags: CellRendererState,
375 cell_area: &gdk::Rectangle,
376 ) -> gdk::Rectangle {
377 unsafe {
378 let data = Self::type_data();
379 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
380 let mut aligned_area = gdk::Rectangle::uninitialized();
381 let f = (*parent_class).get_aligned_area.unwrap();
382 f(
383 self.obj()
384 .unsafe_cast_ref::<CellRenderer>()
385 .to_glib_none()
386 .0,
387 widget.as_ref().to_glib_none().0,
388 flags.into_glib(),
389 cell_area.to_glib_none().0,
390 aligned_area.to_glib_none_mut().0,
391 );
392 aligned_area
393 }
394 }
395
396 fn parent_snapshot<P: IsA<Widget>>(
397 &self,
398 snapshot: &Snapshot,
399 widget: &P,
400 background_area: &gdk::Rectangle,
401 cell_area: &gdk::Rectangle,
402 flags: CellRendererState,
403 ) {
404 unsafe {
405 let data = Self::type_data();
406 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
407 if let Some(f) = (*parent_class).snapshot {
408 f(
409 self.obj()
410 .unsafe_cast_ref::<CellRenderer>()
411 .to_glib_none()
412 .0,
413 snapshot.to_glib_none().0,
414 widget.as_ref().to_glib_none().0,
415 background_area.to_glib_none().0,
416 cell_area.to_glib_none().0,
417 flags.into_glib(),
418 )
419 }
420 }
421 }
422
423 fn parent_activate<P: IsA<Widget>>(
425 &self,
426 event: Option<&gdk::Event>,
427 widget: &P,
428 path: &str,
429 background_area: &gdk::Rectangle,
430 cell_area: &gdk::Rectangle,
431 flags: CellRendererState,
432 ) -> bool {
433 unsafe {
434 let data = Self::type_data();
435 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
436 if let Some(f) = (*parent_class).activate {
437 from_glib(f(
438 self.obj()
439 .unsafe_cast_ref::<CellRenderer>()
440 .to_glib_none()
441 .0,
442 mut_override(event.to_glib_none().0),
443 widget.as_ref().to_glib_none().0,
444 path.to_glib_none().0,
445 background_area.to_glib_none().0,
446 cell_area.to_glib_none().0,
447 flags.into_glib(),
448 ))
449 } else {
450 false
451 }
452 }
453 }
454
455 fn parent_start_editing<P: IsA<Widget>>(
456 &self,
457 event: Option<&gdk::Event>,
458 widget: &P,
459 path: &str,
460 background_area: &gdk::Rectangle,
461 cell_area: &gdk::Rectangle,
462 flags: CellRendererState,
463 ) -> Option<CellEditable> {
464 unsafe {
465 let data = Self::type_data();
466 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
467 if let Some(f) = (*parent_class).start_editing {
468 from_glib_none(f(
469 self.obj()
470 .unsafe_cast_ref::<CellRenderer>()
471 .to_glib_none()
472 .0,
473 mut_override(event.to_glib_none().0),
474 widget.as_ref().to_glib_none().0,
475 path.to_glib_none().0,
476 background_area.to_glib_none().0,
477 cell_area.to_glib_none().0,
478 flags.into_glib(),
479 ))
480 } else {
481 None
482 }
483 }
484 }
485
486 fn parent_editing_canceled(&self) {
487 unsafe {
488 let data = Self::type_data();
489 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
490 if let Some(f) = (*parent_class).editing_canceled {
491 f(self
492 .obj()
493 .unsafe_cast_ref::<CellRenderer>()
494 .to_glib_none()
495 .0)
496 }
497 }
498 }
499
500 fn parent_editing_started(&self, editable: &CellEditable, path: &str) {
501 unsafe {
502 let data = Self::type_data();
503 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
504 if let Some(f) = (*parent_class).editing_started {
505 f(
506 self.obj()
507 .unsafe_cast_ref::<CellRenderer>()
508 .to_glib_none()
509 .0,
510 editable.to_glib_none().0,
511 path.to_glib_none().0,
512 )
513 }
514 }
515 }
516}
517
518impl<T: CellRendererImpl> CellRendererImplExt for T {}
519
520unsafe impl<T: CellRendererImpl> IsSubclassable<T> for CellRenderer {
521 fn class_init(class: &mut ::glib::Class<Self>) {
522 Self::parent_class_init::<T>(class);
523
524 assert_initialized_main_thread!();
525
526 let klass = class.as_mut();
527
528 klass.activate = Some(cell_renderer_activate::<T>);
529 klass.editing_canceled = Some(cell_renderer_editing_canceled::<T>);
530 klass.editing_started = Some(cell_renderer_editing_started::<T>);
531 klass.get_aligned_area = Some(cell_renderer_get_aligned_area::<T>);
532 klass.get_preferred_height_for_width =
533 Some(cell_renderer_get_preferred_height_for_width::<T>);
534 klass.get_preferred_height = Some(cell_renderer_get_preferred_height::<T>);
535 klass.get_preferred_width_for_height =
536 Some(cell_renderer_get_preferred_width_for_height::<T>);
537 klass.get_preferred_width = Some(cell_renderer_get_preferred_width::<T>);
538 klass.get_request_mode = Some(cell_renderer_get_request_mode::<T>);
539 klass.snapshot = Some(cell_renderer_snapshot::<T>);
540 klass.start_editing = Some(cell_renderer_start_editing::<T>);
541 }
542}
543
544unsafe extern "C" fn cell_renderer_activate<T: CellRendererImpl>(
545 ptr: *mut ffi::GtkCellRenderer,
546 evtptr: *mut gdk::ffi::GdkEvent,
547 wdgtptr: *mut ffi::GtkWidget,
548 pathptr: *const c_char,
549 bgptr: *const gdk::ffi::GdkRectangle,
550 cellptr: *const gdk::ffi::GdkRectangle,
551 flags: ffi::GtkCellRendererState,
552) -> glib::ffi::gboolean {
553 let instance = &*(ptr as *mut T::Instance);
554 let imp = instance.imp();
555 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
556 let evt: Borrowed<Option<gdk::Event>> = from_glib_borrow(evtptr);
557
558 imp.activate(
559 evt.as_ref().as_ref(),
560 &*widget,
561 &GString::from_glib_borrow(pathptr),
562 &from_glib_borrow(bgptr),
563 &from_glib_borrow(cellptr),
564 from_glib(flags),
565 )
566 .into_glib()
567}
568
569unsafe extern "C" fn cell_renderer_editing_canceled<T: CellRendererImpl>(
570 ptr: *mut ffi::GtkCellRenderer,
571) {
572 let instance = &*(ptr as *mut T::Instance);
573 let imp = instance.imp();
574
575 imp.editing_canceled();
576}
577
578unsafe extern "C" fn cell_renderer_editing_started<T: CellRendererImpl>(
579 ptr: *mut ffi::GtkCellRenderer,
580 editableptr: *mut ffi::GtkCellEditable,
581 pathptr: *const c_char,
582) {
583 let instance = &*(ptr as *mut T::Instance);
584 let imp = instance.imp();
585 let editable = from_glib_borrow(editableptr);
586
587 imp.editing_started(&editable, &GString::from_glib_borrow(pathptr));
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_get_preferred_height_for_width<T: CellRendererImpl>(
606 ptr: *mut ffi::GtkCellRenderer,
607 wdgtptr: *mut ffi::GtkWidget,
608 width: c_int,
609 min_height_ptr: *mut c_int,
610 nat_height_ptr: *mut c_int,
611) {
612 let instance = &*(ptr as *mut T::Instance);
613 let imp = instance.imp();
614 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
615
616 let (min_height, nat_height) = imp.preferred_height_for_width(&*widget, width);
617 if !min_height_ptr.is_null() {
618 *min_height_ptr = min_height;
619 }
620 if !nat_height_ptr.is_null() {
621 *nat_height_ptr = nat_height;
622 }
623}
624
625unsafe extern "C" fn cell_renderer_get_preferred_height<T: CellRendererImpl>(
626 ptr: *mut ffi::GtkCellRenderer,
627 wdgtptr: *mut ffi::GtkWidget,
628 minptr: *mut c_int,
629 natptr: *mut c_int,
630) {
631 let instance = &*(ptr as *mut T::Instance);
632 let imp = instance.imp();
633 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
634
635 let (min_size, nat_size) = imp.preferred_height(&*widget);
636 if !minptr.is_null() {
637 *minptr = min_size;
638 }
639 if !natptr.is_null() {
640 *natptr = nat_size;
641 }
642}
643
644unsafe extern "C" fn cell_renderer_get_preferred_width_for_height<T: CellRendererImpl>(
645 ptr: *mut ffi::GtkCellRenderer,
646 wdgtptr: *mut ffi::GtkWidget,
647 height: c_int,
648 min_width_ptr: *mut c_int,
649 nat_width_ptr: *mut c_int,
650) {
651 let instance = &*(ptr as *mut T::Instance);
652 let imp = instance.imp();
653 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
654
655 let (min_width, nat_width) = imp.preferred_width_for_height(&*widget, height);
656 if !min_width_ptr.is_null() {
657 *min_width_ptr = min_width;
658 }
659 if !nat_width_ptr.is_null() {
660 *nat_width_ptr = nat_width;
661 }
662}
663
664unsafe extern "C" fn cell_renderer_get_preferred_width<T: CellRendererImpl>(
665 ptr: *mut ffi::GtkCellRenderer,
666 wdgtptr: *mut ffi::GtkWidget,
667 minptr: *mut c_int,
668 natptr: *mut c_int,
669) {
670 let instance = &*(ptr as *mut T::Instance);
671 let imp = instance.imp();
672 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
673
674 let (min_size, nat_size) = imp.preferred_width(&*widget);
675 if !minptr.is_null() {
676 *minptr = min_size;
677 }
678 if !natptr.is_null() {
679 *natptr = nat_size;
680 }
681}
682
683unsafe extern "C" fn cell_renderer_get_request_mode<T: CellRendererImpl>(
684 ptr: *mut ffi::GtkCellRenderer,
685) -> ffi::GtkSizeRequestMode {
686 let instance = &*(ptr as *mut T::Instance);
687 let imp = instance.imp();
688
689 imp.request_mode().into_glib()
690}
691
692unsafe extern "C" fn cell_renderer_snapshot<T: CellRendererImpl>(
693 ptr: *mut ffi::GtkCellRenderer,
694 snapshotptr: *mut ffi::GtkSnapshot,
695 wdgtptr: *mut ffi::GtkWidget,
696 bgptr: *const gdk::ffi::GdkRectangle,
697 cellptr: *const gdk::ffi::GdkRectangle,
698 flags: ffi::GtkCellRendererState,
699) {
700 let instance = &*(ptr as *mut T::Instance);
701 let imp = instance.imp();
702 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
703 let snapshot: Borrowed<Snapshot> = from_glib_borrow(snapshotptr);
704
705 imp.snapshot(
706 &snapshot,
707 &*widget,
708 &from_glib_borrow(bgptr),
709 &from_glib_borrow(cellptr),
710 from_glib(flags),
711 );
712}
713
714unsafe extern "C" fn cell_renderer_start_editing<T: CellRendererImpl>(
715 ptr: *mut ffi::GtkCellRenderer,
716 evtptr: *mut gdk::ffi::GdkEvent,
717 wdgtptr: *mut ffi::GtkWidget,
718 pathptr: *const c_char,
719 bgptr: *const gdk::ffi::GdkRectangle,
720 cellptr: *const gdk::ffi::GdkRectangle,
721 flags: ffi::GtkCellRendererState,
722) -> *mut ffi::GtkCellEditable {
723 let instance = &*(ptr as *mut T::Instance);
724 let imp = instance.imp();
725 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
726 let evt: Borrowed<Option<gdk::Event>> = from_glib_borrow(evtptr);
727
728 imp.start_editing(
729 evt.as_ref().as_ref(),
730 &*widget,
731 &GString::from_glib_borrow(pathptr),
732 &from_glib_borrow(bgptr),
733 &from_glib_borrow(cellptr),
734 from_glib(flags),
735 )
736 .to_glib_none()
737 .0
738}