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: 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 let instance = &*(ptr as *mut T::Instance);
549 let imp = instance.imp();
550 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
551 let evt: Borrowed<Option<gdk::Event>> = from_glib_borrow(evtptr);
552
553 imp.activate(
554 evt.as_ref().as_ref(),
555 &*widget,
556 &GString::from_glib_borrow(pathptr),
557 &from_glib_borrow(bgptr),
558 &from_glib_borrow(cellptr),
559 from_glib(flags),
560 )
561 .into_glib()
562}
563
564unsafe extern "C" fn cell_renderer_editing_canceled<T: CellRendererImpl>(
565 ptr: *mut ffi::GtkCellRenderer,
566) {
567 let instance = &*(ptr as *mut T::Instance);
568 let imp = instance.imp();
569
570 imp.editing_canceled();
571}
572
573unsafe extern "C" fn cell_renderer_editing_started<T: CellRendererImpl>(
574 ptr: *mut ffi::GtkCellRenderer,
575 editableptr: *mut ffi::GtkCellEditable,
576 pathptr: *const c_char,
577) {
578 let instance = &*(ptr as *mut T::Instance);
579 let imp = instance.imp();
580 let editable = from_glib_borrow(editableptr);
581
582 imp.editing_started(&editable, &GString::from_glib_borrow(pathptr));
583}
584
585unsafe extern "C" fn cell_renderer_get_aligned_area<T: CellRendererImpl>(
586 ptr: *mut ffi::GtkCellRenderer,
587 wdgtptr: *mut ffi::GtkWidget,
588 flags: ffi::GtkCellRendererState,
589 cellarea: *const gdk::ffi::GdkRectangle,
590 alignedptr: *mut gdk::ffi::GdkRectangle,
591) {
592 let instance = &*(ptr as *mut T::Instance);
593 let imp = instance.imp();
594 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
595
596 let rectangle = imp.aligned_area(&*widget, from_glib(flags), &from_glib_borrow(cellarea));
597 *alignedptr = *rectangle.to_glib_none().0;
598}
599
600unsafe extern "C" fn cell_renderer_get_preferred_height_for_width<T: CellRendererImpl>(
601 ptr: *mut ffi::GtkCellRenderer,
602 wdgtptr: *mut ffi::GtkWidget,
603 width: c_int,
604 min_height_ptr: *mut c_int,
605 nat_height_ptr: *mut c_int,
606) {
607 let instance = &*(ptr as *mut T::Instance);
608 let imp = instance.imp();
609 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
610
611 let (min_height, nat_height) = imp.preferred_height_for_width(&*widget, width);
612 if !min_height_ptr.is_null() {
613 *min_height_ptr = min_height;
614 }
615 if !nat_height_ptr.is_null() {
616 *nat_height_ptr = nat_height;
617 }
618}
619
620unsafe extern "C" fn cell_renderer_get_preferred_height<T: CellRendererImpl>(
621 ptr: *mut ffi::GtkCellRenderer,
622 wdgtptr: *mut ffi::GtkWidget,
623 minptr: *mut c_int,
624 natptr: *mut c_int,
625) {
626 let instance = &*(ptr as *mut T::Instance);
627 let imp = instance.imp();
628 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
629
630 let (min_size, nat_size) = imp.preferred_height(&*widget);
631 if !minptr.is_null() {
632 *minptr = min_size;
633 }
634 if !natptr.is_null() {
635 *natptr = nat_size;
636 }
637}
638
639unsafe extern "C" fn cell_renderer_get_preferred_width_for_height<T: CellRendererImpl>(
640 ptr: *mut ffi::GtkCellRenderer,
641 wdgtptr: *mut ffi::GtkWidget,
642 height: c_int,
643 min_width_ptr: *mut c_int,
644 nat_width_ptr: *mut c_int,
645) {
646 let instance = &*(ptr as *mut T::Instance);
647 let imp = instance.imp();
648 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
649
650 let (min_width, nat_width) = imp.preferred_width_for_height(&*widget, height);
651 if !min_width_ptr.is_null() {
652 *min_width_ptr = min_width;
653 }
654 if !nat_width_ptr.is_null() {
655 *nat_width_ptr = nat_width;
656 }
657}
658
659unsafe extern "C" fn cell_renderer_get_preferred_width<T: CellRendererImpl>(
660 ptr: *mut ffi::GtkCellRenderer,
661 wdgtptr: *mut ffi::GtkWidget,
662 minptr: *mut c_int,
663 natptr: *mut c_int,
664) {
665 let instance = &*(ptr as *mut T::Instance);
666 let imp = instance.imp();
667 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
668
669 let (min_size, nat_size) = imp.preferred_width(&*widget);
670 if !minptr.is_null() {
671 *minptr = min_size;
672 }
673 if !natptr.is_null() {
674 *natptr = nat_size;
675 }
676}
677
678unsafe extern "C" fn cell_renderer_get_request_mode<T: CellRendererImpl>(
679 ptr: *mut ffi::GtkCellRenderer,
680) -> ffi::GtkSizeRequestMode {
681 let instance = &*(ptr as *mut T::Instance);
682 let imp = instance.imp();
683
684 imp.request_mode().into_glib()
685}
686
687unsafe extern "C" fn cell_renderer_snapshot<T: CellRendererImpl>(
688 ptr: *mut ffi::GtkCellRenderer,
689 snapshotptr: *mut ffi::GtkSnapshot,
690 wdgtptr: *mut ffi::GtkWidget,
691 bgptr: *const gdk::ffi::GdkRectangle,
692 cellptr: *const gdk::ffi::GdkRectangle,
693 flags: ffi::GtkCellRendererState,
694) {
695 let instance = &*(ptr as *mut T::Instance);
696 let imp = instance.imp();
697 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
698 let snapshot: Borrowed<Snapshot> = from_glib_borrow(snapshotptr);
699
700 imp.snapshot(
701 &snapshot,
702 &*widget,
703 &from_glib_borrow(bgptr),
704 &from_glib_borrow(cellptr),
705 from_glib(flags),
706 );
707}
708
709unsafe extern "C" fn cell_renderer_start_editing<T: CellRendererImpl>(
710 ptr: *mut ffi::GtkCellRenderer,
711 evtptr: *mut gdk::ffi::GdkEvent,
712 wdgtptr: *mut ffi::GtkWidget,
713 pathptr: *const c_char,
714 bgptr: *const gdk::ffi::GdkRectangle,
715 cellptr: *const gdk::ffi::GdkRectangle,
716 flags: ffi::GtkCellRendererState,
717) -> *mut ffi::GtkCellEditable {
718 let instance = &*(ptr as *mut T::Instance);
719 let imp = instance.imp();
720 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
721 let evt: Borrowed<Option<gdk::Event>> = from_glib_borrow(evtptr);
722
723 imp.start_editing(
724 evt.as_ref().as_ref(),
725 &*widget,
726 &GString::from_glib_borrow(pathptr),
727 &from_glib_borrow(bgptr),
728 &from_glib_borrow(cellptr),
729 from_glib(flags),
730 )
731 .to_glib_none()
732 .0
733}