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