1use crate::{
2 Error, LayerSurfaceHandle, Shell,
3 selector::{Selector, SurfaceInfo},
4 slint_interpreter::{ComponentInstance, Value},
5};
6use layer_shika_domain::{
7 errors::DomainError, value_objects::surface_instance_id::SurfaceInstanceId,
8};
9
10#[derive(Debug)]
12pub struct PropertyError {
13 pub surface_name: String,
14 pub instance_id: SurfaceInstanceId,
15 pub error: String,
16}
17
18#[derive(Debug)]
20pub struct SelectionResult<T> {
21 pub success_count: usize,
22 pub values: Vec<T>,
23 pub failures: Vec<PropertyError>,
24}
25
26impl<T> SelectionResult<T> {
27 fn new() -> Self {
28 Self {
29 success_count: 0,
30 values: Vec::new(),
31 failures: Vec::new(),
32 }
33 }
34
35 fn add_success(&mut self, value: T) {
36 self.success_count += 1;
37 self.values.push(value);
38 }
39
40 fn add_failure(&mut self, surface_name: String, instance_id: SurfaceInstanceId, error: String) {
41 self.failures.push(PropertyError {
42 surface_name,
43 instance_id,
44 error,
45 });
46 }
47
48 pub fn is_ok(&self) -> bool {
49 self.failures.is_empty()
50 }
51
52 pub fn is_partial_failure(&self) -> bool {
53 !self.failures.is_empty() && self.success_count > 0
54 }
55
56 pub fn is_total_failure(&self) -> bool {
57 !self.failures.is_empty() && self.success_count == 0
58 }
59
60 pub fn into_result(self) -> Result<Vec<T>, Error> {
61 if self.failures.is_empty() {
62 Ok(self.values)
63 } else {
64 let error_messages: Vec<String> = self
65 .failures
66 .iter()
67 .map(|e| format!("{}[{:?}]: {}", e.surface_name, e.instance_id, e.error))
68 .collect();
69 Err(Error::Domain(DomainError::Configuration {
70 message: format!(
71 "Operation failed on {} surface(s): {}",
72 self.failures.len(),
73 error_messages.join(", ")
74 ),
75 }))
76 }
77 }
78}
79
80pub struct Selection<'a> {
85 shell: &'a Shell,
86 selector: Selector,
87}
88
89impl<'a> Selection<'a> {
90 pub(crate) fn new(shell: &'a Shell, selector: Selector) -> Self {
91 Self { shell, selector }
92 }
93
94 pub fn on_callback<F, R>(&self, callback_name: &str, handler: F) -> &Self
103 where
104 F: Fn(crate::CallbackContext) -> R + Clone + 'static,
105 R: crate::IntoValue,
106 {
107 self.shell
108 .on_internal(&self.selector, callback_name, handler);
109 self
110 }
111
112 pub fn on_callback_with_args<F, R>(&self, callback_name: &str, handler: F) -> &Self
124 where
125 F: Fn(&[Value], crate::CallbackContext) -> R + Clone + 'static,
126 R: crate::IntoValue,
127 {
128 self.shell
129 .on_with_args_internal(&self.selector, callback_name, handler);
130 self
131 }
132
133 pub fn with_component<F>(&self, mut f: F)
135 where
136 F: FnMut(&ComponentInstance),
137 {
138 self.shell.with_selected(&self.selector, |_, component| {
139 f(component);
140 });
141 }
142
143 pub fn set_property(&self, name: &str, value: &Value) -> SelectionResult<()> {
149 let mut result = SelectionResult::new();
150 self.shell
151 .with_selected_info(&self.selector, |info, component| {
152 match component.set_property(name, value.clone()) {
153 Ok(()) => result.add_success(()),
154 Err(e) => {
155 let error_msg = format!("Failed to set property '{}': {}", name, e);
156 log::error!(
157 "{} on surface {}[{:?}]",
158 error_msg,
159 info.name,
160 info.instance_id
161 );
162 result.add_failure(info.name.clone(), info.instance_id, error_msg);
163 }
164 }
165 });
166 result
167 }
168
169 pub fn get_property(&self, name: &str) -> SelectionResult<Value> {
175 let mut result = SelectionResult::new();
176 self.shell
177 .with_selected_info(&self.selector, |info, component| {
178 match component.get_property(name) {
179 Ok(value) => result.add_success(value),
180 Err(e) => {
181 let error_msg = format!("Failed to get property '{}': {}", name, e);
182 log::error!(
183 "{} on surface {}[{:?}]",
184 error_msg,
185 info.name,
186 info.instance_id
187 );
188 result.add_failure(info.name.clone(), info.instance_id, error_msg);
189 }
190 }
191 });
192 result
193 }
194
195 pub fn configure<F>(&self, mut f: F)
197 where
198 F: FnMut(&ComponentInstance, LayerSurfaceHandle<'_>),
199 {
200 self.shell
201 .configure_selected(&self.selector, |component, handle| {
202 f(component, handle);
203 });
204 }
205
206 pub fn count(&self) -> usize {
208 self.shell.count_selected(&self.selector)
209 }
210
211 pub fn is_empty(&self) -> bool {
213 self.count() == 0
214 }
215
216 pub fn info(&self) -> Vec<SurfaceInfo> {
218 self.shell.get_selected_info(&self.selector)
219 }
220}