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