cursive_core/cursive_run.rs
1use crate::{backend, buffer, event, Cursive, Vec2};
2use parking_lot::RwLock;
3use std::borrow::{Borrow, BorrowMut};
4use std::time::Duration;
5
6// How long we wait between two empty input polls
7const INPUT_POLL_DELAY_MS: u64 = 30;
8
9/// Event loop runner for a cursive instance.
10///
11/// You can get one from `Cursive::runner`, then either call `.run()`, or
12/// manually `.step()`.
13///
14/// The `C` type is usually either `Cursive` or `&mut Cursive`.
15pub struct CursiveRunner<C> {
16 siv: C,
17
18 backend: Box<dyn backend::Backend>,
19 buffer: RwLock<buffer::PrintBuffer>,
20
21 boring_frame_count: u32,
22 // Last layer sizes of the stack view.
23 // If it changed, clear the screen.
24 last_sizes: Vec<Vec2>,
25}
26
27impl<C> std::ops::Deref for CursiveRunner<C>
28where
29 C: Borrow<Cursive>,
30{
31 type Target = Cursive;
32
33 fn deref(&self) -> &Cursive {
34 self.siv.borrow()
35 }
36}
37
38impl<C> std::ops::DerefMut for CursiveRunner<C>
39where
40 C: BorrowMut<Cursive>,
41{
42 fn deref_mut(&mut self) -> &mut Cursive {
43 self.siv.borrow_mut()
44 }
45}
46
47impl<C> CursiveRunner<C> {
48 /// Creates a new cursive runner wrapper.
49 pub fn new(siv: C, backend: Box<dyn backend::Backend>) -> Self {
50 CursiveRunner {
51 siv,
52 backend,
53 buffer: RwLock::new(buffer::PrintBuffer::new()),
54 boring_frame_count: 0,
55 last_sizes: Vec::new(),
56 }
57 }
58
59 /// Returns the size of the screen, in characters.
60 fn screen_size(&self) -> Vec2 {
61 self.backend.screen_size()
62 }
63
64 /// Clean out the terminal and get back the wrapped object.
65 pub fn into_inner(self) -> C {
66 self.siv
67 }
68}
69
70impl<C> CursiveRunner<C>
71where
72 C: BorrowMut<Cursive>,
73{
74 fn layout(&mut self) {
75 let size = self.screen_size();
76 self.siv.borrow_mut().layout(size);
77 }
78
79 // Process any backend-requiring calls accumulated by the Cursive root.
80 fn process_pending_backend_calls(&mut self) {
81 let calls = std::mem::take(&mut self.backend_calls);
82 for call in calls {
83 (call)(&mut *self.backend);
84 }
85 }
86
87 fn draw(&mut self) {
88 let sizes = self.screen().layer_sizes();
89 if self.last_sizes != sizes {
90 // TODO: Maybe we only need to clear if the _max_ size differs?
91 // Or if the positions change?
92 self.clear();
93 self.last_sizes = sizes;
94 }
95
96 self.buffer.write().resize(self.screen_size());
97 self.siv.borrow_mut().draw(&self.buffer);
98 self.buffer.write().flush(&*self.backend);
99 }
100
101 /// Performs the first half of `Self::step()`.
102 ///
103 /// This is an advanced method for fine-tuned manual stepping;
104 /// you probably want [`run`][1] or [`step`][2].
105 ///
106 /// This processes any pending event or callback. After calling this,
107 /// you will want to call [`post_events`][3] with the result from this
108 /// function.
109 ///
110 /// Returns `true` if an event or callback was received,
111 /// and `false` otherwise.
112 ///
113 /// [1]: CursiveRunner::run()
114 /// [2]: CursiveRunner::step()
115 /// [3]: CursiveRunner::post_events()
116 pub fn process_events(&mut self) -> bool {
117 // Things are boring if nothing significant happened.
118 let mut boring = true;
119
120 // First, handle all available input
121 while let Some(event) = self.backend.poll_event() {
122 boring = false;
123 self.on_event(event);
124 self.process_pending_backend_calls();
125
126 if !self.is_running() {
127 return true;
128 }
129 }
130
131 // Then, handle any available callback
132 while self.process_callback() {
133 boring = false;
134
135 if !self.is_running() {
136 return true;
137 }
138 }
139
140 !boring
141 }
142
143 /// Performs the second half of `Self::step()`.
144 ///
145 /// This is an advanced method for fine-tuned manual stepping;
146 /// you probably want [`run`][1] or [`step`][2].
147 ///
148 /// You should call this after [`process_events`][3].
149 ///
150 /// [1]: CursiveRunner::run()
151 /// [2]: CursiveRunner::step()
152 /// [3]: CursiveRunner::process_events()
153 pub fn post_events(&mut self, received_something: bool) {
154 let boring = !received_something;
155 // How many times should we try if it's still boring?
156 // Total duration will be INPUT_POLL_DELAY_MS * repeats
157 // So effectively fps = 1000 / INPUT_POLL_DELAY_MS / repeats
158 if !boring
159 || self
160 .fps()
161 .map(|fps| 1000 / INPUT_POLL_DELAY_MS as u32 / fps.get())
162 .map(|repeats| self.boring_frame_count >= repeats)
163 .unwrap_or(false)
164 {
165 // We deserve to draw something!
166
167 if boring {
168 // We're only here because of a timeout.
169 self.on_event(event::Event::Refresh);
170 self.process_pending_backend_calls();
171 }
172
173 self.refresh();
174 }
175
176 if boring {
177 std::thread::sleep(Duration::from_millis(INPUT_POLL_DELAY_MS));
178 self.boring_frame_count += 1;
179 }
180 }
181
182 /// Refresh the screen with the current view tree state.
183 pub fn refresh(&mut self) {
184 self.boring_frame_count = 0;
185
186 // Do we need to redraw every time?
187 // Probably, actually.
188 // TODO: Do we need to re-layout every time?
189 self.layout();
190
191 // TODO: Do we need to redraw every view every time?
192 // (Is this getting repetitive? :p)
193 self.draw();
194 self.backend.refresh();
195 }
196
197 /// Return the name of the backend used.
198 ///
199 /// Mostly used for debugging.
200 pub fn backend_name(&self) -> &str {
201 self.backend.name()
202 }
203
204 /// Performs a single step from the event loop.
205 ///
206 /// Useful if you need tighter control on the event loop.
207 /// Otherwise, [`run(&mut self)`] might be more convenient.
208 ///
209 /// Returns `true` if an input event or callback was received
210 /// during this step, and `false` otherwise.
211 ///
212 /// [`run(&mut self)`]: #method.run
213 pub fn step(&mut self) -> bool {
214 let received_something = self.process_events();
215 self.post_events(received_something);
216 received_something
217 }
218
219 /// Runs the event loop.
220 ///
221 /// It will wait for user input (key presses)
222 /// and trigger callbacks accordingly.
223 ///
224 /// Internally, it calls [`step(&mut self)`] until [`quit(&mut self)`] is
225 /// called.
226 ///
227 /// After this function returns, you can call it again and it will start a
228 /// new loop.
229 ///
230 /// [`step(&mut self)`]: #method.step
231 /// [`quit(&mut self)`]: #method.quit
232 pub fn run(&mut self) {
233 self.refresh();
234
235 // And the big event loop begins!
236 while self.is_running() {
237 self.step();
238 }
239 }
240}