From 605cff3f834f77539d9ff8c92761d3642594b329 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Fri, 2 Apr 2021 23:51:25 +0300 Subject: [PATCH] Close #5 - allow `#[widget(recursive)]` on builder fields --- CHANGELOG.md | 1 + macros/src/widgets_from_builder_derive.rs | 26 +++++++++ tests/four_texts.glade | 59 ++++++++++++++++++++ tests/recusive_widgets_from_builder.rs | 65 +++++++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 tests/four_texts.glade create mode 100644 tests/recusive_widgets_from_builder.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index ede16e2265..616523d689 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `woab::NamespacedSignalRouter` for routing signals from the same builder to different actors. - `BuilderConnector::with_object`. +- `#[widget(nested)]` for nesting widget structs. ### Changed - [**BREAKING**] Updated Actix to 0.11 and Tokio to 1.14. Consequences: diff --git a/macros/src/widgets_from_builder_derive.rs b/macros/src/widgets_from_builder_derive.rs index c94c1c242d..bbab29de17 100644 --- a/macros/src/widgets_from_builder_derive.rs +++ b/macros/src/widgets_from_builder_derive.rs @@ -22,9 +22,19 @@ pub fn impl_widgets_from_builder_derive(ast: &syn::DeriveInput) -> Result { + if nested { + return Err(Error::new_spanned(value, "attribute `nested` can only be specified once")); + } + if value.is_some() { + return Err(Error::new_spanned(value, "attribute `nested` cannot have a value")); + } + nested = true; + } "name" => { let value = value.ok_or_else(|| Error::new_spanned(attr_name, "attribute `name` must have a value"))?; if name.is_some() { @@ -38,11 +48,27 @@ pub fn impl_widgets_from_builder_derive(ast: &syn::DeriveInput) -> Result ok, + Err(err) => return Err(err), + } + }, + }) + } + let field_type = &field.ty; let ident_as_str = match name { Some(syn::Expr::Lit(syn::ExprLit { diff --git a/tests/four_texts.glade b/tests/four_texts.glade new file mode 100644 index 0000000000..656522d73a --- /dev/null +++ b/tests/four_texts.glade @@ -0,0 +1,59 @@ + + + + + + False + + + True + False + vertical + + + True + True + + + False + True + 0 + + + + + True + True + + + False + True + 1 + + + + + True + True + + + False + True + 2 + + + + + True + True + + + False + True + 3 + + + + + + diff --git a/tests/recusive_widgets_from_builder.rs b/tests/recusive_widgets_from_builder.rs new file mode 100644 index 0000000000..808b1ade44 --- /dev/null +++ b/tests/recusive_widgets_from_builder.rs @@ -0,0 +1,65 @@ +use gtk::prelude::*; + +#[macro_use] +mod util; + +#[derive(woab::WidgetsFromBuilder)] +pub struct FlatWidgets { + text1: gtk::Entry, + text2: gtk::Entry, + text3: gtk::Entry, + text4: gtk::Entry, +} + +#[derive(woab::WidgetsFromBuilder)] +pub struct GroupedWidgets { + #[widget(nested)] + group_a: GroupA, + #[widget(nested)] + group_b: GroupB, +} + +#[derive(woab::WidgetsFromBuilder)] +pub struct GroupA { + text1: gtk::Entry, + text2: gtk::Entry, +} + +#[derive(woab::WidgetsFromBuilder)] +pub struct GroupB { + text3: gtk::Entry, + text4: gtk::Entry, +} + +#[test] +fn test_recusive_widgets_from_builder() -> anyhow::Result<()> { + let factory = woab::BuilderFactory::from(include_str!("four_texts.glade").to_owned()); + gtk::init()?; + woab::run_actix_inside_gtk_event_loop()?; + let bld = factory.instantiate(); + + let flat_widgets: FlatWidgets = bld.widgets()?; + let grouped_widgets: GroupedWidgets = bld.widgets()?; + + assert!(grouped_widgets.group_a.text1.get_text().is_empty()); + assert!(grouped_widgets.group_a.text2.get_text().is_empty()); + assert!(grouped_widgets.group_b.text3.get_text().is_empty()); + assert!(grouped_widgets.group_b.text4.get_text().is_empty()); + + flat_widgets.text1.set_text("Text 1"); + flat_widgets.text2.set_text("Text 2"); + flat_widgets.text3.set_text("Text 3"); + flat_widgets.text4.set_text("Text 4"); + + wait_for!(flat_widgets.text1.get_text() == "Text 1")?; + wait_for!(flat_widgets.text2.get_text() == "Text 2")?; + wait_for!(flat_widgets.text3.get_text() == "Text 3")?; + wait_for!(flat_widgets.text4.get_text() == "Text 4")?; + + assert!(grouped_widgets.group_a.text1.get_text() == "Text 1"); + assert!(grouped_widgets.group_a.text2.get_text() == "Text 2"); + assert!(grouped_widgets.group_b.text3.get_text() == "Text 3"); + assert!(grouped_widgets.group_b.text4.get_text() == "Text 4"); + + Ok(()) +}