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