From e12d5f7fb978d8e175bf40cea8ff200bbd99151e Mon Sep 17 00:00:00 2001 From: Byson94 Date: Fri, 7 Nov 2025 20:22:56 +0530 Subject: [PATCH] feat: add gtk_ui function for loading .ui --- CHANGELOG.md | 6 ++++++ Cargo.lock | 2 +- crates/ewwii/src/widgets/build_widget.rs | 3 +++ .../ewwii/src/widgets/widget_definitions.rs | 19 +++++++++++++++++++ crates/rhai_impl/src/ast.rs | 6 ++++++ crates/rhai_impl/src/builtins.rs | 11 +++++++++++ crates/rhai_impl/src/dyn_id.rs | 2 ++ 7 files changed, 48 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8396a15..152043c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to `ewwii` are documented here. This changelog follows the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format, and this project adheres to [Semantic Versioning](https://semver.org/). +## [UNRELEASED] + +## Added + +- `gtk_ui` function for loading .ui files. + ## [0.3.1] - 2025-11-01 ## Fixed diff --git a/Cargo.lock b/Cargo.lock index d77e69c..fbea690 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -486,7 +486,7 @@ dependencies = [ [[package]] name = "ewwii" -version = "0.3.0" +version = "0.3.1" dependencies = [ "anyhow", "bincode", diff --git a/crates/ewwii/src/widgets/build_widget.rs b/crates/ewwii/src/widgets/build_widget.rs index d7e255a..c004035 100644 --- a/crates/ewwii/src/widgets/build_widget.rs +++ b/crates/ewwii/src/widgets/build_widget.rs @@ -56,6 +56,9 @@ fn build_gtk_widget_from_node( WidgetNode::CircularProgress { props } => { build_circular_progress_bar(props, widget_reg)?.upcast() } + WidgetNode::GtkUI { props } => { + build_gtk_ui_file(props)?.upcast() + } // WidgetNode::Graph { props } => build_graph(props, widget_reg)?.upcast(), // WidgetNode::Transform { props } => build_transform(props, widget_reg)?.upcast(), WidgetNode::Slider { props } => build_gtk_scale(props, widget_reg)?.upcast(), diff --git a/crates/ewwii/src/widgets/widget_definitions.rs b/crates/ewwii/src/widgets/widget_definitions.rs index 9fff13b..d192e62 100644 --- a/crates/ewwii/src/widgets/widget_definitions.rs +++ b/crates/ewwii/src/widgets/widget_definitions.rs @@ -1971,6 +1971,25 @@ pub(super) fn build_gtk_combo_box_text( Ok(gtk_widget) } +pub(super) fn build_gtk_ui_file( + props: &Map, +) -> Result { + let path = get_string_prop(&props, "file", None)?; + let main_id = get_string_prop(&props, "id", None)?; + + if !std::path::Path::new(&path).exists() { + return Err(anyhow::anyhow!("UI file not found: {}", path)); + } + + let builder = gtk4::Builder::from_file(&path); + + let gtk_widget = builder + .object(&main_id) + .ok_or_else(|| anyhow::anyhow!("No widget with id '{}' in {}", main_id, path))?; + + Ok(gtk_widget) +} + pub(super) fn build_gtk_expander( props: &Map, children: &Vec, diff --git a/crates/rhai_impl/src/ast.rs b/crates/rhai_impl/src/ast.rs index d4b2c6f..9f7faf3 100644 --- a/crates/rhai_impl/src/ast.rs +++ b/crates/rhai_impl/src/ast.rs @@ -32,7 +32,10 @@ pub enum WidgetNode { Transform { props: Map }, EventBox { props: Map, children: Vec }, ToolTip { props: Map, children: Vec }, + + // Special LocalBind { props: Map, children: Vec }, + GtkUI { props: Map }, // Top-level macros DefWindow { name: String, props: Map, node: Box }, @@ -166,6 +169,9 @@ pub fn get_id_to_widget_info<'a>( get_id_to_widget_info(child, id_to_props, Some(id))?; } } + WidgetNode::GtkUI { props } => { + insert_wdgt_info(node, props, "GtkUI", &[], parent_id, id_to_props)?; + } WidgetNode::ColorChooser { props } => { // let id = hash_props_and_type(props, "ColorChooser"); insert_wdgt_info(node, props, "ColorChooser", &[], parent_id, id_to_props)?; diff --git a/crates/rhai_impl/src/builtins.rs b/crates/rhai_impl/src/builtins.rs index 2d0d02d..b47e0a8 100644 --- a/crates/rhai_impl/src/builtins.rs +++ b/crates/rhai_impl/src/builtins.rs @@ -84,6 +84,17 @@ pub fn register_all_widgets( register_with_children!("tooltip", ToolTip); register_with_children!("localbind", LocalBind); + // == Special widget + engine.register_fn( + "gtk_ui", + |path: &str, load: &str| -> Result> { + let mut props = Map::new(); + props.insert("file".into(), path.into()); + props.insert("id".into(), load.into()); + Ok(WidgetNode::GtkUI { props }) + }, + ); + // == Special signal let keep_signal_clone = keep_signal.clone(); engine.register_fn( diff --git a/crates/rhai_impl/src/dyn_id.rs b/crates/rhai_impl/src/dyn_id.rs index a18618a..4829538 100644 --- a/crates/rhai_impl/src/dyn_id.rs +++ b/crates/rhai_impl/src/dyn_id.rs @@ -106,6 +106,7 @@ impl WidgetNode { | node @ WidgetNode::ColorChooser { props } | node @ WidgetNode::CircularProgress { props } | node @ WidgetNode::Graph { props } + | node @ WidgetNode::GtkUI { props } | node @ WidgetNode::Transform { props } => { let new_props = with_dyn_id(props.clone(), parent_path); match node { @@ -129,6 +130,7 @@ impl WidgetNode { WidgetNode::CircularProgress { props: new_props } } WidgetNode::Graph { .. } => WidgetNode::Graph { props: new_props }, + WidgetNode::GtkUI { .. } => WidgetNode::GtkUI { props: new_props }, WidgetNode::Transform { .. } => WidgetNode::Transform { props: new_props }, _ => unreachable!(), }