use crate::{
RelmIterChildrenExt, WidgetRef,
factory::{FactoryView, positions::GridPosition},
};
use gtk::prelude::{FlowBoxChildExt, ListBoxRowExt};
macro_rules! assert_children {
($container:ident: None) => {
if let Some(child) = $container.iter_children().next() {
panic!("Container expected be empty, but there is at least one child: {child:?}");
}
};
($container:ident: $($child:ident),*) => {
{
let mut actual_children = $container.iter_children();
let mut index = 0;
$(
let actual = actual_children.next();
let expected = &$child;
if actual.as_ref().map(|widget| widget.widget_ref()) != Some(expected.widget_ref()) {
panic!(
"Children at index {index} does not match; expected: Some({expected:?}), actual: {actual:?}"
)
}
index += 1;
)+
if let Some(actual) = actual_children.next() {
panic!("Children at index {index} does not match; expected: None, actual: {actual:?}");
}
}
};
}
#[gtk::test]
fn box_factory_view() {
let gtk_box = gtk::Box::default();
let widget1 = gtk::Label::default();
let widget2 = gtk::Switch::default();
let widget3 = gtk::Entry::default();
let w2 = gtk_box.factory_append(&widget2, &());
let w3 = gtk_box.factory_insert_after(&widget3, &(), &w2);
let w1 = gtk_box.factory_prepend(&widget1, &());
assert_eq!(widget1, w1);
assert_eq!(widget2, w2);
assert_eq!(widget3, w3);
assert_eq!(gtk::Box::returned_widget_to_child(&w1), widget1);
assert_eq!(gtk::Box::returned_widget_to_child(&w2), widget2);
assert_eq!(gtk::Box::returned_widget_to_child(&w3), widget3);
assert_children!(gtk_box: w1, w2, w3);
gtk_box.factory_move_after(&w3, &w1);
assert_children!(gtk_box: w1, w3, w2);
gtk_box.factory_move_after(&w1, &w2);
assert_children!(gtk_box: w3, w2, w1);
gtk_box.factory_move_start(&w2);
assert_children!(gtk_box: w2, w3, w1);
gtk_box.factory_move_start(&w1);
assert_children!(gtk_box: w1, w2, w3);
gtk_box.factory_remove(&w3);
assert_children!(gtk_box: w1, w2);
gtk_box.factory_remove(&w2);
assert_children!(gtk_box: w1);
gtk_box.factory_remove(&w1);
assert_children!(gtk_box: None);
}
#[gtk::test]
fn grid_factory_view() {
let grid = gtk::Grid::default();
let widget1 = gtk::Label::default();
let widget2 = gtk::Switch::default();
let widget3 = gtk::Entry::default();
let pos1 = GridPosition {
column: 0,
row: 0,
width: 1,
height: 1,
};
let pos2 = GridPosition {
column: 1,
row: 0,
width: 1,
height: 2,
};
let pos3 = GridPosition {
column: 0,
row: 1,
width: 1,
height: 1,
};
let w2 = grid.factory_append(&widget2, &pos2);
let w3 = grid.factory_append(&widget3, &pos3);
let w1 = grid.factory_append(&widget1, &pos1);
assert_eq!(widget1, w1);
assert_eq!(widget2, w2);
assert_eq!(widget3, w3);
assert_eq!(gtk::Grid::returned_widget_to_child(&w1), widget1);
assert_eq!(gtk::Grid::returned_widget_to_child(&w2), widget2);
assert_eq!(gtk::Grid::returned_widget_to_child(&w3), widget3);
assert_children!(grid: w1, w2, w3);
grid.factory_remove(&w3);
assert_children!(grid: w1, w2);
grid.factory_remove(&w2);
assert_children!(grid: w1);
grid.factory_remove(&w1);
assert_children!(grid: None);
}
#[gtk::test]
fn stack_factory_view() {
let stack = gtk::Stack::default();
let widget1 = gtk::Label::default();
let widget2 = gtk::Switch::default();
let widget3 = gtk::Entry::default();
let page1 = stack.factory_append(&widget1, &());
let page2 = stack.factory_append(&widget2, &());
let page3 = stack.factory_append(&widget3, &());
assert_eq!(page1.child(), widget1);
assert_eq!(page2.child(), widget2);
assert_eq!(page3.child(), widget3);
assert_eq!(gtk::Stack::returned_widget_to_child(&page1), widget1);
assert_eq!(gtk::Stack::returned_widget_to_child(&page2), widget2);
assert_eq!(gtk::Stack::returned_widget_to_child(&page3), widget3);
assert_children!(stack: widget1, widget2, widget3);
stack.factory_remove(&page2);
assert_children!(stack: widget1, widget3);
stack.factory_remove(&page3);
assert_children!(stack: widget1);
stack.factory_remove(&page1);
assert_children!(stack: None);
}
#[gtk::test]
fn list_box_factory_view() {
let list_box = gtk::ListBox::default();
let widget1 = gtk::Label::default();
let widget2 = gtk::ListBoxRow::default();
let widget3 = gtk::Entry::default();
let row2 = list_box.factory_append(&widget2, &());
let row3 = list_box.factory_insert_after(&widget3, &(), &row2);
let row1 = list_box.factory_prepend(&widget1, &());
assert_eq!(row1.child().as_ref(), Some(widget1.as_ref()));
assert_eq!(row2, widget2);
assert_eq!(row3.child().as_ref(), Some(widget3.as_ref()));
assert_eq!(gtk::ListBox::returned_widget_to_child(&row1), widget1);
assert_eq!(gtk::ListBox::returned_widget_to_child(&row2), widget2);
assert_eq!(gtk::ListBox::returned_widget_to_child(&row3), widget3);
assert_children!(list_box: row1, row2, row3);
list_box.factory_move_after(&row3, &row1);
assert_children!(list_box: row1, row3, row2);
list_box.factory_move_after(&row1, &row2);
assert_children!(list_box: row3, row2, row1);
list_box.factory_move_start(&row2);
assert_children!(list_box: row2, row3, row1);
list_box.factory_move_start(&row1);
assert_children!(list_box: row1, row2, row3);
list_box.factory_remove(&row3);
assert_children!(list_box: row1, row2);
list_box.factory_remove(&row2);
assert_children!(list_box: row1);
list_box.factory_remove(&row1);
assert_children!(list_box: None);
}
#[gtk::test]
fn flow_box_factory_view() {
let flow_box = gtk::FlowBox::default();
let widget1 = gtk::Label::default();
let widget2 = gtk::FlowBoxChild::default();
let widget3 = gtk::Entry::default();
let child2 = flow_box.factory_append(&widget2, &());
let child3 = flow_box.factory_insert_after(&widget3, &(), &child2);
let child1 = flow_box.factory_prepend(&widget1, &());
assert_eq!(child1.child().as_ref(), Some(widget1.as_ref()));
assert_eq!(child2, widget2);
assert_eq!(child3.child().as_ref(), Some(widget3.as_ref()));
assert_eq!(gtk::FlowBox::returned_widget_to_child(&child1), widget1);
assert_eq!(gtk::FlowBox::returned_widget_to_child(&child2), widget2);
assert_eq!(gtk::FlowBox::returned_widget_to_child(&child3), widget3);
assert_children!(flow_box: child1, child2, child3);
flow_box.factory_move_after(&child3, &child1);
assert_children!(flow_box: child1, child3, child2);
flow_box.factory_move_after(&child1, &child2);
assert_children!(flow_box: child3, child2, child1);
flow_box.factory_move_start(&child2);
assert_children!(flow_box: child2, child3, child1);
flow_box.factory_move_start(&child1);
assert_children!(flow_box: child1, child2, child3);
flow_box.factory_remove(&child3);
assert_children!(flow_box: child1, child2);
flow_box.factory_remove(&child2);
assert_children!(flow_box: child1);
flow_box.factory_remove(&child1);
assert_children!(flow_box: None);
}
#[gtk::test]
#[cfg(feature = "libadwaita")]
fn tab_view_factory_view() {
let tab_view = adw::TabView::default();
let widget1 = gtk::Label::default();
let widget2 = gtk::Switch::default();
let widget3 = gtk::Entry::default();
let page2 = tab_view.factory_append(&widget2, &());
let page3 = tab_view.factory_insert_after(&widget3, &(), &page2);
let page1 = tab_view.factory_prepend(&widget1, &());
assert_eq!(page1.child(), widget1);
assert_eq!(page2.child(), widget2);
assert_eq!(page3.child(), widget3);
assert_eq!(adw::TabView::returned_widget_to_child(&page1), widget1);
assert_eq!(adw::TabView::returned_widget_to_child(&page2), widget2);
assert_eq!(adw::TabView::returned_widget_to_child(&page3), widget3);
assert_children!(tab_view: widget1, widget2, widget3);
tab_view.factory_move_after(&page3, &page1);
assert_children!(tab_view: widget1, widget3, widget2);
tab_view.factory_move_after(&page1, &page2);
assert_children!(tab_view: widget3, widget2, widget1);
tab_view.factory_move_start(&page2);
assert_children!(tab_view: widget2, widget3, widget1);
}