1use crate::base::BaseListener;
2use fltk::enums::Event;
3use fltk::prelude::{WidgetBase, WidgetExt};
4use std::cell::{Cell, RefCell};
5use std::collections::HashMap;
6use std::rc::Rc;
7
8type EventMap<T> = HashMap<i32, Option<Box<dyn FnMut(&mut T)>>>;
9
10#[derive(Clone)]
11pub struct Trig<T> {
12 triggered: Rc<Cell<bool>>,
13 event: Rc<Cell<Event>>,
14 events: Rc<RefCell<EventMap<T>>>,
15}
16
17pub type Listener<T> = BaseListener<T, Trig<T>>;
20
21impl<T: WidgetBase + WidgetExt + 'static> From<T> for Listener<T> {
23 fn from(mut wid: T) -> Self {
24 let triggered = Rc::new(Cell::new(false));
25 wid.set_callback({
26 let triggered = triggered.clone();
27 move |_| {
28 triggered.set(true);
29 }
30 });
31 let event = Rc::new(Cell::new(Event::NoEvent));
32 let events: EventMap<T> = HashMap::new();
33 let events = Rc::from(RefCell::from(events));
34 wid.handle({
35 let event = event.clone();
36 let events = events.clone();
37 move |w, evt| {
38 let ret = if !events.borrow().is_empty() {
39 if let Some(Some(cb)) = events.borrow_mut().get_mut(&(evt.bits())) {
40 cb(w);
41 w.redraw();
42 true
43 } else {
44 false
45 }
46 } else {
47 event.set(evt);
48 false
49 };
50 ret
51 }
52 });
53 let trig = Trig {
54 triggered,
55 event,
56 events,
57 };
58 Self { wid, trig }
59 }
60}
61
62impl<T: WidgetBase + WidgetExt> Listener<T> {
64 pub fn triggered(&self) -> bool {
66 self.trig.triggered.replace(false)
67 }
68
69 pub fn event(&self) -> Event {
72 self.trig.event.replace(Event::NoEvent)
73 }
74
75 pub fn on(&mut self, ev: Event, cb: impl FnMut(&mut T) + 'static) {
77 self.trig
78 .events
79 .borrow_mut()
80 .insert(ev.bits(), Some(Box::new(cb)));
81 }
82
83 pub fn on_hover(&mut self, cb: impl FnMut(&mut T) + 'static) {
85 self.on(Event::Enter, cb);
86 }
87
88 pub fn on_leave(&mut self, cb: impl FnMut(&mut T) + 'static) {
90 self.on(Event::Leave, cb);
91 }
92
93 pub fn on_click(&mut self, cb: impl FnMut(&mut T) + 'static) {
95 self.on(Event::Push, cb);
96 }
97
98 pub fn on_release(&mut self, cb: impl FnMut(&mut T) + 'static) {
100 self.on(Event::Released, cb);
101 }
102
103 pub fn on_drag(&mut self, cb: impl FnMut(&mut T) + 'static) {
105 self.on(Event::Drag, cb);
106 }
107
108 pub fn on_focus(&mut self, cb: impl FnMut(&mut T) + 'static) {
110 self.on(Event::Focus, cb);
111 }
112
113 pub fn on_unfocus(&mut self, cb: impl FnMut(&mut T) + 'static) {
115 self.on(Event::Unfocus, cb);
116 }
117
118 pub fn on_keydown(&mut self, cb: impl FnMut(&mut T) + 'static) {
120 self.on(Event::KeyDown, cb);
121 }
122
123 pub fn on_keyup(&mut self, cb: impl FnMut(&mut T) + 'static) {
125 self.on(Event::KeyUp, cb);
126 }
127
128 pub fn on_close(&mut self, cb: impl FnMut(&mut T) + 'static) {
130 self.on(Event::Close, cb);
131 }
132
133 pub fn on_move(&mut self, cb: impl FnMut(&mut T) + 'static) {
135 self.on(Event::Move, cb);
136 }
137
138 pub fn on_shortcut(&mut self, cb: impl FnMut(&mut T) + 'static) {
140 self.on(Event::Shortcut, cb);
141 }
142
143 pub fn on_deactivate(&mut self, cb: impl FnMut(&mut T) + 'static) {
145 self.on(Event::Deactivate, cb);
146 }
147
148 pub fn on_activate(&mut self, cb: impl FnMut(&mut T) + 'static) {
150 self.on(Event::Activate, cb);
151 }
152
153 pub fn on_hide(&mut self, cb: impl FnMut(&mut T) + 'static) {
155 self.on(Event::Hide, cb);
156 }
157
158 pub fn on_show(&mut self, cb: impl FnMut(&mut T) + 'static) {
160 self.on(Event::Show, cb);
161 }
162
163 pub fn on_paste(&mut self, cb: impl FnMut(&mut T) + 'static) {
165 self.on(Event::Paste, cb);
166 }
167
168 pub fn on_selection_clear(&mut self, cb: impl FnMut(&mut T) + 'static) {
170 self.on(Event::SelectionClear, cb);
171 }
172
173 pub fn on_mousewheel(&mut self, cb: impl FnMut(&mut T) + 'static) {
175 self.on(Event::MouseWheel, cb);
176 }
177
178 pub fn on_dnd_enter(&mut self, cb: impl FnMut(&mut T) + 'static) {
180 self.on(Event::DndEnter, cb);
181 }
182
183 pub fn on_dnd_drag(&mut self, cb: impl FnMut(&mut T) + 'static) {
185 self.on(Event::DndDrag, cb);
186 }
187
188 pub fn on_dnd_leave(&mut self, cb: impl FnMut(&mut T) + 'static) {
190 self.on(Event::DndLeave, cb);
191 }
192
193 pub fn on_dnd_release(&mut self, cb: impl FnMut(&mut T) + 'static) {
195 self.on(Event::DndRelease, cb);
196 }
197
198 pub fn on_screen_config_changed(&mut self, cb: impl FnMut(&mut T) + 'static) {
200 self.on(Event::ScreenConfigChanged, cb);
201 }
202
203 pub fn on_fullscreen(&mut self, cb: impl FnMut(&mut T) + 'static) {
205 self.on(Event::Fullscreen, cb);
206 }
207
208 pub fn on_zoom_gesture(&mut self, cb: impl FnMut(&mut T) + 'static) {
210 self.on(Event::ZoomGesture, cb);
211 }
212
213 pub fn on_zoom(&mut self, cb: impl FnMut(&mut T) + 'static) {
215 self.on(Event::ZoomEvent, cb);
216 }
217
218 pub fn on_resize(&mut self, cb: impl FnMut(&mut T) + 'static) {
220 self.on(Event::Resize, cb);
221 }
222}