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>>(
20 &self,
21 event: Option<&gdk::Event>,
22 widget: &P,
23 path: &str,
24 background_area: &gdk::Rectangle,
25 cell_area: &gdk::Rectangle,
26 flags: CellRendererState,
27 ) -> bool {
28 self.parent_activate(event, widget, path, background_area, cell_area, flags)
29 }
30
31 fn editing_canceled(&self) {
32 self.parent_editing_canceled()
33 }
34
35 fn editing_started(&self, editable: &CellEditable, path: &str) {
36 self.parent_editing_started(editable, path)
37 }
38
39 #[doc(alias = "get_aligned_area")]
40 fn aligned_area<P: IsA<Widget>>(
41 &self,
42 widget: &P,
43 flags: CellRendererState,
44 cell_area: &gdk::Rectangle,
45 ) -> gdk::Rectangle {
46 self.parent_aligned_area(widget, flags, cell_area)
47 }
48
49 #[doc(alias = "get_preferred_height_for_width")]
50 fn preferred_height_for_width<P: IsA<Widget>>(&self, widget: &P, width: i32) -> (i32, i32) {
51 self.parent_preferred_height_for_width(widget, width)
52 }
53
54 #[doc(alias = "get_preferred_height")]
55 fn preferred_height<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
56 self.parent_preferred_height(widget)
57 }
58
59 #[doc(alias = "get_preferred_width_for_height")]
60 fn preferred_width_for_height<P: IsA<Widget>>(&self, widget: &P, height: i32) -> (i32, i32) {
61 self.parent_preferred_width_for_height(widget, height)
62 }
63
64 #[doc(alias = "get_preferred_width")]
65 fn preferred_width<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
66 self.parent_preferred_width(widget)
67 }
68
69 #[doc(alias = "get_request_mode")]
70 fn request_mode(&self) -> SizeRequestMode {
71 self.parent_request_mode()
72 }
73
74 fn snapshot<P: IsA<Widget>>(
75 &self,
76 snapshot: &Snapshot,
77 widget: &P,
78 background_area: &gdk::Rectangle,
79 cell_area: &gdk::Rectangle,
80 flags: CellRendererState,
81 ) {
82 self.parent_snapshot(snapshot, widget, background_area, cell_area, flags);
83 }
84
85 fn start_editing<P: IsA<Widget>>(
86 &self,
87 event: Option<&gdk::Event>,
88 widget: &P,
89 path: &str,
90 background_area: &gdk::Rectangle,
91 cell_area: &gdk::Rectangle,
92 flags: CellRendererState,
93 ) -> Option<CellEditable> {
94 self.parent_start_editing(event, widget, path, background_area, cell_area, flags)
95 }
96}
97
98#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
99#[allow(deprecated)]
100pub trait CellRendererImplExt: CellRendererImpl {
101 fn parent_request_mode(&self) -> SizeRequestMode {
102 unsafe {
103 let data = Self::type_data();
104 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
105 let f = (*parent_class).get_request_mode.unwrap();
106 from_glib(f(self
107 .obj()
108 .unsafe_cast_ref::<CellRenderer>()
109 .to_glib_none()
110 .0))
111 }
112 }
113
114 fn parent_preferred_width<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
115 unsafe {
116 let data = Self::type_data();
117 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
118 let f = (*parent_class).get_preferred_width.unwrap();
119
120 let mut minimum_size = mem::MaybeUninit::uninit();
121 let mut natural_size = mem::MaybeUninit::uninit();
122 f(
123 self.obj()
124 .unsafe_cast_ref::<CellRenderer>()
125 .to_glib_none()
126 .0,
127 widget.as_ref().to_glib_none().0,
128 minimum_size.as_mut_ptr(),
129 natural_size.as_mut_ptr(),
130 );
131 (minimum_size.assume_init(), natural_size.assume_init())
132 }
133 }
134
135 fn parent_preferred_width_for_height<P: IsA<Widget>>(
136 &self,
137 widget: &P,
138 height: i32,
139 ) -> (i32, i32) {
140 unsafe {
141 let data = Self::type_data();
142 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
143 let f = (*parent_class).get_preferred_width_for_height.unwrap();
144
145 let mut minimum_size = mem::MaybeUninit::uninit();
146 let mut natural_size = mem::MaybeUninit::uninit();
147 f(
148 self.obj()
149 .unsafe_cast_ref::<CellRenderer>()
150 .to_glib_none()
151 .0,
152 widget.as_ref().to_glib_none().0,
153 height,
154 minimum_size.as_mut_ptr(),
155 natural_size.as_mut_ptr(),
156 );
157 (minimum_size.assume_init(), natural_size.assume_init())
158 }
159 }
160 fn parent_preferred_height<P: IsA<Widget>>(&self, widget: &P) -> (i32, i32) {
161 unsafe {
162 let data = Self::type_data();
163 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
164 let f = (*parent_class).get_preferred_height.unwrap();
165 let mut minimum_size = mem::MaybeUninit::uninit();
166 let mut natural_size = mem::MaybeUninit::uninit();
167 f(
168 self.obj()
169 .unsafe_cast_ref::<CellRenderer>()
170 .to_glib_none()
171 .0,
172 widget.as_ref().to_glib_none().0,
173 minimum_size.as_mut_ptr(),
174 natural_size.as_mut_ptr(),
175 );
176 (minimum_size.assume_init(), natural_size.assume_init())
177 }
178 }
179 fn parent_preferred_height_for_width<P: IsA<Widget>>(
180 &self,
181 widget: &P,
182 width: i32,
183 ) -> (i32, i32) {
184 unsafe {
185 let data = Self::type_data();
186 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
187 let f = (*parent_class).get_preferred_height_for_width.unwrap();
188 let mut minimum_size = mem::MaybeUninit::uninit();
189 let mut natural_size = mem::MaybeUninit::uninit();
190 f(
191 self.obj()
192 .unsafe_cast_ref::<CellRenderer>()
193 .to_glib_none()
194 .0,
195 widget.as_ref().to_glib_none().0,
196 width,
197 minimum_size.as_mut_ptr(),
198 natural_size.as_mut_ptr(),
199 );
200 (minimum_size.assume_init(), natural_size.assume_init())
201 }
202 }
203
204 fn parent_aligned_area<P: IsA<Widget>>(
205 &self,
206 widget: &P,
207 flags: CellRendererState,
208 cell_area: &gdk::Rectangle,
209 ) -> gdk::Rectangle {
210 unsafe {
211 let data = Self::type_data();
212 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
213 let mut aligned_area = gdk::Rectangle::uninitialized();
214 let f = (*parent_class).get_aligned_area.unwrap();
215 f(
216 self.obj()
217 .unsafe_cast_ref::<CellRenderer>()
218 .to_glib_none()
219 .0,
220 widget.as_ref().to_glib_none().0,
221 flags.into_glib(),
222 cell_area.to_glib_none().0,
223 aligned_area.to_glib_none_mut().0,
224 );
225 aligned_area
226 }
227 }
228
229 fn parent_snapshot<P: IsA<Widget>>(
230 &self,
231 snapshot: &Snapshot,
232 widget: &P,
233 background_area: &gdk::Rectangle,
234 cell_area: &gdk::Rectangle,
235 flags: CellRendererState,
236 ) {
237 unsafe {
238 let data = Self::type_data();
239 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
240 if let Some(f) = (*parent_class).snapshot {
241 f(
242 self.obj()
243 .unsafe_cast_ref::<CellRenderer>()
244 .to_glib_none()
245 .0,
246 snapshot.to_glib_none().0,
247 widget.as_ref().to_glib_none().0,
248 background_area.to_glib_none().0,
249 cell_area.to_glib_none().0,
250 flags.into_glib(),
251 )
252 }
253 }
254 }
255
256 fn parent_activate<P: IsA<Widget>>(
258 &self,
259 event: Option<&gdk::Event>,
260 widget: &P,
261 path: &str,
262 background_area: &gdk::Rectangle,
263 cell_area: &gdk::Rectangle,
264 flags: CellRendererState,
265 ) -> bool {
266 unsafe {
267 let data = Self::type_data();
268 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
269 if let Some(f) = (*parent_class).activate {
270 from_glib(f(
271 self.obj()
272 .unsafe_cast_ref::<CellRenderer>()
273 .to_glib_none()
274 .0,
275 mut_override(event.to_glib_none().0),
276 widget.as_ref().to_glib_none().0,
277 path.to_glib_none().0,
278 background_area.to_glib_none().0,
279 cell_area.to_glib_none().0,
280 flags.into_glib(),
281 ))
282 } else {
283 false
284 }
285 }
286 }
287
288 fn parent_start_editing<P: IsA<Widget>>(
289 &self,
290 event: Option<&gdk::Event>,
291 widget: &P,
292 path: &str,
293 background_area: &gdk::Rectangle,
294 cell_area: &gdk::Rectangle,
295 flags: CellRendererState,
296 ) -> Option<CellEditable> {
297 unsafe {
298 let data = Self::type_data();
299 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
300 if let Some(f) = (*parent_class).start_editing {
301 from_glib_none(f(
302 self.obj()
303 .unsafe_cast_ref::<CellRenderer>()
304 .to_glib_none()
305 .0,
306 mut_override(event.to_glib_none().0),
307 widget.as_ref().to_glib_none().0,
308 path.to_glib_none().0,
309 background_area.to_glib_none().0,
310 cell_area.to_glib_none().0,
311 flags.into_glib(),
312 ))
313 } else {
314 None
315 }
316 }
317 }
318
319 fn parent_editing_canceled(&self) {
320 unsafe {
321 let data = Self::type_data();
322 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
323 if let Some(f) = (*parent_class).editing_canceled {
324 f(self
325 .obj()
326 .unsafe_cast_ref::<CellRenderer>()
327 .to_glib_none()
328 .0)
329 }
330 }
331 }
332
333 fn parent_editing_started(&self, editable: &CellEditable, path: &str) {
334 unsafe {
335 let data = Self::type_data();
336 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkCellRendererClass;
337 if let Some(f) = (*parent_class).editing_started {
338 f(
339 self.obj()
340 .unsafe_cast_ref::<CellRenderer>()
341 .to_glib_none()
342 .0,
343 editable.to_glib_none().0,
344 path.to_glib_none().0,
345 )
346 }
347 }
348 }
349}
350
351impl<T: CellRendererImpl> CellRendererImplExt for T {}
352
353unsafe impl<T: CellRendererImpl> IsSubclassable<T> for CellRenderer {
354 fn class_init(class: &mut ::glib::Class<Self>) {
355 Self::parent_class_init::<T>(class);
356
357 assert_initialized_main_thread!();
358
359 let klass = class.as_mut();
360
361 klass.activate = Some(cell_renderer_activate::<T>);
362 klass.editing_canceled = Some(cell_renderer_editing_canceled::<T>);
363 klass.editing_started = Some(cell_renderer_editing_started::<T>);
364 klass.get_aligned_area = Some(cell_renderer_get_aligned_area::<T>);
365 klass.get_preferred_height_for_width =
366 Some(cell_renderer_get_preferred_height_for_width::<T>);
367 klass.get_preferred_height = Some(cell_renderer_get_preferred_height::<T>);
368 klass.get_preferred_width_for_height =
369 Some(cell_renderer_get_preferred_width_for_height::<T>);
370 klass.get_preferred_width = Some(cell_renderer_get_preferred_width::<T>);
371 klass.get_request_mode = Some(cell_renderer_get_request_mode::<T>);
372 klass.snapshot = Some(cell_renderer_snapshot::<T>);
373 klass.start_editing = Some(cell_renderer_start_editing::<T>);
374 }
375}
376
377unsafe extern "C" fn cell_renderer_activate<T: CellRendererImpl>(
378 ptr: *mut ffi::GtkCellRenderer,
379 evtptr: *mut gdk::ffi::GdkEvent,
380 wdgtptr: *mut ffi::GtkWidget,
381 pathptr: *const c_char,
382 bgptr: *const gdk::ffi::GdkRectangle,
383 cellptr: *const gdk::ffi::GdkRectangle,
384 flags: ffi::GtkCellRendererState,
385) -> glib::ffi::gboolean {
386 let instance = &*(ptr as *mut T::Instance);
387 let imp = instance.imp();
388 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
389 let evt: Borrowed<Option<gdk::Event>> = from_glib_borrow(evtptr);
390
391 imp.activate(
392 evt.as_ref().as_ref(),
393 &*widget,
394 &GString::from_glib_borrow(pathptr),
395 &from_glib_borrow(bgptr),
396 &from_glib_borrow(cellptr),
397 from_glib(flags),
398 )
399 .into_glib()
400}
401
402unsafe extern "C" fn cell_renderer_editing_canceled<T: CellRendererImpl>(
403 ptr: *mut ffi::GtkCellRenderer,
404) {
405 let instance = &*(ptr as *mut T::Instance);
406 let imp = instance.imp();
407
408 imp.editing_canceled();
409}
410
411unsafe extern "C" fn cell_renderer_editing_started<T: CellRendererImpl>(
412 ptr: *mut ffi::GtkCellRenderer,
413 editableptr: *mut ffi::GtkCellEditable,
414 pathptr: *const c_char,
415) {
416 let instance = &*(ptr as *mut T::Instance);
417 let imp = instance.imp();
418 let editable = from_glib_borrow(editableptr);
419
420 imp.editing_started(&editable, &GString::from_glib_borrow(pathptr));
421}
422
423unsafe extern "C" fn cell_renderer_get_aligned_area<T: CellRendererImpl>(
424 ptr: *mut ffi::GtkCellRenderer,
425 wdgtptr: *mut ffi::GtkWidget,
426 flags: ffi::GtkCellRendererState,
427 cellarea: *const gdk::ffi::GdkRectangle,
428 alignedptr: *mut gdk::ffi::GdkRectangle,
429) {
430 let instance = &*(ptr as *mut T::Instance);
431 let imp = instance.imp();
432 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
433
434 let rectangle = imp.aligned_area(&*widget, from_glib(flags), &from_glib_borrow(cellarea));
435 *alignedptr = *rectangle.to_glib_none().0;
436}
437
438unsafe extern "C" fn cell_renderer_get_preferred_height_for_width<T: CellRendererImpl>(
439 ptr: *mut ffi::GtkCellRenderer,
440 wdgtptr: *mut ffi::GtkWidget,
441 width: c_int,
442 min_height_ptr: *mut c_int,
443 nat_height_ptr: *mut c_int,
444) {
445 let instance = &*(ptr as *mut T::Instance);
446 let imp = instance.imp();
447 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
448
449 let (min_height, nat_height) = imp.preferred_height_for_width(&*widget, width);
450 if !min_height_ptr.is_null() {
451 *min_height_ptr = min_height;
452 }
453 if !nat_height_ptr.is_null() {
454 *nat_height_ptr = nat_height;
455 }
456}
457
458unsafe extern "C" fn cell_renderer_get_preferred_height<T: CellRendererImpl>(
459 ptr: *mut ffi::GtkCellRenderer,
460 wdgtptr: *mut ffi::GtkWidget,
461 minptr: *mut c_int,
462 natptr: *mut c_int,
463) {
464 let instance = &*(ptr as *mut T::Instance);
465 let imp = instance.imp();
466 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
467
468 let (min_size, nat_size) = imp.preferred_height(&*widget);
469 if !minptr.is_null() {
470 *minptr = min_size;
471 }
472 if !natptr.is_null() {
473 *natptr = nat_size;
474 }
475}
476
477unsafe extern "C" fn cell_renderer_get_preferred_width_for_height<T: CellRendererImpl>(
478 ptr: *mut ffi::GtkCellRenderer,
479 wdgtptr: *mut ffi::GtkWidget,
480 height: c_int,
481 min_width_ptr: *mut c_int,
482 nat_width_ptr: *mut c_int,
483) {
484 let instance = &*(ptr as *mut T::Instance);
485 let imp = instance.imp();
486 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
487
488 let (min_width, nat_width) = imp.preferred_width_for_height(&*widget, height);
489 if !min_width_ptr.is_null() {
490 *min_width_ptr = min_width;
491 }
492 if !nat_width_ptr.is_null() {
493 *nat_width_ptr = nat_width;
494 }
495}
496
497unsafe extern "C" fn cell_renderer_get_preferred_width<T: CellRendererImpl>(
498 ptr: *mut ffi::GtkCellRenderer,
499 wdgtptr: *mut ffi::GtkWidget,
500 minptr: *mut c_int,
501 natptr: *mut c_int,
502) {
503 let instance = &*(ptr as *mut T::Instance);
504 let imp = instance.imp();
505 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
506
507 let (min_size, nat_size) = imp.preferred_width(&*widget);
508 if !minptr.is_null() {
509 *minptr = min_size;
510 }
511 if !natptr.is_null() {
512 *natptr = nat_size;
513 }
514}
515
516unsafe extern "C" fn cell_renderer_get_request_mode<T: CellRendererImpl>(
517 ptr: *mut ffi::GtkCellRenderer,
518) -> ffi::GtkSizeRequestMode {
519 let instance = &*(ptr as *mut T::Instance);
520 let imp = instance.imp();
521
522 imp.request_mode().into_glib()
523}
524
525unsafe extern "C" fn cell_renderer_snapshot<T: CellRendererImpl>(
526 ptr: *mut ffi::GtkCellRenderer,
527 snapshotptr: *mut ffi::GtkSnapshot,
528 wdgtptr: *mut ffi::GtkWidget,
529 bgptr: *const gdk::ffi::GdkRectangle,
530 cellptr: *const gdk::ffi::GdkRectangle,
531 flags: ffi::GtkCellRendererState,
532) {
533 let instance = &*(ptr as *mut T::Instance);
534 let imp = instance.imp();
535 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
536 let snapshot: Borrowed<Snapshot> = from_glib_borrow(snapshotptr);
537
538 imp.snapshot(
539 &snapshot,
540 &*widget,
541 &from_glib_borrow(bgptr),
542 &from_glib_borrow(cellptr),
543 from_glib(flags),
544 );
545}
546
547unsafe extern "C" fn cell_renderer_start_editing<T: CellRendererImpl>(
548 ptr: *mut ffi::GtkCellRenderer,
549 evtptr: *mut gdk::ffi::GdkEvent,
550 wdgtptr: *mut ffi::GtkWidget,
551 pathptr: *const c_char,
552 bgptr: *const gdk::ffi::GdkRectangle,
553 cellptr: *const gdk::ffi::GdkRectangle,
554 flags: ffi::GtkCellRendererState,
555) -> *mut ffi::GtkCellEditable {
556 let instance = &*(ptr as *mut T::Instance);
557 let imp = instance.imp();
558 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
559 let evt: Borrowed<Option<gdk::Event>> = from_glib_borrow(evtptr);
560
561 imp.start_editing(
562 evt.as_ref().as_ref(),
563 &*widget,
564 &GString::from_glib_borrow(pathptr),
565 &from_glib_borrow(bgptr),
566 &from_glib_borrow(cellptr),
567 from_glib(flags),
568 )
569 .to_glib_none()
570 .0
571}