native_windows_gui/controls/
timer.rs

1#![allow(deprecated)]
2
3use crate::controls::ControlHandle;
4use crate::win32::{window_helper as wh, window::build_timer};
5use crate::NwgError;
6use std::cell::RefCell;
7
8const NOT_BOUND: &'static str = "Timer is not yet bound to a winapi object";
9const UNUSABLE_TIMER: &'static str = "Timer parent window was freed";
10const BAD_HANDLE: &'static str = "INTERNAL ERROR: Timer handle is not Timer!";
11
12
13/**
14WARNING: Use AnimationTimer instead. The winapi timer does not have a constant tick and will call your single threaded from another thread.
15
16A timer is an invisible UI component that trigger the `OnTimerTick` event at the specified interval.
17Timers are mosty used to handle animations OR to create a timeout. To sync multithreaded action see the `Notice` object.
18
19A timer still requires a top level window parent. If the top level window parent is destroyed, the timer becomes invalid.
20
21Note that timer SHOULD NOT be used when a consistent interval is needed. The timer event might be triggered much faster
22than the `interval` value. For example, when a user resize a window, Timer OnTimerTick gets triggered each time the window size changes.
23This is a Windows "feature", there's probably nothing I can do to fix that.
24
25
26Requires the `timer` feature. 
27
28**Builder parameters:**
29  * `parent`:   **Required.** The timer parent container. Should be a top level window
30  * `interval`:  The timer tick interval in millisecond
31  * `stopped`:   If the timer should start right away. By default timers starts "stopped(true)". Be sure to include `stopped(false)` in your builder if you want the timer to start instantly.
32
33**Control events:**
34  * `OnTimerTick`: When the timer ticks
35
36```
37use native_windows_gui as nwg;
38
39fn build_timer(parent: &nwg::Window)  {
40    let mut timer = Default::default();
41    nwg::Timer::builder()
42        .parent(parent)
43        .interval(100)
44        .stopped(false)
45        .build(&mut timer);
46}
47```
48*/
49#[deprecated(
50    since = "1.0.11",
51    note = "Use AnimationTimer instead. The winapi timer does not have a constant tick and will call your single threaded from another thread."
52)]
53#[derive(Default)]
54pub struct Timer {
55    pub handle: ControlHandle,
56    interval: RefCell<u32>,
57}
58
59impl Timer {
60
61    pub fn builder() -> TimerBuilder {
62        TimerBuilder {
63            parent: None,
64            interval: 100,
65            stopped: true
66        }
67    }
68
69    /// Checks if the timer is still usable. A timer becomes unusable when the parent window is destroyed.
70    /// This will also return false if the timer is not initialized.
71    pub fn valid(&self) -> bool {
72        if self.handle.blank() { return false; }
73        let (hwnd, _) = self.handle.timer().expect(BAD_HANDLE);
74        wh::window_valid(hwnd)
75    }
76
77    /// Returns the interval of the timer, in milliseconds.
78    pub fn interval(&self) -> u32 {
79        *self.interval.borrow()
80    }
81
82    /// Sets the interval of the timer, in milliseconds.
83    pub fn set_interval(&self, i: u32) {
84        *self.interval.borrow_mut() = i;
85    }
86
87    /// Stops the timer.
88    pub fn stop(&self) {
89        if self.handle.blank() { panic!("{}", NOT_BOUND); }
90        if !self.valid() { panic!("{}", UNUSABLE_TIMER); }
91        let (hwnd, id) = self.handle.timer().expect(BAD_HANDLE);
92
93        wh::kill_timer(hwnd, id);
94    }
95
96    /// Starts the timer. If the timer is already running, this restarts it.
97    pub fn start(&self) {
98        if self.handle.blank() { panic!("{}", NOT_BOUND); }
99        if !self.valid() { panic!("{}", UNUSABLE_TIMER); }
100        let (hwnd, id) = self.handle.timer().expect(BAD_HANDLE);
101
102        wh::start_timer(hwnd, id, self.interval());
103    }
104
105}
106
107impl Drop for Timer {
108    fn drop(&mut self) {
109        self.handle.destroy();
110    }
111}
112
113pub struct TimerBuilder {
114    parent: Option<ControlHandle>,
115    interval: u32,
116    stopped: bool
117}
118
119impl TimerBuilder {
120    
121    pub fn interval(mut self, interval: u32) -> TimerBuilder {
122        self.interval = interval;
123        self
124    }
125
126    pub fn stopped(mut self, stop: bool) -> TimerBuilder {
127        self.stopped = stop;
128        self
129    }
130
131    pub fn parent<C: Into<ControlHandle>>(mut self, p: C) -> TimerBuilder {
132        self.parent = Some(p.into());
133        self
134    }
135
136    pub fn build(self, out: &mut Timer) -> Result<(), NwgError> {
137        let parent = match self.parent {
138            Some(p) => match p.hwnd() {
139                Some(handle) => Ok(handle),
140                None => Err(NwgError::control_create("Wrong parent type"))
141            },
142            None => Err(NwgError::no_parent("Timer"))
143        }?;
144
145        *out = Default::default();
146
147        out.handle = unsafe { build_timer(parent, self.interval, self.stopped) };
148        out.set_interval(self.interval);
149        
150        Ok(())
151    }
152
153}
154
155impl PartialEq for Timer {
156    fn eq(&self, other: &Self) -> bool {
157        self.handle == other.handle
158    }
159}