Skip to content

Commit 10a4564

Browse files
committed
Rust interpreter: cache properties and callbacks
1 parent 30f6e01 commit 10a4564

File tree

2 files changed

+146
-51
lines changed

2 files changed

+146
-51
lines changed

internal/compiler/generator/rust_interpreted.rs

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,19 @@ fn generate_public_component(
9494
property_and_callback_accessors.push(quote!(
9595
#[allow(dead_code)]
9696
pub fn #caller_ident(&self, #(#args_name : #callback_args,)*) -> #return_type {
97-
self.0.borrow().instance().invoke(#prop_name, &[#(#args_name.into(),)*])
98-
.unwrap_or_else(|e| panic!("Cannot invoke callback {}::{}: {e}", #component_name, #prop_name))
99-
.try_into().expect("Invalid return type")
97+
self.0.borrow().invoke(#prop_name, &[#(#args_name.into(),)*])
98+
.try_into().unwrap_or_else(|_| panic!("Invalid return type for callback {}::{}", #component_name, #prop_name))
10099
}
101100
));
102101
let on_ident = format_ident!("on_{}", prop_ident);
103102
property_and_callback_accessors.push(quote!(
104103
#[allow(dead_code)]
105104
pub fn #on_ident(&self, f: impl FnMut(#(#callback_args),*) -> #return_type + 'static) {
106105
let f = ::core::cell::RefCell::new(f);
107-
self.0.borrow().instance().set_callback(#prop_name, move |values| {
106+
self.0.borrow_mut().set_callback(#prop_name, sp::Rc::new(move |values| {
108107
let [#(#args_name,)*] = values else { panic!("invalid number of argument for callback {}::{}", #component_name, #prop_name) };
109108
(*f.borrow_mut())(#(#args_name.clone().try_into().unwrap_or_else(|_| panic!("invalid argument for callback {}::{}", #component_name, #prop_name)),)*).into()
110-
}).unwrap_or_else(|e| panic!("Cannot set callback {}::{}: {e}", #component_name, #prop_name))
109+
}))
111110
}
112111
));
113112
} else if let Type::Function(function) = &p.ty {
@@ -120,9 +119,8 @@ fn generate_public_component(
120119
property_and_callback_accessors.push(quote!(
121120
#[allow(dead_code)]
122121
pub fn #caller_ident(&self, #(#args_name : #callback_args,)*) -> #return_type {
123-
self.0.borrow().instance().invoke(#prop_name, &[#(#args_name.into(),)*])
124-
.unwrap_or_else(|e| panic!("Cannot invoke callback {}::{}: {e}", #component_name, #prop_name))
125-
.try_into().expect("Invalid return type")
122+
self.0.borrow().invoke(#prop_name, &[#(#args_name.into(),)*])
123+
.try_into().unwrap_or_else(|_| panic!("Invalid return type for function {}::{}", #component_name, #prop_name))
126124
}
127125
));
128126
} else {
@@ -134,11 +132,8 @@ fn generate_public_component(
134132
property_and_callback_accessors.push(quote!(
135133
#[allow(dead_code)]
136134
pub fn #getter_ident(&self) -> #rust_property_type {
137-
#[allow(unused_imports)]
138-
#convert_from_value(
139-
self.0.instance()get_property(#prop_name)
140-
.unwrap_or_else(|e| panic!("Cannot get property {}::{} - {e}", #component_name, #prop_name))
141-
).expect("Invalid property type")
135+
#convert_from_value(self.0.borrow().get_property(#prop_name))
136+
.unwrap_or_else(|_| panic!("Invalid property type for {}::{}", #component_name, #prop_name))
142137
}
143138
));
144139

@@ -147,8 +142,7 @@ fn generate_public_component(
147142
property_and_callback_accessors.push(quote!(
148143
#[allow(dead_code)]
149144
pub fn #setter_ident(&self, value: #rust_property_type) {
150-
self.0.set_property(#prop_name, #convert_to_value(value))
151-
.unwrap_or_else(|e| panic!("Cannot set property {}::{} - {e}", #component_name, #prop_name));
145+
self.0.borrow_mut().set_property(#prop_name, #convert_to_value(value))
152146
}
153147
));
154148
} else {
@@ -253,20 +247,19 @@ fn generate_global(global: &llr::GlobalComponent, root: &llr::CompilationUnit) -
253247
property_and_callback_accessors.push(quote!(
254248
#[allow(dead_code)]
255249
pub fn #caller_ident(&self, #(#args_name : #callback_args,)*) -> #return_type {
256-
self.0.borrow().instance().invoke_global(#global_name, #prop_name, &[#(#args_name.into(),)*])
257-
.unwrap_or_else(|e| panic!("Cannot invoke callback {}::{}: {e}", #global_name, #prop_name))
258-
.try_into().expect("Invalid return type")
250+
self.0.borrow().invoke_global(#global_name, #prop_name, &[#(#args_name.into(),)*])
251+
.try_into().unwrap_or_else(|_| panic!("Invalid return type for callback {}::{}", #global_name, #prop_name))
259252
}
260253
));
261254
let on_ident = format_ident!("on_{}", prop_ident);
262255
property_and_callback_accessors.push(quote!(
263256
#[allow(dead_code)]
264257
pub fn #on_ident(&self, f: impl FnMut(#(#callback_args),*) -> #return_type + 'static) {
265258
let f = ::core::cell::RefCell::new(f);
266-
self.0.borrow().instance().set_global_callback(#global_name, #prop_name, move |values| {
259+
self.0.borrow_mut().set_global_callback(#global_name, #prop_name, sp::Rc::new(move |values| {
267260
let [#(#args_name,)*] = values else { panic!("invalid number of argument for callback {}::{}", #global_name, #prop_name) };
268261
(*f.borrow_mut())(#(#args_name.clone().try_into().unwrap_or_else(|_| panic!("invalid argument for callback {}::{}", #global_name, #prop_name)),)*).into()
269-
}).unwrap_or_else(|e| panic!("Cannot set callback {}::{}: {e}", #global_name, #prop_name))
262+
}))
270263
}
271264
));
272265
} else if let Type::Function(function) = &p.ty {
@@ -279,9 +272,8 @@ fn generate_global(global: &llr::GlobalComponent, root: &llr::CompilationUnit) -
279272
property_and_callback_accessors.push(quote!(
280273
#[allow(dead_code)]
281274
pub fn #caller_ident(&self, #(#args_name : #callback_args,)*) -> #return_type {
282-
self.0.borrow().instance().invoke_global(#global_name, #prop_name, &[#(#args_name.into(),)*])
283-
.unwrap_or_else(|e| panic!("Cannot invoke callback {}::{}: {e}", #global_name, #prop_name))
284-
.try_into().expect("Invalid return type")
275+
self.0.borrow().invoke_global(#global_name, #prop_name, &[#(#args_name.into(),)*])
276+
.try_into().unwrap_or_else(|_| panic!("Invalid return type for function {}::{}", #global_name, #prop_name))
285277
}
286278
));
287279
} else {
@@ -293,10 +285,8 @@ fn generate_global(global: &llr::GlobalComponent, root: &llr::CompilationUnit) -
293285
property_and_callback_accessors.push(quote!(
294286
#[allow(dead_code)]
295287
pub fn #getter_ident(&self) -> #rust_property_type {
296-
#convert_from_value(
297-
self.0.borrow().instance().get_global_property(#global_name, #prop_name)
298-
.unwrap_or_else(|e| panic!("Cannot get property {}::{} - {e}", #global_name, #prop_name))
299-
).expect("Invalid property type")
288+
#convert_from_value(self.0.borrow().get_global_property(#global_name, #prop_name))
289+
.unwrap_or_else(|_| panic!("Invalid property type for {}::{}", #global_name, #prop_name))
300290
}
301291
));
302292

@@ -305,8 +295,7 @@ fn generate_global(global: &llr::GlobalComponent, root: &llr::CompilationUnit) -
305295
property_and_callback_accessors.push(quote!(
306296
#[allow(dead_code)]
307297
pub fn #setter_ident(&self, value: #rust_property_type) {
308-
self.0.borrow().instance().set_global_property(#global_name, #prop_name, #convert_to_value(value))
309-
.unwrap_or_else(|e| panic!("Cannot set property {}::{} - {e}", #global_name, #prop_name));
298+
self.0.borrow_mut().set_global_property(#global_name, #prop_name, #convert_to_value(value))
310299
}
311300
));
312301
} else {

internal/interpreter/live_reload.rs

Lines changed: 128 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::dynamic_item_tree::WindowOptions;
77
use core::cell::RefCell;
88
use core::task::Waker;
99
use i_slint_core::api::{ComponentHandle, PlatformError};
10+
use std::collections::HashMap;
1011
use std::path::{Path, PathBuf};
1112
use std::rc::Rc;
1213
use std::sync::{Arc, Mutex};
@@ -22,6 +23,8 @@ pub struct LiveReloadingComponent {
2223
compiler: Compiler,
2324
file_name: PathBuf,
2425
component_name: String,
26+
properties: HashMap<String, Value>,
27+
callbacks: HashMap<String, Rc<dyn Fn(&[Value]) -> Value + 'static>>,
2528
}
2629

2730
impl LiveReloadingComponent {
@@ -33,13 +36,22 @@ impl LiveReloadingComponent {
3336
) -> Result<Rc<RefCell<Self>>, PlatformError> {
3437
let self_rc = Rc::<RefCell<Self>>::new_cyclic(move |self_weak| {
3538
let watcher = Watcher::new(self_weak.clone());
36-
let watcher_clone = watcher.clone();
37-
compiler.set_file_loader(move |path| {
38-
watcher_clone.lock().unwrap().watch(path);
39-
Box::pin(async { None })
40-
});
41-
watcher.lock().unwrap().watch(&file_name);
42-
RefCell::new(Self { instance: None, compiler, file_name, component_name })
39+
if watcher.lock().unwrap().watcher.is_some() {
40+
let watcher_clone = watcher.clone();
41+
compiler.set_file_loader(move |path| {
42+
watcher_clone.lock().unwrap().watch(path);
43+
Box::pin(async { None })
44+
});
45+
watcher.lock().unwrap().watch(&file_name);
46+
}
47+
RefCell::new(Self {
48+
instance: None,
49+
compiler,
50+
file_name,
51+
component_name,
52+
properties: Default::default(),
53+
callbacks: Default::default(),
54+
})
4355
});
4456

4557
let mut self_mut = self_rc.borrow_mut();
@@ -85,31 +97,125 @@ impl LiveReloadingComponent {
8597
};
8698
#[cfg(feature = "display-diagnostics")]
8799
result.print_diagnostics();
88-
if !result.has_errors() {
89-
if let Some(definition) = result.component(&self.component_name) {
90-
let window_adapter =
91-
i_slint_core::window::WindowInner::from_pub(self.instance().window())
92-
.window_adapter();
93-
match definition
94-
.create_with_options(WindowOptions::UseExistingWindow(window_adapter))
95-
{
96-
Ok(instance) => {
97-
self.instance = Some(instance);
98-
return true;
99-
}
100-
Err(e) => eprintln!("Error while creating the component: {e}"),
100+
if result.has_errors() {
101+
return false;
102+
}
103+
104+
if let Some(definition) = result.component(&self.component_name) {
105+
let window_adapter =
106+
i_slint_core::window::WindowInner::from_pub(self.instance().window())
107+
.window_adapter();
108+
match definition.create_with_options(WindowOptions::UseExistingWindow(window_adapter)) {
109+
Ok(instance) => {
110+
self.instance = Some(instance);
111+
}
112+
Err(e) => {
113+
eprintln!("Error while creating the component: {e}");
114+
return false;
101115
}
116+
}
117+
} else {
118+
eprintln!("Component {} not found", self.component_name);
119+
return false;
120+
}
121+
122+
// Set the properties
123+
for (name, value) in self.properties.iter() {
124+
if let Some((global, prop)) = name.split_once('.') {
125+
self.instance()
126+
.set_global_property(global, prop, value.clone())
127+
.unwrap_or_else(|e| panic!("Cannot set property {name}: {e}"));
128+
} else {
129+
self.instance()
130+
.set_property(name, value.clone())
131+
.unwrap_or_else(|e| panic!("Cannot set property {name}: {e}"));
132+
}
133+
}
134+
for (name, callback) in self.callbacks.iter() {
135+
let callback = callback.clone();
136+
if let Some((global, prop)) = name.split_once('.') {
137+
self.instance()
138+
.set_global_callback(global, prop, move |args| callback(args))
139+
.unwrap_or_else(|e| panic!("Cannot set callback {name}: {e}"));
102140
} else {
103-
eprintln!("Component {} not found", self.component_name);
141+
self.instance()
142+
.set_callback(name, move |args| callback(args))
143+
.unwrap_or_else(|e| panic!("Cannot set callback {name}: {e}"));
104144
}
105145
}
106-
false
146+
147+
true
107148
}
108149

109150
/// Return the instance
110151
pub fn instance(&self) -> &ComponentInstance {
111152
&self.instance.as_ref().expect("always set after Self is created from Rc::new_cyclic")
112153
}
154+
155+
/// Set a property and remember its value for when the component is reloaded
156+
pub fn set_property(&mut self, name: &str, value: Value) {
157+
self.properties.insert(name.into(), value.clone());
158+
self.instance()
159+
.set_property(&name, value)
160+
.unwrap_or_else(|e| panic!("Cannot set property {name}: {e}"))
161+
}
162+
163+
/// Forward to get_property
164+
pub fn get_property(&self, name: &str) -> Value {
165+
self.instance()
166+
.get_property(&name)
167+
.unwrap_or_else(|e| panic!("Cannot get property {name}: {e}"))
168+
}
169+
170+
/// Forward to invoke
171+
pub fn invoke(&self, name: &str, args: &[Value]) -> Value {
172+
self.instance()
173+
.invoke(name, args)
174+
.unwrap_or_else(|e| panic!("Cannot invoke callback {name}: {e}"))
175+
}
176+
177+
/// Forward to set_callback
178+
pub fn set_callback(&mut self, name: &str, callback: Rc<dyn Fn(&[Value]) -> Value + 'static>) {
179+
self.callbacks.insert(name.into(), callback.clone());
180+
self.instance()
181+
.set_callback(&name, move |args| callback(args))
182+
.unwrap_or_else(|e| panic!("Cannot set callback {name}: {e}"));
183+
}
184+
185+
/// forward to set_global_property
186+
pub fn set_global_property(&mut self, global_name: &str, name: &str, value: Value) {
187+
self.properties.insert(format!("{global_name}.{name}"), value.clone());
188+
self.instance()
189+
.set_global_property(global_name, name, value)
190+
.unwrap_or_else(|e| panic!("Cannot set property {global_name}::{name}: {e}"))
191+
}
192+
193+
/// forward to get_global_property
194+
pub fn get_global_property(&self, global_name: &str, name: &str) -> Value {
195+
self.instance()
196+
.get_global_property(global_name, name)
197+
.unwrap_or_else(|e| panic!("Cannot get property {global_name}::{name}: {e}"))
198+
}
199+
200+
/// Forward to invoke_global
201+
pub fn invoke_global(&self, global_name: &str, name: &str, args: &[Value]) -> Value {
202+
self.instance()
203+
.invoke_global(global_name, name, args)
204+
.unwrap_or_else(|e| panic!("Cannot invoke callback {global_name}::{name}: {e}"))
205+
}
206+
207+
/// Forward to set_global_callback
208+
pub fn set_global_callback(
209+
&mut self,
210+
global_name: &str,
211+
name: &str,
212+
callback: Rc<dyn Fn(&[Value]) -> Value + 'static>,
213+
) {
214+
self.callbacks.insert(format!("{global_name}.{name}"), callback.clone());
215+
self.instance()
216+
.set_global_callback(global_name, name, move |args| callback(args))
217+
.unwrap_or_else(|e| panic!("Cannot set callback {global_name}::{name}: {e}"));
218+
}
113219
}
114220

115221
enum WatcherState {

0 commit comments

Comments
 (0)