layer_shika_composition/
shell_config.rs

1use layer_shika_adapters::platform::slint_interpreter::CompilationResult;
2use layer_shika_domain::prelude::{SurfaceConfig, UiSource};
3use std::path::PathBuf;
4use std::rc::Rc;
5
6/// Source for Slint UI definition
7///
8/// Specifies where to load the UI from: a `.slint` file, inline source code, or pre-compiled result.
9pub enum CompiledUiSource {
10    /// Load UI from a `.slint` file path
11    File(PathBuf),
12    /// Parse UI from source code string
13    Source(String),
14    /// Use pre-compiled Slint result
15    Compiled(Rc<CompilationResult>),
16}
17
18impl CompiledUiSource {
19    pub fn file(path: impl Into<PathBuf>) -> Self {
20        Self::File(path.into())
21    }
22
23    pub fn source(code: impl Into<String>) -> Self {
24        Self::Source(code.into())
25    }
26
27    pub fn compiled(result: Rc<CompilationResult>) -> Self {
28        Self::Compiled(result)
29    }
30}
31
32impl From<UiSource> for CompiledUiSource {
33    fn from(source: UiSource) -> Self {
34        match source {
35            UiSource::File(path) => Self::File(path),
36            UiSource::Source(code) => Self::Source(code),
37        }
38    }
39}
40
41impl From<Rc<CompilationResult>> for CompiledUiSource {
42    fn from(result: Rc<CompilationResult>) -> Self {
43        Self::Compiled(result)
44    }
45}
46
47impl From<&str> for CompiledUiSource {
48    fn from(s: &str) -> Self {
49        Self::File(PathBuf::from(s))
50    }
51}
52
53impl From<String> for CompiledUiSource {
54    fn from(s: String) -> Self {
55        Self::File(PathBuf::from(s))
56    }
57}
58
59impl From<PathBuf> for CompiledUiSource {
60    fn from(path: PathBuf) -> Self {
61        Self::File(path)
62    }
63}
64
65/// Declarative configuration for creating a shell with multiple surfaces
66///
67/// Useful for loading configuration from files or programmatic generation.
68pub struct ShellConfig {
69    pub ui_source: CompiledUiSource,
70    pub surfaces: Vec<SurfaceComponentConfig>,
71}
72
73/// Associates a Slint component name with its surface configuration
74#[derive(Debug, Clone)]
75pub struct SurfaceComponentConfig {
76    /// Name of the Slint component to instantiate
77    pub component: String,
78    /// Surface configuration for this component
79    pub config: SurfaceConfig,
80}
81
82impl ShellConfig {
83    /// Creates a new shell configuration from a UI source
84    pub fn new(ui_source: impl Into<CompiledUiSource>) -> Self {
85        Self {
86            ui_source: ui_source.into(),
87            surfaces: Vec::new(),
88        }
89    }
90
91    /// Adds a surface with the given component name
92    #[must_use]
93    pub fn with_surface(mut self, component: impl Into<String>) -> Self {
94        self.surfaces.push(SurfaceComponentConfig {
95            component: component.into(),
96            config: SurfaceConfig::default(),
97        });
98        self
99    }
100
101    /// Adds a surface with a complete configuration
102    #[must_use]
103    pub fn with_surface_config(
104        mut self,
105        component: impl Into<String>,
106        config: SurfaceConfig,
107    ) -> Self {
108        self.surfaces.push(SurfaceComponentConfig {
109            component: component.into(),
110            config,
111        });
112        self
113    }
114
115    /// Adds a surface and returns a mutable reference to it
116    pub fn add_surface(&mut self, component: impl Into<String>) -> &mut SurfaceComponentConfig {
117        self.surfaces.push(SurfaceComponentConfig {
118            component: component.into(),
119            config: SurfaceConfig::default(),
120        });
121        self.surfaces
122            .last_mut()
123            .unwrap_or_else(|| unreachable!("just pushed"))
124    }
125
126    /// Adds a surface with configuration and returns a mutable reference to it
127    pub fn add_surface_config(
128        &mut self,
129        component: impl Into<String>,
130        config: SurfaceConfig,
131    ) -> &mut SurfaceComponentConfig {
132        self.surfaces.push(SurfaceComponentConfig {
133            component: component.into(),
134            config,
135        });
136        self.surfaces
137            .last_mut()
138            .unwrap_or_else(|| unreachable!("just pushed"))
139    }
140}
141
142impl Default for ShellConfig {
143    fn default() -> Self {
144        Self {
145            ui_source: CompiledUiSource::Source(String::new()),
146            surfaces: Vec::new(),
147        }
148    }
149}
150
151impl SurfaceComponentConfig {
152    pub fn new(component: impl Into<String>) -> Self {
153        Self {
154            component: component.into(),
155            config: SurfaceConfig::default(),
156        }
157    }
158
159    pub fn with_config(component: impl Into<String>, config: SurfaceConfig) -> Self {
160        Self {
161            component: component.into(),
162            config,
163        }
164    }
165}