Skip to main content

native_windows_gui2/layouts/
flexbox_layout.rs

1use crate::NwgError;
2use crate::controls::ControlHandle;
3use crate::win32::window::{
4    RawEventHandler, bind_raw_event_handler_inner, unbind_raw_event_handler,
5};
6use crate::win32::window_helper as wh;
7use std::{
8    cell::{Ref, RefCell, RefMut},
9    ptr,
10    rc::Rc,
11};
12use winapi::shared::windef::HWND;
13
14use stretch::{
15    geometry::{Point, Rect, Size},
16    node::{Node, Stretch},
17    number::Number,
18    style::*,
19};
20
21#[derive(Debug)]
22pub struct FlexboxLayoutItem {
23    /// The handle to the control in the item
24    control: HWND,
25    style: Style,
26}
27
28pub enum FlexboxLayoutChild {
29    Item(FlexboxLayoutItem),
30    Flexbox(FlexboxLayout),
31}
32
33impl FlexboxLayoutChild {
34    fn modify_style<F>(&mut self, fnc: F)
35    where
36        F: Fn(&mut Style),
37    {
38        match self {
39            FlexboxLayoutChild::Item(item) => fnc(&mut item.style),
40            FlexboxLayoutChild::Flexbox(layout) => fnc(&mut layout.inner.borrow_mut().style),
41        }
42    }
43}
44
45/// This is the inner data shared between the callback and the application
46struct FlexboxLayoutInner {
47    base: HWND,
48    handler: Option<RawEventHandler>,
49    style: Style,
50    children: Vec<FlexboxLayoutChild>,
51    parent_layout: Option<FlexboxLayout>,
52}
53
54/**
55    A flexbox layout that organizes the children control in a parent control.
56    Flexbox uses the stretch library internally ( <https://github.com/vislyhq/stretch> ).
57
58    FlexboxLayout requires the `flexbox` feature.
59*/
60#[derive(Clone)]
61pub struct FlexboxLayout {
62    inner: Rc<RefCell<FlexboxLayoutInner>>,
63}
64
65impl FlexboxLayout {
66    pub fn builder() -> FlexboxLayoutBuilder {
67        let layout = FlexboxLayoutInner {
68            base: ptr::null_mut(),
69            handler: None,
70            style: Default::default(),
71            children: Vec::new(),
72            parent_layout: None,
73        };
74
75        FlexboxLayoutBuilder {
76            layout,
77            current_index: None,
78            auto_size: true,
79            auto_spacing: Some(5),
80        }
81    }
82
83    /**
84        Returns the style of the parent control
85
86        Panic:
87        - The layout must have been successfully built otherwise this function will panic.
88    */
89    pub fn style(&self) -> Style {
90        let inner = self.inner.borrow();
91        if inner.base.is_null() {
92            panic!("Flexbox layout is not yet initialized!");
93        }
94
95        inner.style.clone()
96    }
97
98    /**
99        Sets the style of the layout parent control
100
101        Panic:
102        - The layout must have been successfully built otherwise this function will panic.
103    */
104    pub fn set_style(&self, style: Style) {
105        let mut inner = self.inner.borrow_mut();
106        if inner.base.is_null() {
107            panic!("Flexbox layout is not yet initialized!");
108        }
109
110        inner.style = style;
111    }
112
113    /**
114        Add a new children in the layout with the stretch style.
115
116        Panic:
117        * If the control is not a window-like control
118        * If the layout was not initialized
119    */
120    pub fn add_child<W: Into<ControlHandle>>(
121        &self,
122        c: W,
123        style: Style,
124    ) -> Result<(), stretch::Error> {
125        {
126            let mut inner = self.inner.borrow_mut();
127            if inner.base.is_null() {
128                panic!("Flexbox layout is not yet initialized!");
129            }
130
131            let item = FlexboxLayoutItem {
132                control: c
133                    .into()
134                    .hwnd()
135                    .expect("Control must be window like (HWND handle)"),
136                style,
137            };
138
139            inner.children.push(FlexboxLayoutChild::Item(item));
140        }
141
142        self.fit()
143    }
144
145    /**
146        Remove a children from the layout
147
148        Panic:
149        * If the control is not a window-like control
150        * If the control is not in the layout (see `has_child`)
151        * If the layout was not initialized
152    */
153    pub fn remove_child<W: Into<ControlHandle>>(&self, c: W) {
154        let mut inner = self.inner.borrow_mut();
155        if inner.base.is_null() {
156            panic!("Flexbox layout is not yet initialized!");
157        }
158
159        let handle = c
160            .into()
161            .hwnd()
162            .expect("Control must be window like (HWND handle)");
163        let index = inner
164            .children
165            .iter()
166            .position(|child| child.is_item() && child.as_item().control == handle);
167
168        match index {
169            Some(i) => {
170                inner.children.remove(i);
171            }
172            None => {
173                panic!("Control was not found in layout");
174            }
175        }
176    }
177
178    /**
179        Check if the selected control is a children in the layout.
180        Does not check in the sublayouts
181
182        Panic:
183        * If the control is not a window-like control.
184        * If the layout was not initialized
185    */
186    pub fn has_child<W: Into<ControlHandle>>(&self, c: W) -> bool {
187        let inner = self.inner.borrow();
188        if inner.base.is_null() {
189            panic!("Flexbox layout is not yet initialized!");
190        }
191
192        let handle = c
193            .into()
194            .hwnd()
195            .expect("Control must be window like (HWND handle)");
196        inner
197            .children
198            .iter()
199            .any(|child| child.is_item() && child.as_item().control == handle)
200    }
201
202    /**
203        Borrow the inner value of the flexbox layout. While the returned value lives, calling other method
204        of the the flexbox layout that modify the inner state will cause a panic. Simple looktup (ex: `has_child`) will still work.
205
206        Panic:
207        - The layout must have been successfully built otherwise this function will panic.
208    */
209    pub fn children(&self) -> FlexboxLayoutChildren<'_> {
210        let inner = self.inner.borrow();
211        if inner.base.is_null() {
212            panic!("Flexbox layout is not yet initialized!");
213        }
214
215        FlexboxLayoutChildren { inner }
216    }
217
218    /**
219        Borrow the inner value of the flexbox layout as mutable. While the returned value lives, calling other method
220        of the the flexbox layout will cause a panic.
221
222        If the children of the layout were modified, call `fit` to update the layout after `FlexboxLayoutChildrenMut` is dropped.
223
224        Panic:
225        - The layout must have been successfully built otherwise this function will panic.
226    */
227    pub fn children_mut(&self) -> FlexboxLayoutChildrenMut<'_> {
228        let inner = self.inner.borrow_mut();
229        if inner.base.is_null() {
230            panic!("Flexbox layout is not yet initialized!");
231        }
232
233        FlexboxLayoutChildrenMut { inner }
234    }
235
236    /**
237        Resize the layout to fit the parent window size
238
239        Panic:
240        - The layout must have been successfully built otherwise this function will panic.
241    */
242    pub fn fit(&self) -> Result<(), stretch::Error> {
243        let inner = self.inner.borrow();
244        if inner.base.is_null() {
245            panic!("FlexboxLayout is not bound to a parent control.")
246        }
247
248        if let Some(parent_layout) = &inner.parent_layout {
249            parent_layout.fit()
250        } else {
251            let (w, h) = wh::get_window_size(inner.base);
252            self.update_layout(w, h, (0, 0))
253        }
254    }
255
256    // Utility function to compile tree of children nodes for layout purposes
257    // Also returns the total number of children items to allow cleaner deferred positioning
258    fn build_child_nodes(
259        children: &Vec<FlexboxLayoutChild>,
260        stretch: &mut Stretch,
261    ) -> Result<(usize, Vec<Node>), stretch::Error> {
262        let mut nodes = Vec::new();
263        let mut item_count = 0;
264
265        for child in children.iter() {
266            match child {
267                FlexboxLayoutChild::Item(child) => {
268                    nodes.push(stretch.new_node(child.style, Vec::new())?);
269                    item_count += 1;
270                }
271                FlexboxLayoutChild::Flexbox(child) => {
272                    let (child_count, child_nodes) =
273                        FlexboxLayout::build_child_nodes(child.children().children(), stretch)?;
274                    nodes.push(stretch.new_node(child.style(), child_nodes)?);
275                    item_count += child_count;
276                }
277            };
278        }
279
280        Ok((item_count, nodes))
281    }
282
283    // Applies the calculated item positions for this layout
284    // Uses deferred window positioning to prevent rendering artefacts
285    fn apply_layout_deferred(
286        positioner: &mut wh::DeferredWindowPositioner,
287        stretch: &mut Stretch,
288        nodes: Vec<Node>,
289        children: &Vec<FlexboxLayoutChild>,
290        last_handle: &mut Option<HWND>,
291        offset: (i32, i32),
292    ) -> Result<(), stretch::Error> {
293        use FlexboxLayoutChild as Child;
294
295        for (node, child) in nodes.into_iter().zip(children.iter()) {
296            let layout = stretch.layout(node)?;
297            let Point { x, y } = layout.location;
298            let Size { width, height } = layout.size;
299
300            match child {
301                Child::Item(child) => {
302                    positioner
303                        .defer_pos(
304                            child.control,
305                            last_handle.unwrap_or(std::ptr::null_mut()),
306                            x as i32 + offset.0,
307                            y as i32 + offset.1,
308                            width as i32,
309                            height as i32,
310                        )
311                        .ok();
312                    last_handle.replace(child.control);
313                }
314                Child::Flexbox(child) => {
315                    let children_nodes = stretch.children(node)?;
316                    FlexboxLayout::apply_layout_deferred(
317                        positioner,
318                        stretch,
319                        children_nodes,
320                        child.children().children(),
321                        last_handle,
322                        (x as i32, y as i32),
323                    )?;
324                }
325            }
326        }
327
328        Ok(())
329    }
330
331    // Applies the calculated item positions for this layout
332    // Uses immediate window positioning, which might cause visual artefacts in some cases
333    fn apply_layout_immediate(
334        stretch: &mut Stretch,
335        nodes: Vec<Node>,
336        children: &Vec<FlexboxLayoutChild>,
337        last_handle: &mut Option<HWND>,
338        offset: (i32, i32),
339    ) -> Result<(), stretch::Error> {
340        use FlexboxLayoutChild as Child;
341
342        for (node, child) in nodes.into_iter().zip(children.iter()) {
343            let layout = stretch.layout(node)?;
344            let Point { x, y } = layout.location;
345            let Size { width, height } = layout.size;
346
347            match child {
348                Child::Item(child) => {
349                    wh::set_window_position(
350                        child.control,
351                        x as i32 + offset.0,
352                        y as i32 + offset.1,
353                    );
354                    wh::set_window_size(child.control, width as u32, height as u32, false);
355                    wh::set_window_after(child.control, *last_handle);
356                    last_handle.replace(child.control);
357                }
358                Child::Flexbox(child) => {
359                    let children_nodes = stretch.children(node)?;
360                    FlexboxLayout::apply_layout_immediate(
361                        stretch,
362                        children_nodes,
363                        child.children().children(),
364                        last_handle,
365                        (x as i32, y as i32),
366                    )?;
367                }
368            }
369        }
370
371        Ok(())
372    }
373
374    fn update_layout(
375        &self,
376        width: u32,
377        height: u32,
378        offset: (i32, i32),
379    ) -> Result<(), stretch::Error> {
380        let inner = self.inner.borrow();
381        if inner.base.is_null() || inner.children.len() == 0 {
382            return Ok(());
383        }
384
385        let mut stretch = Stretch::new();
386        let (item_count, nodes) = FlexboxLayout::build_child_nodes(&inner.children, &mut stretch)?;
387
388        let mut style = inner.style.clone();
389        style.size = Size {
390            width: Dimension::Points(width as f32),
391            height: Dimension::Points(height as f32),
392        };
393        let node = stretch.new_node(style, nodes.clone())?;
394
395        stretch.compute_layout(node, Size::undefined())?;
396
397        // Keep a fallback case to prevent panics if the layout is too large to be deferred
398        if let Ok(mut positioner) = wh::DeferredWindowPositioner::new(item_count as i32) {
399            let layout_result = FlexboxLayout::apply_layout_deferred(
400                &mut positioner,
401                &mut stretch,
402                nodes,
403                self.children().children(),
404                &mut None,
405                offset,
406            );
407            positioner.end();
408
409            layout_result
410        } else {
411            FlexboxLayout::apply_layout_immediate(
412                &mut stretch,
413                nodes,
414                self.children().children(),
415                &mut None,
416                offset,
417            )
418        }
419    }
420}
421
422pub struct FlexboxLayoutBuilder {
423    layout: FlexboxLayoutInner,
424    current_index: Option<usize>,
425    auto_size: bool,
426    auto_spacing: Option<u32>,
427}
428
429impl FlexboxLayoutBuilder {
430    /// Set the layout parent. The handle must be a window object otherwise the function will panic
431    pub fn parent<W: Into<ControlHandle>>(mut self, p: W) -> FlexboxLayoutBuilder {
432        self.layout.base = p.into().hwnd().expect("Parent must be HWND");
433        self
434    }
435
436    /// Add a new child to the layout build.
437    /// Panics if `child` is not a window-like control.
438    pub fn child<W: Into<ControlHandle>>(mut self, child: W) -> FlexboxLayoutBuilder {
439        self.current_index = Some(self.layout.children.len());
440
441        let item = FlexboxLayoutItem {
442            control: child.into().hwnd().unwrap(),
443            style: Style::default(),
444        };
445
446        self.layout.children.push(FlexboxLayoutChild::Item(item));
447
448        self
449    }
450
451    /// Add a new child layout to the layout build.
452    pub fn child_layout(mut self, child: &FlexboxLayout) -> FlexboxLayoutBuilder {
453        self.current_index = Some(self.layout.children.len());
454
455        self.layout
456            .children
457            .push(FlexboxLayoutChild::Flexbox(child.clone()));
458
459        self
460    }
461
462    /// Make it so that the children of the layout all have equal size
463    /// This flags is erased when `size`, `max_size`, or `min_size` is set on the children.
464    pub fn auto_size(mut self, auto: bool) -> FlexboxLayoutBuilder {
465        self.auto_size = auto;
466        self
467    }
468
469    /// Automatically generate padding and margin for the parent layout and the children from the selected value.
470    /// This flags is erased when `padding` is called on the layout or when `child_margin` is called on the children
471    pub fn auto_spacing(mut self, auto: Option<u32>) -> FlexboxLayoutBuilder {
472        self.auto_spacing = auto;
473        self
474    }
475
476    //
477    // Base layout style
478    //
479
480    pub fn direction(mut self, value: Direction) -> FlexboxLayoutBuilder {
481        self.layout.style.direction = value;
482        self
483    }
484
485    pub fn flex_direction(mut self, value: FlexDirection) -> FlexboxLayoutBuilder {
486        self.layout.style.flex_direction = value;
487        self
488    }
489
490    pub fn flex_wrap(mut self, value: FlexWrap) -> FlexboxLayoutBuilder {
491        self.layout.style.flex_wrap = value;
492        self
493    }
494
495    pub fn overflow(mut self, value: Overflow) -> FlexboxLayoutBuilder {
496        self.layout.style.overflow = value;
497        self
498    }
499
500    pub fn align_items(mut self, value: AlignItems) -> FlexboxLayoutBuilder {
501        self.layout.style.align_items = value;
502        self
503    }
504
505    pub fn align_content(mut self, value: AlignContent) -> FlexboxLayoutBuilder {
506        self.layout.style.align_content = value;
507        self
508    }
509
510    pub fn justify_content(mut self, value: JustifyContent) -> FlexboxLayoutBuilder {
511        self.layout.style.justify_content = value;
512        self
513    }
514
515    pub fn padding(mut self, value: Rect<Dimension>) -> FlexboxLayoutBuilder {
516        self.layout.style.padding = value;
517        self.auto_spacing = None;
518        self
519    }
520
521    pub fn border(mut self, value: Rect<Dimension>) -> FlexboxLayoutBuilder {
522        self.layout.style.border = value;
523        self
524    }
525
526    pub fn min_size(mut self, value: Size<Dimension>) -> FlexboxLayoutBuilder {
527        self.layout.style.min_size = value;
528        self
529    }
530
531    pub fn max_size(mut self, value: Size<Dimension>) -> FlexboxLayoutBuilder {
532        self.layout.style.max_size = value;
533        self
534    }
535
536    pub fn aspect_ratio(mut self, value: Number) -> FlexboxLayoutBuilder {
537        self.layout.style.aspect_ratio = value;
538        self
539    }
540
541    //
542    // Child layout style
543    //
544
545    /// Set the size of of the current child.
546    /// Panics if `child` was not called before.
547    pub fn child_size(mut self, size: Size<Dimension>) -> FlexboxLayoutBuilder {
548        self.modify_current_child_style(|s| s.size = size);
549        self.auto_size = false;
550        self
551    }
552
553    /// Set the position of the current child.
554    /// Panics if `child` was not called before.
555    pub fn child_position(mut self, position: Rect<Dimension>) -> FlexboxLayoutBuilder {
556        self.modify_current_child_style(|s| s.position = position);
557        self
558    }
559
560    /// Set the margin of the current child.
561    /// Panics if `child` was not called before.
562    pub fn child_margin(mut self, value: Rect<Dimension>) -> FlexboxLayoutBuilder {
563        self.modify_current_child_style(|s| s.margin = value);
564        self.auto_spacing = None;
565        self
566    }
567
568    /// Set the min size of the current child.
569    /// Panics if `child` was not called before.
570    pub fn child_min_size(mut self, value: Size<Dimension>) -> FlexboxLayoutBuilder {
571        self.modify_current_child_style(|s| s.min_size = value);
572        self.auto_size = false;
573        self
574    }
575
576    /// Set the max size of the current child.
577    /// Panics if `child` was not called before.
578    pub fn child_max_size(mut self, value: Size<Dimension>) -> FlexboxLayoutBuilder {
579        self.modify_current_child_style(|s| s.max_size = value);
580        self.auto_size = false;
581        self
582    }
583
584    /// Panics if `child` was not called before.
585    pub fn child_flex_grow(mut self, value: f32) -> FlexboxLayoutBuilder {
586        self.modify_current_child_style(|s| s.flex_grow = value);
587        self.auto_size = false;
588        self
589    }
590
591    /// Panics if `child` was not called before.
592    pub fn child_flex_shrink(mut self, value: f32) -> FlexboxLayoutBuilder {
593        self.modify_current_child_style(|s| s.flex_shrink = value);
594        self.auto_size = false;
595        self
596    }
597
598    /// Panics if `child` was not called before.
599    pub fn child_flex_basis(mut self, value: Dimension) -> FlexboxLayoutBuilder {
600        self.modify_current_child_style(|s| s.flex_basis = value);
601        self.auto_size = false;
602        self
603    }
604
605    /// Panics if `child` was not called before.
606    pub fn child_align_self(mut self, value: AlignSelf) -> FlexboxLayoutBuilder {
607        self.modify_current_child_style(|s| s.align_self = value);
608        self
609    }
610
611    /**
612        Directly set the style parameter of the current child. Panics if `child` was not called before.
613
614        If defining style is too verbose, other method such as `size` can be used.
615    */
616    pub fn style(mut self, style: Style) -> FlexboxLayoutBuilder {
617        self.modify_current_child_style(|s| *s = style);
618        self
619    }
620
621    fn modify_current_child_style<F>(&mut self, fnc: F)
622    where
623        F: Fn(&mut Style),
624    {
625        assert!(self.current_index.is_some(), "No current children");
626
627        let index = self.current_index.unwrap();
628
629        self.layout.children[index].modify_style(|s| fnc(s));
630    }
631
632    /// Build the layout object and bind the callback.
633    pub fn build(mut self, layout: &FlexboxLayout) -> Result<(), NwgError> {
634        use winapi::shared::minwindef::{HIWORD, LOWORD};
635        use winapi::um::winuser::WM_SIZE;
636
637        if self.layout.base.is_null() {
638            return Err(NwgError::layout_create(
639                "Flexboxlayout does not have a parent.",
640            ));
641        }
642
643        let (w, h) = wh::get_window_size(self.layout.base);
644        let base_handle = ControlHandle::Hwnd(self.layout.base);
645
646        // Auto compute size if enabled
647        if self.auto_size {
648            let children_count = self.layout.children.len();
649            let size = 1.0f32 / (children_count as f32);
650            for child in self.layout.children.iter_mut() {
651                let child_size = match &self.layout.style.flex_direction {
652                    FlexDirection::Row | FlexDirection::RowReverse => Size {
653                        width: Dimension::Percent(size),
654                        height: Dimension::Auto,
655                    },
656                    FlexDirection::Column | FlexDirection::ColumnReverse => Size {
657                        width: Dimension::Auto,
658                        height: Dimension::Percent(size),
659                    },
660                };
661
662                child.modify_style(|s| s.size = child_size);
663            }
664        }
665
666        // Auto spacing if enabled
667        if let Some(spacing) = self.auto_spacing {
668            let spacing = Dimension::Points(spacing as f32);
669            let spacing = Rect {
670                start: spacing,
671                end: spacing,
672                top: spacing,
673                bottom: spacing,
674            };
675            self.layout.style.padding = spacing;
676            for child in self.layout.children.iter_mut() {
677                child.modify_style(|s| s.margin = spacing);
678            }
679        }
680
681        // Saves the new layout. Free the old layout (if there is one)
682        {
683            let mut layout_inner = layout.inner.borrow_mut();
684            if layout_inner.handler.is_some() {
685                drop(unbind_raw_event_handler(
686                    layout_inner.handler.as_ref().unwrap(),
687                ));
688            }
689
690            *layout_inner = self.layout;
691        }
692
693        // Sets the parent_layout of any child layout to this layout
694        for child in layout.inner.borrow_mut().children.iter_mut() {
695            match child {
696                FlexboxLayoutChild::Item(_) => {}
697                FlexboxLayoutChild::Flexbox(child_layout) => {
698                    child_layout
699                        .inner
700                        .borrow_mut()
701                        .parent_layout
702                        .replace(layout.clone());
703                }
704            }
705        }
706
707        // Initial layout update
708        layout
709            .update_layout(w, h, (0, 0))
710            .expect("Failed to compute layout");
711
712        // Fetch a new ID for the layout handler
713        use std::sync::atomic::{AtomicUsize, Ordering};
714        static FLEX_LAYOUT_ID: AtomicUsize = AtomicUsize::new(0x9FFF);
715        let handler_id = FLEX_LAYOUT_ID.fetch_add(1, Ordering::SeqCst);
716
717        // Bind the event handler
718        let event_layout = layout.clone();
719        let cb = move |_h, msg, _w, l| {
720            if msg == WM_SIZE {
721                let size = l as u32;
722                let width = LOWORD(size) as i32;
723                let height = HIWORD(size) as i32;
724                let (w, h) = crate::win32::high_dpi::physical_to_logical(width, height);
725                FlexboxLayout::update_layout(&event_layout, w as u32, h as u32, (0, 0))
726                    .expect("Failed to compute layout!");
727            }
728            None
729        };
730
731        {
732            let mut layout_inner = layout.inner.borrow_mut();
733            layout_inner.handler =
734                Some(bind_raw_event_handler_inner(&base_handle, handler_id, cb).unwrap());
735        }
736
737        Ok(())
738    }
739
740    /// Build a "partial" layout object - this layout has no direct callback and needs to be added to a parent layout using child_layout
741    pub fn build_partial(mut self, layout: &FlexboxLayout) -> Result<(), NwgError> {
742        if self.layout.base.is_null() {
743            return Err(NwgError::layout_create(
744                "Flexboxlayout does not have a parent.",
745            ));
746        }
747
748        // Auto compute size if enabled
749        if self.auto_size {
750            let children_count = self.layout.children.len();
751            let size = 1.0f32 / (children_count as f32);
752            for child in self.layout.children.iter_mut() {
753                let child_size = match &self.layout.style.flex_direction {
754                    FlexDirection::Row | FlexDirection::RowReverse => Size {
755                        width: Dimension::Percent(size),
756                        height: Dimension::Auto,
757                    },
758                    FlexDirection::Column | FlexDirection::ColumnReverse => Size {
759                        width: Dimension::Auto,
760                        height: Dimension::Percent(size),
761                    },
762                };
763
764                child.modify_style(|s| s.size = child_size);
765            }
766        }
767
768        // Auto spacing if enabled
769        if let Some(spacing) = self.auto_spacing {
770            let spacing = Dimension::Points(spacing as f32);
771            let spacing = Rect {
772                start: spacing,
773                end: spacing,
774                top: spacing,
775                bottom: spacing,
776            };
777            self.layout.style.padding = spacing;
778            for child in self.layout.children.iter_mut() {
779                child.modify_style(|s| s.margin = spacing);
780            }
781        }
782
783        // Saves the new layout. Free the old layout (if there is one)
784        {
785            let mut layout_inner = layout.inner.borrow_mut();
786            if layout_inner.handler.is_some() {
787                drop(unbind_raw_event_handler(
788                    layout_inner.handler.as_ref().unwrap(),
789                ));
790            }
791
792            *layout_inner = self.layout;
793        }
794
795        Ok(())
796    }
797}
798
799impl Default for FlexboxLayout {
800    fn default() -> FlexboxLayout {
801        let inner = FlexboxLayoutInner {
802            base: ptr::null_mut(),
803            handler: None,
804            children: Vec::new(),
805            style: Default::default(),
806            parent_layout: None,
807        };
808
809        FlexboxLayout {
810            inner: Rc::new(RefCell::new(inner)),
811        }
812    }
813}
814
815impl FlexboxLayoutChild {
816    pub fn is_item(&self) -> bool {
817        match self {
818            FlexboxLayoutChild::Item(_) => true,
819            _ => false,
820        }
821    }
822
823    pub fn as_item<'a>(&'a self) -> &'a FlexboxLayoutItem {
824        match self {
825            FlexboxLayoutChild::Item(i) => i,
826            _ => panic!("FlexboxLayoutChild is not an item"),
827        }
828    }
829
830    pub fn as_item_mut<'a>(&'a mut self) -> &'a mut FlexboxLayoutItem {
831        match self {
832            FlexboxLayoutChild::Item(i) => i,
833            _ => panic!("FlexboxLayoutChild is not an item"),
834        }
835    }
836
837    pub fn is_flexbox(&self) -> bool {
838        match self {
839            FlexboxLayoutChild::Flexbox(_) => true,
840            _ => false,
841        }
842    }
843}
844
845/**
846    A wrapper that expose the inner collection of a flexboxlayout.
847*/
848pub struct FlexboxLayoutChildrenMut<'a> {
849    inner: RefMut<'a, FlexboxLayoutInner>,
850}
851
852impl<'a> FlexboxLayoutChildrenMut<'a> {
853    pub fn children<'b>(&'b mut self) -> &'b mut Vec<FlexboxLayoutChild> {
854        &mut self.inner.children
855    }
856}
857
858pub struct FlexboxLayoutChildren<'a> {
859    inner: Ref<'a, FlexboxLayoutInner>,
860}
861
862impl<'a> FlexboxLayoutChildren<'a> {
863    pub fn children<'b>(&'b self) -> &'b Vec<FlexboxLayoutChild> {
864        &self.inner.children
865    }
866}