1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
// Timer Widget // Timer-based widget that fires off a callback every time a certain time period is reached. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use piston_window::*; use std::time::{SystemTime, UNIX_EPOCH}; use crate::core::callbacks::CallbackEvent; use crate::widget::config::*; use crate::widget::widget::*; pub const CALLBACK_TIMER: u32 = 100; /// This is the `TimerWidget`. It contains no base widget, it only contains a start and end /// time, /// /// Example usage: /// IN PROGRESS pub struct TimerWidget { config: Configurable, enabled: bool, initiated: u64, triggered: bool, } /// Helper function that returns the current time in milliseconds since the `UNIX_EPOCH`. This /// function is the equivalent of a `System.currentTimeMillis()` in Java. fn time_ms() -> u64 { let since_the_epoch = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); (since_the_epoch.as_secs() * 1_000) + (since_the_epoch.subsec_nanos() / 1_000_000) as u64 } /// Implementation of the constructor for the `TimerWidget`. Timer widgets are not accessible /// on the screen, so they have an origin of 0x0 and width of 0x0. /// /// The timer provides a simple way to call a callback function after a certain amount of time /// has passed. Upon instantiation, the timer is enabled. /// /// Here are a few limitations of the timer as it currently stands: /// /// - Timer cannot be paused; it is enabled or disabled, and the timer resets when enabled. /// - Timer is called when the screen refreshes, so slower FPS settings will affect the timer. impl TimerWidget { /// Constructor, creates a new `TimerWidget` struct with an empty timeout function. pub fn new() -> Self { Self { config: Configurable::new(), enabled: true, initiated: time_ms(), triggered: false, } } // Called to check the time since initiation, and call the timeout function when a timer has // been triggered. fn tick(&mut self) { if !self.enabled { return; } let elapsed = time_ms() - self.initiated; if elapsed > self.config().get_numeric(CONFIG_TIMER_TIMEOUT) { self.initiated = time_ms(); self.triggered = true; } } } /// Implementation of the `TimerWidget` object with the `Widget` traits implemented. impl Widget for TimerWidget { fn config(&mut self) -> &mut Configurable { &mut self.config } /// Timer is always invalidated, this way, the tick function is always called on each /// screen refresh. fn is_invalidated(&mut self) -> bool { true } /// This function injects events, as a timeout event only occurs once. fn injects_events(&mut self) -> bool { true } /// Returns an injected event where appropriate. fn inject_event(&mut self, widget_id: i32) -> Option<CallbackEvent> { if self.triggered { self.triggered = false; Some(CallbackEvent::TimerTriggered { widget_id }) } else { None } } /// Does not draw anything - only calls the timer `tick()` function to increment the /// timer. fn draw(&mut self, _context: Context, _graphics: &mut G2d, _clip: &DrawState) { self.tick(); } }