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 115 116 117 118 119 120 121 122 123 124 125 126 127
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::collections::VecDeque; use super::{ WatchedMeta, WatcherInit, Watcher, WatcherMeta, }; struct AlternatingData<T> { queue: VecDeque<T>, current_data: Option<T>, current_trigger: WatchedMeta, off_frame: WatchedMeta, } impl<T: 'static> WatcherInit for AlternatingData<T> { fn init(watcher: &mut WatcherMeta<Self>) { watcher.watch(|data| { data.off_frame.watched(); data.current_data = data.queue.pop_front(); data.current_trigger.trigger(); }); watcher.watch(|data| { data.current_trigger.watched(); if data.current_data.is_some() { data.off_frame.trigger(); } }); } } impl<T> Default for AlternatingData<T> { fn default() -> Self { AlternatingData { queue: VecDeque::new(), current_data: None, current_trigger: WatchedMeta::new(), off_frame: WatchedMeta::new(), } } } /// A WatchedEvent uses the watch system provided by this crate to implement /// an event disptacher. This is different from a watched value /// ([Watched](struct.Watched.html)) in that events will fire for each value /// passed to WatchedEvent::dispatch() and will not "store" the data. /// /// ```rust /// use drying_paint::*; /// /// type EventCounter = Watcher<EventCounterData>; /// /// #[derive(Default)] /// struct EventCounterData { /// counter: u32, /// add: WatchedEvent<u32>, /// } /// /// impl WatcherInit for EventCounterData { /// fn init(watcher: &mut WatcherMeta<Self>) { /// watcher.watch(|root| { /// if let Some(amount) = root.add.bind() { /// root.counter += amount; /// } /// }); /// } /// } /// /// fn main() { /// let mut ctx = WatchContext::new(); /// ctx.with(|| { /// let item = WatchContext::allow_watcher_access((), |()| { /// let mut item = EventCounter::new(); /// item.data_mut().add.dispatch(7); /// item /// }); /// WatchContext::update_current(); /// let item = WatchContext::allow_watcher_access(item, |mut item| { /// assert_eq!(item.data().counter, 7); /// item.data_mut().add.dispatch(9); /// item.data_mut().add.dispatch(3); /// item /// }); /// WatchContext::update_current(); /// WatchContext::allow_watcher_access(item, |mut item| { /// assert_eq!(item.data().counter, 19); /// }); /// }); /// } /// ``` pub struct WatchedEvent<T> { watcher: Watcher<AlternatingData<T>>, } impl<T: 'static> WatchedEvent<T> { /// Create a new WatchedEvent pub fn new() -> Self { Default::default() } /// Used inside a [watch](struct.WatcherMeta.html#method.watch) closure /// this will return a value each time the event is dispatched pub fn bind(&self) -> Option<&T> { let borrow = self.watcher.data(); borrow.current_trigger.watched(); borrow.current_data.as_ref() } /// Trigger the event. The argument passed will be delivered to listeners. pub fn dispatch(&mut self, arg: T) { let data = self.watcher.data_mut(); data.queue.push_back(arg); data.off_frame.trigger(); } } impl<T: 'static> Default for WatchedEvent<T> { fn default() -> Self { WatchedEvent { watcher: Watcher::new(), } } }