diff --git a/Cargo.lock b/Cargo.lock index ad49fe1..5cf1a42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1857,6 +1857,7 @@ version = "0.1.0" dependencies = [ "layer-shika-adapters", "layer-shika-domain", + "spin_on", "thiserror 2.0.17", ] diff --git a/Cargo.toml b/Cargo.toml index aa80324..d327059 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ categories = ["gui"] glutin = { version = "0.32.3", default-features = false, features = [ "wayland", ] } +spin_on = "0.1" log = "0.4.28" raw-window-handle = "0.6.2" slab = "0.4" diff --git a/composition/Cargo.toml b/composition/Cargo.toml index 7936f3b..e822126 100644 --- a/composition/Cargo.toml +++ b/composition/Cargo.toml @@ -16,4 +16,5 @@ workspace = true [dependencies] layer-shika-adapters.workspace = true layer-shika-domain.workspace = true +spin_on.workspace = true thiserror.workspace = true diff --git a/composition/src/builder.rs b/composition/src/builder.rs index d84f3d2..45f5d62 100644 --- a/composition/src/builder.rs +++ b/composition/src/builder.rs @@ -1,9 +1,12 @@ use crate::Result; use crate::system::WindowingSystem; -use layer_shika_adapters::platform::slint_interpreter::ComponentDefinition; +use layer_shika_adapters::platform::slint_interpreter::{Compiler, ComponentDefinition}; +use layer_shika_domain::errors::DomainError; use layer_shika_domain::prelude::{ AnchorEdges, KeyboardInteractivity, Layer, Margins, WindowConfig, }; +use spin_on::spin_on; +use std::path::{Path, PathBuf}; pub struct NeedsComponent; pub struct HasComponent { @@ -25,6 +28,89 @@ impl LayerShika { config: WindowConfig::default(), } } + + pub fn from_file( + path: impl AsRef, + component_name: Option<&str>, + ) -> Result> { + Self::from_file_with_compiler( + path, + &mut Compiler::default(), + component_name.unwrap_or("Main"), + ) + } + + pub fn from_file_with_compiler( + path: impl AsRef, + compiler: &mut Compiler, + component_name: &str, + ) -> Result> { + let compilation_result = spin_on(compiler.build_from_path(path.as_ref())); + let diagnostics: Vec<_> = compilation_result.diagnostics().collect(); + if !diagnostics.is_empty() { + let messages: Vec = diagnostics.iter().map(ToString::to_string).collect(); + return Err(DomainError::Configuration { + message: format!( + "Failed to compile Slint file '{}':\n{}", + path.as_ref().display(), + messages.join("\n") + ), + } + .into()); + } + + let definition = compilation_result.component(component_name).ok_or_else(|| { + DomainError::Configuration { + message: format!( + "Component '{}' not found in Slint file '{}'", + component_name, + path.as_ref().display() + ), + } + })?; + + Ok(Self::new(definition)) + } + + pub fn from_source( + source: impl AsRef, + component_name: Option<&str>, + ) -> Result> { + Self::from_source_with_compiler( + source, + &mut Compiler::default(), + component_name.unwrap_or("Main"), + ) + } + + pub fn from_source_with_compiler( + source: impl AsRef, + compiler: &mut Compiler, + component_name: &str, + ) -> Result> { + let compilation_result = + spin_on(compiler.build_from_source(source.as_ref().to_string(), PathBuf::default())); + + let diagnostics: Vec<_> = compilation_result.diagnostics().collect(); + if !diagnostics.is_empty() { + let messages: Vec = diagnostics.iter().map(ToString::to_string).collect(); + return Err(DomainError::Configuration { + message: format!( + "Failed to compile Slint source code:\n{}", + messages.join("\n") + ), + } + .into()); + } + + let definition = compilation_result.component(component_name).ok_or_else(|| { + DomainError::Configuration { + message: format!("Component '{}' not found in Slint source code", component_name), + } + })?; + + Ok(Self::new(definition)) + } } impl LayerShika {