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}