use crate::ffi;
use crate::signal::{self, SignalHandle};
pub struct Timer {
ptr: *mut ffi::QTimer,
signal_handles: Vec<SignalHandle>,
}
impl Timer {
pub fn new(interval_ms: i32) -> Builder {
Builder::new(interval_ms)
}
pub fn single_shot<F: Fn() + 'static>(interval_ms: i32, f: F) -> Timer {
let timer = Timer::new(interval_ms).on_timeout(f).build();
timer
}
pub fn start(&self, interval_ms: i32) {
debug_assert!(!self.ptr.is_null());
unsafe { ffi::QTimer_start(self.ptr, interval_ms); }
}
pub fn stop(&self) {
debug_assert!(!self.ptr.is_null());
unsafe { ffi::QTimer_stop(self.ptr); }
}
pub fn is_active(&self) -> bool {
debug_assert!(!self.ptr.is_null());
unsafe { ffi::QTimer_isActive(self.ptr) }
}
}
impl Drop for Timer {
fn drop(&mut self) {
if self.ptr.is_null() { return; }
unsafe { ffi::QTimer_stop(self.ptr); }
for h in self.signal_handles.drain(..) {
unsafe { h.reclaim(); }
}
unsafe { ffi::QTimer_delete(self.ptr) };
self.ptr = std::ptr::null_mut();
}
}
pub struct Builder {
interval_ms: i32,
on_timeout: Option<Box<dyn Fn()>>,
}
impl Builder {
fn new(interval_ms: i32) -> Self {
Self { interval_ms, on_timeout: None }
}
pub fn on_timeout<F: Fn() + 'static>(mut self, f: F) -> Self {
self.on_timeout = Some(Box::new(f));
self
}
pub fn build(self) -> Timer {
let ptr = unsafe { ffi::QTimer_new() };
debug_assert!(!ptr.is_null());
let mut timer = Timer { ptr, signal_handles: Vec::new() };
if let Some(f) = self.on_timeout {
let h = signal::leak_void(f);
unsafe { ffi::QTimer_onTimeout(ptr, h.token); }
timer.signal_handles.push(h);
}
unsafe { ffi::QTimer_start(ptr, self.interval_ms); }
timer
}
}