Timer Element

Closes #5724
This commit is contained in:
Olivier Goffart 2024-08-15 13:02:05 +02:00
parent 2643a327e8
commit a9f526491a
25 changed files with 599 additions and 14 deletions

View file

@ -1918,6 +1918,38 @@ fn generate_sub_component(
format!("self->change_tracker{idx}.init(self, [](auto self) {{ return {prop}; }}, []([[maybe_unused]] auto self, auto) {{ {code}; }});")
}));
if !component.timers.is_empty() {
let mut update_timers = vec!["auto self = this;".into()];
for (i, tmr) in component.timers.iter().enumerate() {
user_init.push(format!("self->update_timers();"));
let name = format!("timer{}", i);
let running = compile_expression(&tmr.running.borrow(), &ctx);
let interval = compile_expression(&tmr.interval.borrow(), &ctx);
let callback = compile_expression(&tmr.triggered.borrow(), &ctx);
update_timers.push(format!("if ({running}) {{"));
update_timers
.push(format!(" auto interval = std::chrono::milliseconds({interval});"));
update_timers.push(format!(
" if (!self->{name}.running() || *self->{name}.interval() != interval)"
));
update_timers.push(format!(" self->{name}.start(slint::TimerMode::Repeated, interval, [self] {{ {callback}; }});"));
update_timers.push(format!("}} else {{ self->{name}.stop(); }}").into());
target_struct.members.push((
field_access,
Declaration::Var(Var { ty: "slint::Timer".into(), name, ..Default::default() }),
));
}
target_struct.members.push((
field_access,
Declaration::Function(Function {
name: "update_timers".to_owned(),
signature: "() -> void".into(),
statements: Some(update_timers),
..Default::default()
}),
));
}
target_struct
.members
.extend(generate_functions(&component.functions, &ctx).map(|x| (Access::Public, x)));
@ -3445,6 +3477,9 @@ fn compile_builtin_function_call(
BuiltinFunction::Translate => {
format!("slint::private_api::translate({})", a.join(","))
}
BuiltinFunction::UpdateTimers => {
"self->update_timers()".into()
}
}
}

View file

@ -1064,6 +1064,41 @@ fn generate_sub_component(
quote!(usize::MAX)
};
let timer_names =
component.timers.iter().enumerate().map(|(idx, _)| format_ident!("timer{idx}"));
let update_timers = (!component.timers.is_empty()).then(|| {
let updt = component.timers.iter().enumerate().map(|(idx, tmr)| {
let ident = format_ident!("timer{idx}");
let interval = compile_expression(&tmr.interval.borrow(), &ctx);
let running = compile_expression(&tmr.running.borrow(), &ctx);
let callback = compile_expression(&tmr.triggered.borrow(), &ctx);
quote!(
if #running {
let interval = core::time::Duration::from_millis(#interval as u64);
let old_interval = self.#ident.interval();
if old_interval != Some(interval) || !self.#ident.running() {
let self_weak = self.self_weak.get().unwrap().clone();
self.#ident.start(sp::TimerMode::Repeated, interval, move || {
if let Some(self_rc) = self_weak.upgrade() {
let _self = self_rc.as_pin_ref();
#callback
}
});
}
} else {
self.#ident.stop();
}
)
});
user_init_code.push(quote!(_self.update_timers();));
quote!(
fn update_timers(self: ::core::pin::Pin<&Self>) {
let _self = self;
#(#updt)*
}
)
});
let pin_macro = if pinned_drop { quote!(#[pin_drop]) } else { quote!(#[pin]) };
quote!(
@ -1079,6 +1114,7 @@ fn generate_sub_component(
#(#declared_callbacks : sp::Callback<(#(#declared_callbacks_types,)*), #declared_callbacks_ret>,)*
#(#repeated_element_names : sp::Repeater<#repeated_element_components>,)*
#(#change_tracker_names : sp::ChangeTracker,)*
#(#timer_names : sp::Timer,)*
self_weak : sp::OnceCell<sp::VWeakMapped<sp::ItemTreeVTable, #inner_component_id>>,
#(parent : #parent_component_type,)*
globals: sp::OnceCell<sp::Rc<SharedGlobals>>,
@ -1214,6 +1250,8 @@ fn generate_sub_component(
}
}
#update_timers
#(#declared_functions)*
}
@ -2816,6 +2854,9 @@ fn compile_builtin_function_call(
panic!("internal error: invalid args to MapPointToWindow {:?}", arguments)
}
}
BuiltinFunction::UpdateTimers => {
quote!(_self.update_timers())
}
}
}