1use crate::clipboard;
3use crate::event;
4use crate::window;
5use crate::{Clipboard, InputMethod, Window};
6
7use std::rc::{self, Rc};
8use std::sync::Arc;
9use std::vec;
10
11#[derive(Debug)]
18pub struct Shell<'a, Message> {
19 window: &'a dyn Window,
20 bus: &'a mut Bus<Message>,
21 waker: Waker,
22 event_status: event::Status,
23 redraw_request: window::RedrawRequest,
24 input_method: InputMethod,
25 invalidation: Invalidation,
26 clipboard: Clipboard,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
35pub enum Invalidation {
36 None,
38 Overlay,
40 Layout(Diff),
43 Widgets,
46}
47
48impl<'a, Message> Shell<'a, Message> {
49 pub fn new(window: &'a dyn Window, waker: Waker, bus: &'a mut Bus<Message>) -> Self {
51 Self {
52 window,
53 bus,
54 waker,
55 event_status: event::Status::Ignored,
56 redraw_request: window::RedrawRequest::Wait,
57 invalidation: Invalidation::None,
58 input_method: InputMethod::Disabled,
59 clipboard: Clipboard {
60 reads: Vec::new(),
61 write: None,
62 },
63 }
64 }
65
66 pub fn local<'b, A>(&self, bus: &'b mut Bus<A>) -> Shell<'b, A>
68 where
69 'a: 'b,
70 {
71 Shell::new(self.window, self.waker.clone(), bus)
72 }
73
74 pub fn window(&self) -> &'a dyn Window {
76 self.window
77 }
78
79 pub fn waker(&self) -> &Waker {
81 &self.waker
82 }
83
84 #[must_use]
86 pub fn is_empty(&self) -> bool {
87 self.bus.messages.is_empty()
88 }
89
90 pub fn publish(&mut self, message: Message) {
92 let _ = self.publish_and_track(message);
93 }
94
95 pub fn publish_and_track(&mut self, message: Message) -> Tracking {
100 self.bus.push(message)
101 }
102
103 pub fn forward(&mut self, message: Message, receipt: Receipt) {
106 self.bus.forward(message, receipt);
107 }
108
109 pub fn capture_event(&mut self) {
114 self.event_status = event::Status::Captured;
115 }
116
117 #[must_use]
119 pub fn event_status(&self) -> event::Status {
120 self.event_status
121 }
122
123 #[must_use]
125 pub fn is_event_captured(&self) -> bool {
126 self.event_status == event::Status::Captured
127 }
128
129 pub fn request_redraw(&mut self) {
131 self.redraw_request = window::RedrawRequest::NextFrame;
132 }
133
134 pub fn request_redraw_at(&mut self, redraw_request: impl Into<window::RedrawRequest>) {
136 self.redraw_request = self.redraw_request.min(redraw_request.into());
137 }
138
139 #[must_use]
141 pub fn redraw_request(&self) -> window::RedrawRequest {
142 self.redraw_request
143 }
144
145 pub fn replace_redraw_request(shell: &mut Self, redraw_request: window::RedrawRequest) {
151 shell.redraw_request = redraw_request;
152 }
153
154 pub fn read_clipboard(&mut self, kind: clipboard::Kind) {
158 self.clipboard.reads.push(kind);
159 }
160
161 pub fn write_clipboard(&mut self, content: impl Into<clipboard::Content>) {
165 self.clipboard.write = Some(content.into());
166 }
167
168 pub fn clipboard_mut(&mut self) -> &mut Clipboard {
170 &mut self.clipboard
171 }
172
173 pub fn request_input_method<T: AsRef<str>>(&mut self, ime: &InputMethod<T>) {
178 self.input_method.merge(ime);
179 }
180
181 #[must_use]
183 pub fn input_method(&self) -> &InputMethod {
184 &self.input_method
185 }
186
187 #[must_use]
189 pub fn input_method_mut(&mut self) -> &mut InputMethod {
190 &mut self.input_method
191 }
192
193 pub fn invalidate_overlay(&mut self) {
197 self.invalidate(Invalidation::Overlay);
198 }
199
200 pub fn invalidate_layout(&mut self) {
204 self.invalidate_layout_with(Diff::Skip);
205 }
206
207 pub fn invalidate_layout_with(&mut self, diff: Diff) {
209 self.invalidate(Invalidation::Layout(diff));
210 }
211
212 pub fn invalidate_widgets(&mut self) {
216 self.invalidate(Invalidation::Widgets);
217 }
218
219 pub fn invalidate(&mut self, invalidation: Invalidation) {
221 self.invalidation = self.invalidation.max(invalidation);
222 }
223
224 pub fn invalidation(&self) -> Invalidation {
226 self.invalidation
227 }
228
229 pub fn merge<B>(&mut self, mut other: Shell<'_, B>, f: impl Fn(B) -> Message) {
234 self.bus.messages.extend(
235 other
236 .bus
237 .messages
238 .drain(..)
239 .map(|(message, receipt)| (f(message), receipt)),
240 );
241
242 self.invalidation = self.invalidation.max(other.invalidation);
243 self.redraw_request = self.redraw_request.min(other.redraw_request);
244 self.event_status = self.event_status.merge(other.event_status);
245
246 self.input_method.merge(&other.input_method);
247 self.clipboard.merge(&mut other.clipboard);
248 }
249}
250
251#[derive(Clone)]
254pub struct Waker {
255 wake: Arc<dyn Fn() + Send + Sync + 'static>,
256}
257
258impl Waker {
259 pub fn new(wake: impl Fn() + Send + Sync + 'static) -> Self {
261 Self {
262 wake: Arc::new(wake),
263 }
264 }
265
266 pub fn noop() -> Self {
268 Self::new(|| {})
269 }
270
271 pub fn wake(&self) {
275 (self.wake)();
276 }
277}
278
279impl std::fmt::Debug for Waker {
280 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
281 f.debug_struct("Waker").finish()
282 }
283}
284
285#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
287pub enum Diff {
288 Skip,
290 Perform,
292}
293
294#[derive(Debug)]
296pub struct Bus<T> {
297 messages: Vec<(T, Receipt)>,
298}
299
300impl<T> Bus<T> {
301 pub fn new() -> Self {
303 Self {
304 messages: Vec::new(),
305 }
306 }
307
308 pub fn is_empty(&self) -> bool {
310 self.messages.is_empty()
311 }
312
313 pub fn len(&self) -> usize {
315 self.messages.len()
316 }
317
318 pub fn push(&mut self, message: T) -> Tracking {
323 let receipt = Receipt::new();
324 let tracking = receipt.tracking();
325
326 self.messages.push((message, receipt));
327
328 tracking
329 }
330
331 pub fn forward(&mut self, message: T, receipt: Receipt) {
333 self.messages.push((message, receipt));
334 }
335
336 pub fn drain(&mut self) -> impl Iterator<Item = (T, Receipt)> {
338 self.messages.drain(..)
339 }
340}
341
342impl<T> Default for Bus<T> {
343 fn default() -> Self {
344 Self::new()
345 }
346}
347
348impl<T> IntoIterator for Bus<T> {
349 type Item = T;
350 type IntoIter = IntoIter<T>;
351
352 fn into_iter(self) -> Self::IntoIter {
353 IntoIter {
354 iter: self.messages.into_iter(),
355 }
356 }
357}
358
359pub struct IntoIter<T> {
361 iter: vec::IntoIter<(T, Receipt)>,
362}
363
364impl<T> Iterator for IntoIter<T> {
365 type Item = T;
366
367 fn next(&mut self) -> Option<Self::Item> {
368 Some(self.iter.next()?.0)
369 }
370}
371
372#[derive(Debug)]
374pub struct Receipt(Rc<()>);
375
376impl Receipt {
377 fn new() -> Self {
378 Self(Rc::new(()))
379 }
380
381 fn tracking(&self) -> Tracking {
382 Tracking(Rc::downgrade(&self.0))
383 }
384}
385
386#[derive(Debug, Clone)]
388pub struct Tracking(rc::Weak<()>);
389
390impl Tracking {
391 pub fn is_processed(&self) -> bool {
394 self.0.strong_count() == 0
395 }
396}