animate/legacy/
layout_manager.rs

1use crate::{Actor, ActorBox, AllocationFlags, Container, LayoutMeta};
2use glib::{
3    object as gobject,
4    object::{Cast, IsA},
5    signal::{connect_raw, SignalHandlerId},
6    translate::*,
7};
8use std::boxed::Box as Box_;
9use std::{fmt, mem, mem::transmute};
10
11glib_wrapper! {
12    pub struct LayoutManager(Object<ffi::ClutterLayoutManager, ffi::ClutterLayoutManagerClass, LayoutManagerClass>) @extends gobject::InitiallyUnowned;
13
14    match fn {
15        get_type => || ffi::clutter_layout_manager_get_type(),
16    }
17}
18
19/// Trait containing all `LayoutManager` methods.
20///
21/// # Implementors
22///
23/// [`BinLayout`](struct.BinLayout.html), [`BoxLayout`](struct.BoxLayout.html), [`FixedLayout`](struct.FixedLayout.html), [`FlowLayout`](struct.FlowLayout.html), [`GridLayout`](struct.GridLayout.html), [`LayoutManager`](struct.LayoutManager.html)
24pub trait LayoutManagerExt: 'static {
25    /// Allocates the children of `container` given an area
26    ///
27    /// See also `ActorExt::allocate`
28    /// ## `container`
29    /// the `Container` using `self`
30    /// ## `allocation`
31    /// the `ActorBox` containing the allocated area
32    ///  of `container`
33    /// ## `flags`
34    /// the allocation flags
35    fn allocate<P: IsA<Container>>(
36        &self,
37        container: &P,
38        allocation: &ActorBox,
39        flags: AllocationFlags,
40    );
41
42    //fn child_get<P: IsA<Container>, Q: IsA<Actor>>(&self, container: &P, actor: &Q, first_property: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs);
43
44    /// Gets a property on the `LayoutMeta` created by `self` and
45    /// attached to a child of `container`
46    ///
47    /// The `gobject::Value` must already be initialized to the type of the property
48    /// and has to be unset with `gobject::Value::unset` after extracting the real
49    /// value out of it
50    /// ## `container`
51    /// a `Container` using `self`
52    /// ## `actor`
53    /// a `Actor` child of `container`
54    /// ## `property_name`
55    /// the name of the property to get
56    /// ## `value`
57    /// a `gobject::Value` with the value of the property to get
58    fn child_get_property<P: IsA<Container>, Q: IsA<Actor>>(
59        &self,
60        container: &P,
61        actor: &Q,
62        property_name: &str,
63        value: &mut glib::Value,
64    );
65
66    //fn child_set<P: IsA<Container>, Q: IsA<Actor>>(&self, container: &P, actor: &Q, first_property: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs);
67
68    /// Sets a property on the `LayoutMeta` created by `self` and
69    /// attached to a child of `container`
70    /// ## `container`
71    /// a `Container` using `self`
72    /// ## `actor`
73    /// a `Actor` child of `container`
74    /// ## `property_name`
75    /// the name of the property to set
76    /// ## `value`
77    /// a `gobject::Value` with the value of the property to set
78    fn child_set_property<P: IsA<Container>, Q: IsA<Actor>>(
79        &self,
80        container: &P,
81        actor: &Q,
82        property_name: &str,
83        value: &glib::Value,
84    );
85
86    /// Retrieves the `gobject::ParamSpec` for the layout property `name` inside
87    /// the `LayoutMeta` sub-class used by `self`
88    /// ## `name`
89    /// the name of the property
90    ///
91    /// # Returns
92    ///
93    /// a `gobject::ParamSpec` describing the property,
94    ///  or `None` if no property with that name exists. The returned
95    ///  `gobject::ParamSpec` is owned by the layout manager and should not be
96    ///  modified or freed
97    fn find_child_property(&self, name: &str) -> Option<glib::ParamSpec>;
98
99    /// Retrieves the `LayoutMeta` that the layout `self` associated
100    /// to the `actor` child of `container`, eventually by creating one if the
101    /// `LayoutManager` supports layout properties
102    /// ## `container`
103    /// a `Container` using `self`
104    /// ## `actor`
105    /// a `Actor` child of `container`
106    ///
107    /// # Returns
108    ///
109    /// a `LayoutMeta`, or `None` if the
110    ///  `LayoutManager` does not have layout properties. The returned
111    ///  layout meta instance is owned by the `LayoutManager` and it
112    ///  should not be unreferenced
113    fn get_child_meta<P: IsA<Container>, Q: IsA<Actor>>(
114        &self,
115        container: &P,
116        actor: &Q,
117    ) -> Option<LayoutMeta>;
118
119    /// Computes the minimum and natural heights of the `container` according
120    /// to `self`.
121    ///
122    /// See also `ActorExt::get_preferred_height`
123    /// ## `container`
124    /// the `Container` using `self`
125    /// ## `for_width`
126    /// the width for which the height should be computed, or -1
127    /// ## `min_height_p`
128    /// return location for the minimum height
129    ///  of the layout, or `None`
130    /// ## `nat_height_p`
131    /// return location for the natural height
132    ///  of the layout, or `None`
133    fn get_preferred_height<P: IsA<Container>>(&self, container: &P, for_width: f32) -> (f32, f32);
134
135    /// Computes the minimum and natural widths of the `container` according
136    /// to `self`.
137    ///
138    /// See also `ActorExt::get_preferred_width`
139    /// ## `container`
140    /// the `Container` using `self`
141    /// ## `for_height`
142    /// the height for which the width should be computed, or -1
143    /// ## `min_width_p`
144    /// return location for the minimum width
145    ///  of the layout, or `None`
146    /// ## `nat_width_p`
147    /// return location for the natural width
148    ///  of the layout, or `None`
149    fn get_preferred_width<P: IsA<Container>>(&self, container: &P, for_height: f32) -> (f32, f32);
150
151    /// Emits the `LayoutManager::layout-changed` signal on `self`
152    ///
153    /// This function should only be called by implementations of the
154    /// `LayoutManager` class
155    fn layout_changed(&self);
156
157    /// Retrieves all the `gobject::ParamSpec`<!-- -->s for the layout properties
158    /// stored inside the `LayoutMeta` sub-class used by `self`
159    /// ## `n_pspecs`
160    /// return location for the number of returned
161    ///  `gobject::ParamSpec`<!-- -->s
162    ///
163    /// # Returns
164    ///
165    /// the newly-allocated,
166    ///  `None`-terminated array of `gobject::ParamSpec`<!-- -->s. Use `g_free` to free the
167    ///  resources allocated for the array
168    fn list_child_properties(&self) -> Vec<glib::ParamSpec>;
169
170    /// If the `LayoutManager` sub-class allows it, allow
171    /// adding a weak reference of the `container` using `self`
172    /// from within the layout manager
173    ///
174    /// The layout manager should not increase the reference
175    /// count of the `container`
176    /// ## `container`
177    /// a `Container` using `self`
178    fn set_container<P: IsA<Container>>(&self, container: Option<&P>);
179
180    /// The ::layout-changed signal is emitted each time a layout manager
181    /// has been changed. Every `Actor` using the `manager` instance
182    /// as a layout manager should connect a handler to the ::layout-changed
183    /// signal and queue a relayout on themselves:
184    ///
185    ///
186    /// ```text
187    ///   static void layout_changed (LayoutManager *manager,
188    ///                               Actor         *self)
189    ///   {
190    ///     actor_queue_relayout (self);
191    ///   }
192    ///   ...
193    ///     self->manager = g_object_ref_sink (manager);
194    ///     g_signal_connect (self->manager, "layout-changed",
195    ///                       G_CALLBACK (layout_changed),
196    ///                       self);
197    /// ```
198    ///
199    /// Sub-classes of `LayoutManager` that implement a layout that
200    /// can be controlled or changed using parameters should emit the
201    /// ::layout-changed signal whenever one of the parameters changes,
202    /// by using `LayoutManagerExt::layout_changed`.
203    fn connect_layout_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
204}
205
206impl<O: IsA<LayoutManager>> LayoutManagerExt for O {
207    fn allocate<P: IsA<Container>>(
208        &self,
209        container: &P,
210        allocation: &ActorBox,
211        flags: AllocationFlags,
212    ) {
213        unsafe {
214            ffi::clutter_layout_manager_allocate(
215                self.as_ref().to_glib_none().0,
216                container.as_ref().to_glib_none().0,
217                allocation.to_glib_none().0,
218                flags.to_glib(),
219            );
220        }
221    }
222
223    //fn child_get<P: IsA<Container>, Q: IsA<Actor>>(&self, container: &P, actor: &Q, first_property: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) {
224    //    unsafe { TODO: call clutter_sys:clutter_layout_manager_child_get() }
225    //}
226
227    fn child_get_property<P: IsA<Container>, Q: IsA<Actor>>(
228        &self,
229        container: &P,
230        actor: &Q,
231        property_name: &str,
232        value: &mut glib::Value,
233    ) {
234        unsafe {
235            ffi::clutter_layout_manager_child_get_property(
236                self.as_ref().to_glib_none().0,
237                container.as_ref().to_glib_none().0,
238                actor.as_ref().to_glib_none().0,
239                property_name.to_glib_none().0,
240                value.to_glib_none_mut().0,
241            );
242        }
243    }
244
245    //fn child_set<P: IsA<Container>, Q: IsA<Actor>>(&self, container: &P, actor: &Q, first_property: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) {
246    //    unsafe { TODO: call clutter_sys:clutter_layout_manager_child_set() }
247    //}
248
249    fn child_set_property<P: IsA<Container>, Q: IsA<Actor>>(
250        &self,
251        container: &P,
252        actor: &Q,
253        property_name: &str,
254        value: &glib::Value,
255    ) {
256        unsafe {
257            ffi::clutter_layout_manager_child_set_property(
258                self.as_ref().to_glib_none().0,
259                container.as_ref().to_glib_none().0,
260                actor.as_ref().to_glib_none().0,
261                property_name.to_glib_none().0,
262                value.to_glib_none().0,
263            );
264        }
265    }
266
267    fn find_child_property(&self, name: &str) -> Option<glib::ParamSpec> {
268        unsafe {
269            from_glib_none(ffi::clutter_layout_manager_find_child_property(
270                self.as_ref().to_glib_none().0,
271                name.to_glib_none().0,
272            ))
273        }
274    }
275
276    fn get_child_meta<P: IsA<Container>, Q: IsA<Actor>>(
277        &self,
278        container: &P,
279        actor: &Q,
280    ) -> Option<LayoutMeta> {
281        unsafe {
282            from_glib_none(ffi::clutter_layout_manager_get_child_meta(
283                self.as_ref().to_glib_none().0,
284                container.as_ref().to_glib_none().0,
285                actor.as_ref().to_glib_none().0,
286            ))
287        }
288    }
289
290    fn get_preferred_height<P: IsA<Container>>(&self, container: &P, for_width: f32) -> (f32, f32) {
291        unsafe {
292            let mut min_height_p = mem::MaybeUninit::uninit();
293            let mut nat_height_p = mem::MaybeUninit::uninit();
294            ffi::clutter_layout_manager_get_preferred_height(
295                self.as_ref().to_glib_none().0,
296                container.as_ref().to_glib_none().0,
297                for_width,
298                min_height_p.as_mut_ptr(),
299                nat_height_p.as_mut_ptr(),
300            );
301            let min_height_p = min_height_p.assume_init();
302            let nat_height_p = nat_height_p.assume_init();
303            (min_height_p, nat_height_p)
304        }
305    }
306
307    fn get_preferred_width<P: IsA<Container>>(&self, container: &P, for_height: f32) -> (f32, f32) {
308        unsafe {
309            let mut min_width_p = mem::MaybeUninit::uninit();
310            let mut nat_width_p = mem::MaybeUninit::uninit();
311            ffi::clutter_layout_manager_get_preferred_width(
312                self.as_ref().to_glib_none().0,
313                container.as_ref().to_glib_none().0,
314                for_height,
315                min_width_p.as_mut_ptr(),
316                nat_width_p.as_mut_ptr(),
317            );
318            let min_width_p = min_width_p.assume_init();
319            let nat_width_p = nat_width_p.assume_init();
320            (min_width_p, nat_width_p)
321        }
322    }
323
324    fn layout_changed(&self) {
325        unsafe {
326            ffi::clutter_layout_manager_layout_changed(self.as_ref().to_glib_none().0);
327        }
328    }
329
330    fn list_child_properties(&self) -> Vec<glib::ParamSpec> {
331        unsafe {
332            let mut n_pspecs = mem::MaybeUninit::uninit();
333            let ret = FromGlibContainer::from_glib_full_num(
334                ffi::clutter_layout_manager_list_child_properties(
335                    self.as_ref().to_glib_none().0,
336                    n_pspecs.as_mut_ptr(),
337                ),
338                n_pspecs.assume_init() as usize,
339            );
340            ret
341        }
342    }
343
344    fn set_container<P: IsA<Container>>(&self, container: Option<&P>) {
345        unsafe {
346            ffi::clutter_layout_manager_set_container(
347                self.as_ref().to_glib_none().0,
348                container.map(|p| p.as_ref()).to_glib_none().0,
349            );
350        }
351    }
352
353    fn connect_layout_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
354        unsafe extern "C" fn layout_changed_trampoline<P, F: Fn(&P) + 'static>(
355            this: *mut ffi::ClutterLayoutManager,
356            f: glib_sys::gpointer,
357        ) where
358            P: IsA<LayoutManager>,
359        {
360            let f: &F = &*(f as *const F);
361            f(&LayoutManager::from_glib_borrow(this).unsafe_cast_ref())
362        }
363        unsafe {
364            let f: Box_<F> = Box_::new(f);
365            connect_raw(
366                self.as_ptr() as *mut _,
367                b"layout-changed\0".as_ptr() as *const _,
368                Some(transmute::<_, unsafe extern "C" fn()>(
369                    layout_changed_trampoline::<Self, F> as *const (),
370                )),
371                Box_::into_raw(f),
372            )
373        }
374    }
375}
376
377impl fmt::Display for LayoutManager {
378    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
379        write!(f, "LayoutManager")
380    }
381}