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}