mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +00:00
Fix the Rust/C++ Timer API to be more convenient to use
Allow calling restart() on a repeated timer if it has been previously stopped.
This commit is contained in:
parent
ced05732a8
commit
083ae5692b
4 changed files with 83 additions and 16 deletions
|
@ -9,6 +9,8 @@ All notable changes to this project will be documented in this file.
|
||||||
has changed. This was undocumented, but if one was handling this in the
|
has changed. This was undocumented, but if one was handling this in the
|
||||||
`FocusScope` event, these keys will now be ignored. Use the `Keys.LeftArrow`
|
`FocusScope` event, these keys will now be ignored. Use the `Keys.LeftArrow`
|
||||||
and other code exposed in the `Keys` namespace instead
|
and other code exposed in the `Keys` namespace instead
|
||||||
|
- For `sixtyfps::Timer` (C++ and Rust), it's now possible to call `restart()` after
|
||||||
|
a timer has been stopped previously by calling `stop()`.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|
|
@ -374,7 +374,7 @@ struct Timer
|
||||||
}
|
}
|
||||||
Timer(const Timer &) = delete;
|
Timer(const Timer &) = delete;
|
||||||
Timer &operator=(const Timer &) = delete;
|
Timer &operator=(const Timer &) = delete;
|
||||||
~Timer() { cbindgen_private::sixtyfps_timer_stop(id); }
|
~Timer() { cbindgen_private::sixtyfps_timer_destroy(id); }
|
||||||
|
|
||||||
/// Starts the timer with the given \a mode and \a interval, in order for the \a callback to
|
/// Starts the timer with the given \a mode and \a interval, in order for the \a callback to
|
||||||
/// called when the timer fires. If the timer has been started previously and not fired yet,
|
/// called when the timer fires. If the timer has been started previously and not fired yet,
|
||||||
|
@ -388,12 +388,12 @@ struct Timer
|
||||||
}
|
}
|
||||||
/// Stops the previously started timer. Does nothing if the timer has never been started. A
|
/// Stops the previously started timer. Does nothing if the timer has never been started. A
|
||||||
/// stopped timer cannot be restarted with restart() -- instead you need to call start().
|
/// stopped timer cannot be restarted with restart() -- instead you need to call start().
|
||||||
void stop()
|
void stop() { cbindgen_private::sixtyfps_timer_stop(id); }
|
||||||
{
|
/// Restarts the timer. If the timer was previously started by calling [`Self::start()`]
|
||||||
cbindgen_private::sixtyfps_timer_stop(id);
|
/// with a duration and callback, then the time when the callback will be next invoked
|
||||||
id = -1;
|
/// is re-calculated to be in the specified duration relative to when this function is called.
|
||||||
}
|
///
|
||||||
/// Restarts the timer, if it was previously started.
|
/// Does nothing if the timer was never started.
|
||||||
void restart() { cbindgen_private::sixtyfps_timer_restart(id); }
|
void restart() { cbindgen_private::sixtyfps_timer_restart(id); }
|
||||||
/// Returns true if the timer is running; false otherwise.
|
/// Returns true if the timer is running; false otherwise.
|
||||||
bool running() const { return cbindgen_private::sixtyfps_timer_running(id); }
|
bool running() const { return cbindgen_private::sixtyfps_timer_running(id); }
|
||||||
|
|
|
@ -77,6 +77,57 @@ TEST_CASE("C++ Restart Singleshot Timer")
|
||||||
REQUIRE(timer_was_running);
|
REQUIRE(timer_was_running);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("C++ Restart Repeated Timer")
|
||||||
|
{
|
||||||
|
int timer_triggered = 0;
|
||||||
|
sixtyfps::Timer timer;
|
||||||
|
|
||||||
|
timer.start(sixtyfps::TimerMode::Repeated, std::chrono::milliseconds(30),
|
||||||
|
[&]() { timer_triggered++; });
|
||||||
|
|
||||||
|
REQUIRE(timer_triggered == 0);
|
||||||
|
|
||||||
|
bool timer_was_running = false;
|
||||||
|
|
||||||
|
sixtyfps::Timer::single_shot(std::chrono::milliseconds(500), [&]() {
|
||||||
|
timer_was_running = timer.running();
|
||||||
|
sixtyfps::quit_event_loop();
|
||||||
|
});
|
||||||
|
|
||||||
|
sixtyfps::run_event_loop();
|
||||||
|
|
||||||
|
REQUIRE(timer_triggered > 1);
|
||||||
|
REQUIRE(timer_was_running);
|
||||||
|
|
||||||
|
timer_was_running = false;
|
||||||
|
timer_triggered = 0;
|
||||||
|
timer.stop();
|
||||||
|
sixtyfps::Timer::single_shot(std::chrono::milliseconds(500), [&]() {
|
||||||
|
timer_was_running = timer.running();
|
||||||
|
sixtyfps::quit_event_loop();
|
||||||
|
});
|
||||||
|
|
||||||
|
sixtyfps::run_event_loop();
|
||||||
|
|
||||||
|
REQUIRE(timer_triggered == 0);
|
||||||
|
REQUIRE(!timer_was_running);
|
||||||
|
|
||||||
|
timer_was_running = false;
|
||||||
|
timer_triggered = 0;
|
||||||
|
|
||||||
|
timer.restart();
|
||||||
|
|
||||||
|
sixtyfps::Timer::single_shot(std::chrono::milliseconds(500), [&]() {
|
||||||
|
timer_was_running = timer.running();
|
||||||
|
sixtyfps::quit_event_loop();
|
||||||
|
});
|
||||||
|
|
||||||
|
sixtyfps::run_event_loop();
|
||||||
|
|
||||||
|
REQUIRE(timer_triggered > 1);
|
||||||
|
REQUIRE(timer_was_running);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Quit from event")
|
TEST_CASE("Quit from event")
|
||||||
{
|
{
|
||||||
int called = 0;
|
int called = 0;
|
||||||
|
|
|
@ -110,17 +110,20 @@ impl Timer {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stops the previously started timer. Does nothing if the timer has never been started. A stopped
|
/// Stops the previously started timer. Does nothing if the timer has never been started.
|
||||||
/// timer cannot be restarted with restart() -- instead you need to call start().
|
|
||||||
pub fn stop(&self) {
|
pub fn stop(&self) {
|
||||||
if let Some(id) = self.id.take() {
|
if let Some(id) = self.id.get() {
|
||||||
CURRENT_TIMERS.with(|timers| {
|
CURRENT_TIMERS.with(|timers| {
|
||||||
timers.borrow_mut().remove_timer(id);
|
timers.borrow_mut().deactivate_timer(id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Restarts the timer, if it was previously started.
|
/// Restarts the timer. If the timer was previously started by calling [`Self::start()`]
|
||||||
|
/// with a duration and callback, then the time when the callback will be next invoked
|
||||||
|
/// is re-calculated to be in the specified duration relative to when this function is called.
|
||||||
|
///
|
||||||
|
/// Does nothing if the timer was never started.
|
||||||
pub fn restart(&self) {
|
pub fn restart(&self) {
|
||||||
if let Some(id) = self.id.get() {
|
if let Some(id) = self.id.get() {
|
||||||
CURRENT_TIMERS.with(|timers| {
|
CURRENT_TIMERS.with(|timers| {
|
||||||
|
@ -359,7 +362,7 @@ pub(crate) mod ffi {
|
||||||
/// Start a timer with the given mode, duration in millisecond and callback. A timer id may be provided (first argument).
|
/// Start a timer with the given mode, duration in millisecond and callback. A timer id may be provided (first argument).
|
||||||
/// A value of -1 for the timer id means a new timer is to be allocated.
|
/// A value of -1 for the timer id means a new timer is to be allocated.
|
||||||
/// The (new) timer id is returned.
|
/// The (new) timer id is returned.
|
||||||
/// The timer MUST be destroyed with sixtyfps_timer_stop.
|
/// The timer MUST be destroyed with sixtyfps_timer_destroy.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn sixtyfps_timer_start(
|
pub extern "C" fn sixtyfps_timer_start(
|
||||||
id: i64,
|
id: i64,
|
||||||
|
@ -396,12 +399,23 @@ pub(crate) mod ffi {
|
||||||
|
|
||||||
/// Stop a timer and free its raw data
|
/// Stop a timer and free its raw data
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
pub extern "C" fn sixtyfps_timer_destroy(id: i64) {
|
||||||
|
if id == -1 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let timer = Timer { id: Cell::new(Some(id as _)) };
|
||||||
|
drop(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stop a timer
|
||||||
|
#[no_mangle]
|
||||||
pub extern "C" fn sixtyfps_timer_stop(id: i64) {
|
pub extern "C" fn sixtyfps_timer_stop(id: i64) {
|
||||||
if id == -1 {
|
if id == -1 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let timer = Timer { id: Cell::new(Some(id as _)) };
|
let timer = Timer { id: Cell::new(Some(id as _)) };
|
||||||
timer.stop()
|
timer.stop();
|
||||||
|
timer.id.take(); // Make sure that dropping the Timer doesn't unregister it. C++ will call destroy() in the destructor.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Restart a repeated timer
|
/// Restart a repeated timer
|
||||||
|
@ -412,7 +426,7 @@ pub(crate) mod ffi {
|
||||||
}
|
}
|
||||||
let timer = Timer { id: Cell::new(Some(id as _)) };
|
let timer = Timer { id: Cell::new(Some(id as _)) };
|
||||||
timer.restart();
|
timer.restart();
|
||||||
timer.id.take(); // Make sure that dropping the Timer doesn't unregister it. C++ will call stop() in the destructor.
|
timer.id.take(); // Make sure that dropping the Timer doesn't unregister it. C++ will call destroy() in the destructor.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the timer is running; false otherwise.
|
/// Returns true if the timer is running; false otherwise.
|
||||||
|
@ -423,7 +437,7 @@ pub(crate) mod ffi {
|
||||||
}
|
}
|
||||||
let timer = Timer { id: Cell::new(Some(id as _)) };
|
let timer = Timer { id: Cell::new(Some(id as _)) };
|
||||||
let running = timer.running();
|
let running = timer.running();
|
||||||
timer.id.take(); // Make sure that dropping the Timer doesn't unregister it. C++ will call stop() in the destructor.
|
timer.id.take(); // Make sure that dropping the Timer doesn't unregister it. C++ will call destroy() in the destructor.
|
||||||
running
|
running
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue