ribir_core 0.4.0-alpha.59

A non-intrusive declarative GUI framework, to build modern native/wasm cross-platform applications.
Documentation
use super::*;

/// The event fired when the widget is mounted, performed layout or disposed.
pub type LifecycleEvent = CommonEvent;

#[cfg(test)]
mod tests {
  use std::collections::HashSet;

  use crate::{prelude::*, reset_test_env, test_helper::*};

  #[test]
  fn full_lifecycle() {
    reset_test_env!();

    let trigger = Stateful::new(0);
    let lifecycle = Stateful::new(vec![]);
    let c_lc = lifecycle.clone_reader();
    let c_trigger = trigger.clone_writer();
    let (is_empty, clean_trigger) = split_value(false);

    let w = fn_widget! {
      @MockBox {
        size: Size::zero(),
        @ {
          pipe!(*$read(is_empty)).map(move |v| {
            (!v).then(move || fn_widget!{
              @MockBox {
                size: Size::zero(),
                on_mounted: move |_| $write(lifecycle).push("static mounted"),
                on_performed_layout: move |_| $write(lifecycle).push("static performed layout"),
                on_disposed: move |_| $write(lifecycle).push("static disposed"),
                @ {
                  pipe!(*$read(trigger)).map(move |_| fn_widget!{
                    @MockBox {
                      size: Size::zero(),
                      on_mounted: move |_| $write(lifecycle).push("dyn mounted"),
                      on_performed_layout: move |_| $write(lifecycle).push("dyn performed layout"),
                      on_disposed: move |_| $write(lifecycle).push("dyn disposed")
                    }
                  })
                }
              }
            })
          })
        }
      }
    };

    let wnd = TestWindow::new_with_size(w, Size::new(100., 100.));
    assert_eq!(&**c_lc.read(), ["static mounted", "dyn mounted",]);

    wnd.draw_frame();

    assert_eq!(
      &**c_lc.read(),
      ["static mounted", "dyn mounted", "dyn performed layout", "static performed layout",]
    );
    {
      *c_trigger.write() += 1;
    }
    wnd.draw_frame();
    assert_eq!(
      &**c_lc.read(),
      [
        "static mounted",
        "dyn mounted",
        "dyn performed layout",
        "static performed layout",
        "dyn disposed",
        "dyn mounted",
        "dyn performed layout",
        "static performed layout",
      ]
    );

    {
      *clean_trigger.write() = true;
    }
    wnd.draw_frame();
    assert_eq!(
      &**c_lc.read(),
      [
        "static mounted",
        "dyn mounted",
        "dyn performed layout",
        "static performed layout",
        "dyn disposed",
        "dyn mounted",
        "dyn performed layout",
        "static performed layout",
        "static disposed",
        "dyn disposed"
      ]
    );
  }

  #[test]
  fn track_lifecycle() {
    reset_test_env!();

    let cnt = Stateful::new(3);
    let mounted: Stateful<HashSet<WidgetId>> = Stateful::new(HashSet::default());
    let disposed: Stateful<HashSet<WidgetId>> = Stateful::new(HashSet::default());

    let c_cnt = cnt.clone_writer();
    let c_mounted = mounted.clone_reader();
    let c_disposed = disposed.clone_reader();
    let w = fn_widget! {
      @MockMulti {
        @ {
          pipe!(*$read(cnt)).map(move |cnt| {
            (0..cnt).map(move |_| {
              @MockBox {
                size: Size::zero(),
                on_mounted: move |e| { $write(mounted).insert(e.id); },
                on_disposed: move |e| { $write(disposed).insert(e.id); },
              }
            })
          })
        }
      }
    };

    let wnd = TestWindow::new_with_size(w, Size::new(100., 100.));
    wnd.draw_frame();
    let mounted_ids = c_mounted.read().clone();

    *c_cnt.write() = 5;
    wnd.draw_frame();

    assert_eq!(mounted_ids.len(), 3);
    assert_eq!(&mounted_ids, &*c_disposed.read());
  }

  #[test]
  fn disposed_can_map_to_global_with_detached_parent() {
    reset_test_env!();

    let show = Stateful::new(true);
    let mounted_id = Stateful::new(None::<WidgetId>);
    let disposed_pos = Stateful::new(None::<Point>);

    let c_show = show.clone_writer();
    let c_mounted_id = mounted_id.clone_reader();
    let c_disposed_pos = disposed_pos.clone_reader();

    let w = fn_widget! {
      @MockBox {
        size: Size::new(200., 200.),
        x: 37.,
        y: 23.,
        @ {
          pipe!(*$read(show)).map(move |visible| {
            if visible {
              @MockBox {
                size: Size::new(50., 50.),
                x: 11.,
                y: 13.,
                on_mounted: move |e| *$write(mounted_id) = Some(e.id),
                on_disposed: move |e| *$write(disposed_pos) = Some(e.map_to_global(Point::zero())),
              }.into_widget()
            } else {
              @Void {}.into_widget()
            }
          })
        }
      }
    };

    let wnd = TestWindow::new_with_size(w, Size::new(400., 400.));
    wnd.draw_frame();
    let id = c_mounted_id
      .read()
      .expect("child should be mounted before dispose");
    let expected = wnd.map_to_global(Point::zero(), id);

    *c_show.write() = false;
    wnd.draw_frame();

    assert_eq!(*c_disposed_pos.read(), Some(expected));
  }
}