clutter/auto/
content.rs

1use crate::Actor;
2use glib::{
3    object::{Cast, IsA},
4    signal::{connect_raw, SignalHandlerId},
5    translate::*,
6};
7use std::boxed::Box as Box_;
8use std::{fmt, mem, mem::transmute};
9
10glib_wrapper! {
11    pub struct Content(Interface<ffi::ClutterContent>);
12
13    match fn {
14        get_type => || ffi::clutter_content_get_type(),
15    }
16}
17
18pub const NONE_CONTENT: Option<&Content> = None;
19
20/// Trait containing all `Content` methods.
21///
22/// # Implementors
23///
24/// [`Canvas`](struct.Canvas.html), [`Content`](struct.Content.html), [`Image`](struct.Image.html)
25pub trait ContentExt: 'static {
26    /// Retrieves the natural size of the `self`, if any.
27    ///
28    /// The natural size of a `Content` is defined as the size the content
29    /// would have regardless of the allocation of the actor that is painting it,
30    /// for instance the size of an image data.
31    /// ## `width`
32    /// return location for the natural width of the content
33    /// ## `height`
34    /// return location for the natural height of the content
35    ///
36    /// # Returns
37    ///
38    /// `true` if the content has a preferred size, and `false`
39    ///  otherwise
40    fn get_preferred_size(&self) -> Option<(f32, f32)>;
41
42    /// Invalidates a `Content`.
43    ///
44    /// This function should be called by `Content` implementations when
45    /// they change the way a the content should be painted regardless of the
46    /// actor state.
47    fn invalidate(&self);
48
49    /// This signal is emitted each time a `Content` implementation is
50    /// assigned to a `Actor`.
51    /// ## `actor`
52    /// a `Actor`
53    fn connect_attached<F: Fn(&Self, &Actor) + 'static>(&self, f: F) -> SignalHandlerId;
54
55    /// This signal is emitted each time a `Content` implementation is
56    /// removed from a `Actor`.
57    /// ## `actor`
58    /// a `Actor`
59    fn connect_detached<F: Fn(&Self, &Actor) + 'static>(&self, f: F) -> SignalHandlerId;
60}
61
62impl<O: IsA<Content>> ContentExt for O {
63    fn get_preferred_size(&self) -> Option<(f32, f32)> {
64        unsafe {
65            let mut width = mem::MaybeUninit::uninit();
66            let mut height = mem::MaybeUninit::uninit();
67            let ret = from_glib(ffi::clutter_content_get_preferred_size(
68                self.as_ref().to_glib_none().0,
69                width.as_mut_ptr(),
70                height.as_mut_ptr(),
71            ));
72            let width = width.assume_init();
73            let height = height.assume_init();
74            if ret {
75                Some((width, height))
76            } else {
77                None
78            }
79        }
80    }
81
82    fn invalidate(&self) {
83        unsafe {
84            ffi::clutter_content_invalidate(self.as_ref().to_glib_none().0);
85        }
86    }
87
88    fn connect_attached<F: Fn(&Self, &Actor) + 'static>(&self, f: F) -> SignalHandlerId {
89        unsafe extern "C" fn attached_trampoline<P, F: Fn(&P, &Actor) + 'static>(
90            this: *mut ffi::ClutterContent,
91            actor: *mut ffi::ClutterActor,
92            f: glib_sys::gpointer,
93        ) where
94            P: IsA<Content>,
95        {
96            let f: &F = &*(f as *const F);
97            f(
98                &Content::from_glib_borrow(this).unsafe_cast_ref(),
99                &from_glib_borrow(actor),
100            )
101        }
102        unsafe {
103            let f: Box_<F> = Box_::new(f);
104            connect_raw(
105                self.as_ptr() as *mut _,
106                b"attached\0".as_ptr() as *const _,
107                Some(transmute::<_, unsafe extern "C" fn()>(
108                    attached_trampoline::<Self, F> as *const (),
109                )),
110                Box_::into_raw(f),
111            )
112        }
113    }
114
115    fn connect_detached<F: Fn(&Self, &Actor) + 'static>(&self, f: F) -> SignalHandlerId {
116        unsafe extern "C" fn detached_trampoline<P, F: Fn(&P, &Actor) + 'static>(
117            this: *mut ffi::ClutterContent,
118            actor: *mut ffi::ClutterActor,
119            f: glib_sys::gpointer,
120        ) where
121            P: IsA<Content>,
122        {
123            let f: &F = &*(f as *const F);
124            f(
125                &Content::from_glib_borrow(this).unsafe_cast_ref(),
126                &from_glib_borrow(actor),
127            )
128        }
129        unsafe {
130            let f: Box_<F> = Box_::new(f);
131            connect_raw(
132                self.as_ptr() as *mut _,
133                b"detached\0".as_ptr() as *const _,
134                Some(transmute::<_, unsafe extern "C" fn()>(
135                    detached_trampoline::<Self, F> as *const (),
136                )),
137                Box_::into_raw(f),
138            )
139        }
140    }
141}
142
143impl fmt::Display for Content {
144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145        write!(f, "Content")
146    }
147}