1use crate::{
2 elements::ElementBox,
3 executor,
4 keymap::{self, Keystroke},
5 platform::{self, App as _, WindowOptions},
6 presenter::Presenter,
7 util::post_inc,
8 AssetCache, AssetSource, FontCache, TextLayoutCache,
9};
10use anyhow::{anyhow, Result};
11use async_std::sync::Condvar;
12use keymap::MatchResult;
13use parking_lot::Mutex;
14use pathfinder_geometry::{rect::RectF, vector::vec2f};
15use platform::Event;
16use smol::prelude::*;
17use std::{
18 any::{type_name, Any, TypeId},
19 cell::RefCell,
20 collections::{HashMap, HashSet, VecDeque},
21 fmt::{self, Debug},
22 hash::{Hash, Hasher},
23 marker::PhantomData,
24 rc::{self, Rc},
25 sync::{Arc, Weak},
26};
27
28pub trait Entity: 'static + Send + Sync {
29 type Event;
30}
31
32pub trait View: Entity {
33 fn ui_name() -> &'static str;
34 fn render<'a>(&self, app: &AppContext) -> ElementBox;
35 fn on_focus(&mut self, _ctx: &mut ViewContext<Self>) {}
36 fn on_blur(&mut self, _ctx: &mut ViewContext<Self>) {}
37 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
38 Self::default_keymap_context()
39 }
40 fn default_keymap_context() -> keymap::Context {
41 let mut ctx = keymap::Context::default();
42 ctx.set.insert(Self::ui_name().into());
43 ctx
44 }
45}
46
47pub trait ModelAsRef {
48 fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T;
49}
50
51pub trait UpdateModel {
52 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
53 where
54 T: Entity,
55 F: FnOnce(&mut T, &mut ModelContext<T>) -> S;
56}
57
58pub trait ViewAsRef {
59 fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T;
60}
61
62pub trait UpdateView {
63 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
64 where
65 T: View,
66 F: FnOnce(&mut T, &mut ViewContext<T>) -> S;
67}
68
69#[derive(Clone)]
70pub struct App(Rc<RefCell<MutableAppContext>>);
71
72impl App {
73 pub fn test<T, A: AssetSource, F: Future<Output = T>, G: FnOnce(App) -> F>(
74 asset_source: A,
75 f: G,
76 ) -> T {
77 let platform = platform::test::app();
78 let foreground = Rc::new(executor::Foreground::test());
79 let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
80 foreground.clone(),
81 Arc::new(platform),
82 asset_source,
83 ))));
84 app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
85 smol::block_on(foreground.run(f(app)))
86 }
87
88 pub fn new(asset_source: impl AssetSource) -> Result<Self> {
89 let platform = Arc::new(platform::current::app());
90 let foreground = Rc::new(executor::Foreground::platform(platform.dispatcher())?);
91 let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
92 foreground,
93 platform,
94 asset_source,
95 ))));
96 app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
97 Ok(app)
98 }
99
100 pub fn on_window_invalidated<F: 'static + FnMut(WindowInvalidation, &mut MutableAppContext)>(
101 &self,
102 window_id: usize,
103 callback: F,
104 ) {
105 self.0
106 .borrow_mut()
107 .on_window_invalidated(window_id, callback);
108 }
109
110 pub fn add_action<S, V, T, F>(&self, name: S, handler: F)
111 where
112 S: Into<String>,
113 V: View,
114 T: Any,
115 F: 'static + FnMut(&mut V, &T, &mut ViewContext<V>),
116 {
117 self.0.borrow_mut().add_action(name, handler);
118 }
119
120 pub fn add_global_action<S, T, F>(&self, name: S, handler: F)
121 where
122 S: Into<String>,
123 T: 'static + Any,
124 F: 'static + FnMut(&T, &mut MutableAppContext),
125 {
126 self.0.borrow_mut().add_global_action(name, handler);
127 }
128
129 pub fn dispatch_action<T: 'static + Any>(
130 &self,
131 window_id: usize,
132 responder_chain: Vec<usize>,
133 name: &str,
134 arg: T,
135 ) {
136 self.0.borrow_mut().dispatch_action(
137 window_id,
138 &responder_chain,
139 name,
140 Box::new(arg).as_ref(),
141 );
142 }
143
144 pub fn dispatch_global_action<T: 'static + Any>(&self, name: &str, arg: T) {
145 self.0
146 .borrow_mut()
147 .dispatch_global_action(name, Box::new(arg).as_ref());
148 }
149
150 pub fn add_bindings<T: IntoIterator<Item = keymap::Binding>>(&self, bindings: T) {
151 self.0.borrow_mut().add_bindings(bindings);
152 }
153
154 pub fn dispatch_keystroke(
155 &self,
156 window_id: usize,
157 responder_chain: Vec<usize>,
158 keystroke: &Keystroke,
159 ) -> Result<bool> {
160 let mut state = self.0.borrow_mut();
161 state.dispatch_keystroke(window_id, responder_chain, keystroke)
162 }
163
164 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
165 where
166 T: Entity,
167 F: FnOnce(&mut ModelContext<T>) -> T,
168 {
169 let mut state = self.0.borrow_mut();
170 state.pending_flushes += 1;
171 let handle = state.add_model(build_model);
172 state.flush_effects();
173 handle
174 }
175
176 fn read_model<T, F, S>(&self, handle: &ModelHandle<T>, read: F) -> S
177 where
178 T: Entity,
179 F: FnOnce(&T, &AppContext) -> S,
180 {
181 let state = self.0.borrow();
182 read(state.model(handle), &state.ctx)
183 }
184
185 pub fn add_window<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>)
186 where
187 T: View,
188 F: FnOnce(&mut ViewContext<T>) -> T,
189 {
190 self.0.borrow_mut().add_window(build_root_view)
191 }
192
193 pub fn window_ids(&self) -> Vec<usize> {
194 self.0.borrow().window_ids().collect()
195 }
196
197 pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
198 self.0.borrow().root_view(window_id)
199 }
200
201 pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
202 where
203 T: View,
204 F: FnOnce(&mut ViewContext<T>) -> T,
205 {
206 let mut state = self.0.borrow_mut();
207 state.pending_flushes += 1;
208 let handle = state.add_view(window_id, build_view);
209 state.flush_effects();
210 handle
211 }
212
213 pub fn add_option_view<T, F>(
214 &mut self,
215 window_id: usize,
216 build_view: F,
217 ) -> Option<ViewHandle<T>>
218 where
219 T: View,
220 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
221 {
222 let mut state = self.0.borrow_mut();
223 state.pending_flushes += 1;
224 let handle = state.add_option_view(window_id, build_view);
225 state.flush_effects();
226 handle
227 }
228
229 pub fn read<T, F: FnOnce(&AppContext) -> T>(&mut self, callback: F) -> T {
230 callback(self.0.borrow().downgrade())
231 }
232
233 pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
234 let mut state = self.0.borrow_mut();
235 state.pending_flushes += 1;
236 let result = callback(&mut *state);
237 state.flush_effects();
238 result
239 }
240
241 fn read_view<T, F, S>(&self, handle: &ViewHandle<T>, read: F) -> S
242 where
243 T: View,
244 F: FnOnce(&T, &AppContext) -> S,
245 {
246 let state = self.0.borrow();
247 read(state.view(handle), state.downgrade())
248 }
249
250 pub fn finish_pending_tasks(&self) -> impl Future<Output = ()> {
251 self.0.borrow().finish_pending_tasks()
252 }
253
254 pub fn font_cache(&self) -> Arc<FontCache> {
255 self.0.borrow().font_cache.clone()
256 }
257
258 pub fn platform(&self) -> Arc<dyn platform::App> {
259 self.0.borrow().platform.clone()
260 }
261}
262
263impl UpdateModel for App {
264 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
265 where
266 T: Entity,
267 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
268 {
269 let mut state = self.0.borrow_mut();
270 state.pending_flushes += 1;
271 let result = state.update_model(handle, update);
272 state.flush_effects();
273 result
274 }
275}
276
277impl UpdateView for App {
278 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
279 where
280 T: View,
281 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
282 {
283 let mut state = self.0.borrow_mut();
284 state.pending_flushes += 1;
285 let result = state.update_view(handle, update);
286 state.flush_effects();
287 result
288 }
289}
290
291type ActionCallback =
292 dyn FnMut(&mut dyn AnyView, &dyn Any, &mut MutableAppContext, usize, usize) -> bool;
293
294type GlobalActionCallback = dyn FnMut(&dyn Any, &mut MutableAppContext);
295
296pub struct MutableAppContext {
297 weak_self: Option<rc::Weak<RefCell<Self>>>,
298 platform: Arc<dyn platform::App>,
299 font_cache: Arc<FontCache>,
300 assets: Arc<AssetCache>,
301 ctx: AppContext,
302 actions: HashMap<TypeId, HashMap<String, Vec<Box<ActionCallback>>>>,
303 global_actions: HashMap<String, Vec<Box<GlobalActionCallback>>>,
304 keystroke_matcher: keymap::Matcher,
305 next_entity_id: usize,
306 next_window_id: usize,
307 next_task_id: usize,
308 subscriptions: HashMap<usize, Vec<Subscription>>,
309 observations: HashMap<usize, Vec<Observation>>,
310 window_invalidations: HashMap<usize, WindowInvalidation>,
311 invalidation_callbacks:
312 HashMap<usize, Box<dyn FnMut(WindowInvalidation, &mut MutableAppContext)>>,
313 foreground: Rc<executor::Foreground>,
314 background: Arc<executor::Background>,
315 future_handlers: Rc<RefCell<HashMap<usize, FutureHandler>>>,
316 stream_handlers: Rc<RefCell<HashMap<usize, StreamHandler>>>,
317 task_done: Arc<Condvar>,
318 pending_effects: VecDeque<Effect>,
319 pending_flushes: usize,
320 flushing_effects: bool,
321}
322
323impl MutableAppContext {
324 pub fn new(
325 foreground: Rc<executor::Foreground>,
326 platform: Arc<dyn platform::App>,
327 asset_source: impl AssetSource,
328 ) -> Self {
329 let fonts = platform.fonts();
330 Self {
331 weak_self: None,
332 platform,
333 font_cache: Arc::new(FontCache::new(fonts)),
334 assets: Arc::new(AssetCache::new(asset_source)),
335 ctx: AppContext {
336 models: HashMap::new(),
337 windows: HashMap::new(),
338 ref_counts: Arc::new(Mutex::new(RefCounts::default())),
339 },
340 actions: HashMap::new(),
341 global_actions: HashMap::new(),
342 keystroke_matcher: keymap::Matcher::default(),
343 next_entity_id: 0,
344 next_window_id: 0,
345 next_task_id: 0,
346 subscriptions: HashMap::new(),
347 observations: HashMap::new(),
348 window_invalidations: HashMap::new(),
349 invalidation_callbacks: HashMap::new(),
350 foreground,
351 background: Arc::new(executor::Background::new()),
352 future_handlers: Default::default(),
353 stream_handlers: Default::default(),
354 task_done: Default::default(),
355 pending_effects: VecDeque::new(),
356 pending_flushes: 0,
357 flushing_effects: false,
358 }
359 }
360
361 pub fn upgrade(&self) -> App {
362 App(self.weak_self.as_ref().unwrap().upgrade().unwrap())
363 }
364
365 pub fn downgrade(&self) -> &AppContext {
366 &self.ctx
367 }
368
369 pub fn foreground_executor(&self) -> Rc<executor::Foreground> {
370 self.foreground.clone()
371 }
372
373 pub fn on_window_invalidated<F: 'static + FnMut(WindowInvalidation, &mut MutableAppContext)>(
374 &mut self,
375 window_id: usize,
376 callback: F,
377 ) {
378 self.invalidation_callbacks
379 .insert(window_id, Box::new(callback));
380 }
381
382 pub fn add_action<S, V, T, F>(&mut self, name: S, mut handler: F)
383 where
384 S: Into<String>,
385 V: View,
386 T: Any,
387 F: 'static + FnMut(&mut V, &T, &mut ViewContext<V>),
388 {
389 let name = name.into();
390 let name_clone = name.clone();
391 let handler = Box::new(
392 move |view: &mut dyn AnyView,
393 arg: &dyn Any,
394 app: &mut MutableAppContext,
395 window_id: usize,
396 view_id: usize| {
397 match arg.downcast_ref() {
398 Some(arg) => {
399 let mut ctx = ViewContext::new(app, window_id, view_id);
400 handler(
401 view.as_any_mut()
402 .downcast_mut()
403 .expect("downcast is type safe"),
404 arg,
405 &mut ctx,
406 );
407 ctx.halt_action_dispatch
408 }
409 None => {
410 log::error!("Could not downcast argument for action {}", name_clone);
411 false
412 }
413 }
414 },
415 );
416
417 self.actions
418 .entry(TypeId::of::<V>())
419 .or_default()
420 .entry(name)
421 .or_default()
422 .push(handler);
423 }
424
425 pub fn add_global_action<S, T, F>(&mut self, name: S, mut handler: F)
426 where
427 S: Into<String>,
428 T: 'static + Any,
429 F: 'static + FnMut(&T, &mut MutableAppContext),
430 {
431 let name = name.into();
432 let name_clone = name.clone();
433 let handler = Box::new(move |arg: &dyn Any, app: &mut MutableAppContext| {
434 if let Some(arg) = arg.downcast_ref() {
435 handler(arg, app);
436 } else {
437 log::error!("Could not downcast argument for action {}", name_clone);
438 }
439 });
440
441 self.global_actions.entry(name).or_default().push(handler);
442 }
443
444 pub fn window_ids(&self) -> impl Iterator<Item = usize> + '_ {
445 self.ctx.windows.keys().cloned()
446 }
447
448 pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
449 self.ctx
450 .windows
451 .get(&window_id)
452 .and_then(|window| window.root_view.as_ref().unwrap().clone().downcast::<T>())
453 }
454
455 pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
456 self.ctx.root_view_id(window_id)
457 }
458
459 pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
460 self.ctx.focused_view_id(window_id)
461 }
462
463 pub fn render_view(&self, window_id: usize, view_id: usize) -> Result<ElementBox> {
464 self.ctx.render_view(window_id, view_id)
465 }
466
467 pub fn render_views(&self, window_id: usize) -> Result<HashMap<usize, ElementBox>> {
468 self.ctx.render_views(window_id)
469 }
470
471 pub fn dispatch_action(
472 &mut self,
473 window_id: usize,
474 path: &[usize],
475 name: &str,
476 arg: &dyn Any,
477 ) -> bool {
478 self.pending_flushes += 1;
479 let mut halted_dispatch = false;
480
481 for view_id in path.iter().rev() {
482 if let Some(mut view) = self
483 .ctx
484 .windows
485 .get_mut(&window_id)
486 .and_then(|w| w.views.remove(view_id))
487 {
488 let type_id = view.as_any().type_id();
489
490 if let Some((name, mut handlers)) = self
491 .actions
492 .get_mut(&type_id)
493 .and_then(|h| h.remove_entry(name))
494 {
495 for handler in handlers.iter_mut().rev() {
496 let halt_dispatch = handler(view.as_mut(), arg, self, window_id, *view_id);
497 if halt_dispatch {
498 halted_dispatch = true;
499 break;
500 }
501 }
502 self.actions
503 .get_mut(&type_id)
504 .unwrap()
505 .insert(name, handlers);
506 }
507
508 self.ctx
509 .windows
510 .get_mut(&window_id)
511 .unwrap()
512 .views
513 .insert(*view_id, view);
514
515 if halted_dispatch {
516 break;
517 }
518 }
519 }
520
521 if !halted_dispatch {
522 self.dispatch_global_action(name, arg);
523 }
524
525 self.flush_effects();
526 halted_dispatch
527 }
528
529 fn dispatch_global_action(&mut self, name: &str, arg: &dyn Any) {
530 if let Some((name, mut handlers)) = self.global_actions.remove_entry(name) {
531 self.pending_flushes += 1;
532 for handler in handlers.iter_mut().rev() {
533 handler(arg, self);
534 }
535 self.global_actions.insert(name, handlers);
536 self.flush_effects();
537 }
538 }
539
540 fn add_bindings<T: IntoIterator<Item = keymap::Binding>>(&mut self, bindings: T) {
541 self.keystroke_matcher.add_bindings(bindings);
542 }
543
544 pub fn dispatch_keystroke(
545 &mut self,
546 window_id: usize,
547 responder_chain: Vec<usize>,
548 keystroke: &Keystroke,
549 ) -> Result<bool> {
550 let mut context_chain = Vec::new();
551 let mut context = keymap::Context::default();
552 for view_id in &responder_chain {
553 if let Some(view) = self
554 .ctx
555 .windows
556 .get(&window_id)
557 .and_then(|w| w.views.get(view_id))
558 {
559 context.extend(view.keymap_context(self.downgrade()));
560 context_chain.push(context.clone());
561 } else {
562 return Err(anyhow!(
563 "View {} in responder chain does not exist",
564 view_id
565 ));
566 }
567 }
568
569 let mut pending = false;
570 for (i, ctx) in context_chain.iter().enumerate().rev() {
571 match self
572 .keystroke_matcher
573 .push_keystroke(keystroke.clone(), responder_chain[i], ctx)
574 {
575 MatchResult::None => {}
576 MatchResult::Pending => pending = true,
577 MatchResult::Action { name, arg } => {
578 if self.dispatch_action(
579 window_id,
580 &responder_chain[0..=i],
581 &name,
582 arg.as_ref().map(|arg| arg.as_ref()).unwrap_or(&()),
583 ) {
584 return Ok(true);
585 }
586 }
587 }
588 }
589
590 Ok(pending)
591 }
592
593 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
594 where
595 T: Entity,
596 F: FnOnce(&mut ModelContext<T>) -> T,
597 {
598 self.pending_flushes += 1;
599 let model_id = post_inc(&mut self.next_entity_id);
600 let mut ctx = ModelContext::new(self, model_id);
601 let model = build_model(&mut ctx);
602 self.ctx.models.insert(model_id, Box::new(model));
603 self.flush_effects();
604 ModelHandle::new(model_id, &self.ctx.ref_counts)
605 }
606
607 pub fn add_window<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>)
608 where
609 T: View,
610 F: FnOnce(&mut ViewContext<T>) -> T,
611 {
612 let window_id = post_inc(&mut self.next_window_id);
613 self.ctx.windows.insert(window_id, Window::default());
614
615 let root_handle = self.add_view(window_id, build_root_view);
616 self.ctx.windows.get_mut(&window_id).unwrap().root_view = Some(root_handle.clone().into());
617 self.focus(window_id, root_handle.id());
618
619 match self.platform.open_window(
620 WindowOptions {
621 bounds: RectF::new(vec2f(0., 0.), vec2f(1024., 768.)),
622 title: "Zed".into(),
623 },
624 self.foreground.clone(),
625 ) {
626 Err(e) => log::error!("error opening window: {}", e),
627 Ok(mut window) => {
628 let text_layout_cache = TextLayoutCache::new(self.platform.fonts());
629 let presenter = Rc::new(RefCell::new(Presenter::new(
630 window_id,
631 self.font_cache.clone(),
632 text_layout_cache,
633 self.assets.clone(),
634 self,
635 )));
636
637 {
638 let mut app = self.upgrade();
639 let presenter = presenter.clone();
640 window.on_event(Box::new(move |event| {
641 app.update(|ctx| {
642 if let Event::KeyDown { keystroke, .. } = &event {
643 if ctx
644 .dispatch_keystroke(
645 window_id,
646 presenter.borrow().dispatch_path(ctx.downgrade()),
647 keystroke,
648 )
649 .unwrap()
650 {
651 return;
652 }
653 }
654
655 let actions = presenter
656 .borrow_mut()
657 .dispatch_event(event, ctx.downgrade());
658 for action in actions {
659 ctx.dispatch_action(
660 window_id,
661 &action.path,
662 action.name,
663 action.arg.as_ref(),
664 );
665 }
666 })
667 }));
668 }
669
670 {
671 let mut app = self.upgrade();
672 let presenter = presenter.clone();
673 window.on_resize(Box::new(move |window| {
674 app.update(|ctx| {
675 let scene = presenter.borrow_mut().build_scene(
676 window.size(),
677 window.scale_factor(),
678 ctx,
679 );
680 window.present_scene(scene);
681 })
682 }));
683 }
684
685 self.on_window_invalidated(window_id, move |invalidation, ctx| {
686 let mut presenter = presenter.borrow_mut();
687 presenter.invalidate(invalidation, ctx.downgrade());
688 let scene = presenter.build_scene(window.size(), window.scale_factor(), ctx);
689 window.present_scene(scene);
690 });
691 }
692 }
693
694 (window_id, root_handle)
695 }
696
697 pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
698 where
699 T: View,
700 F: FnOnce(&mut ViewContext<T>) -> T,
701 {
702 self.add_option_view(window_id, |ctx| Some(build_view(ctx)))
703 .unwrap()
704 }
705
706 pub fn add_option_view<T, F>(
707 &mut self,
708 window_id: usize,
709 build_view: F,
710 ) -> Option<ViewHandle<T>>
711 where
712 T: View,
713 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
714 {
715 let view_id = post_inc(&mut self.next_entity_id);
716 self.pending_flushes += 1;
717 let mut ctx = ViewContext::new(self, window_id, view_id);
718 let handle = if let Some(view) = build_view(&mut ctx) {
719 if let Some(window) = self.ctx.windows.get_mut(&window_id) {
720 window.views.insert(view_id, Box::new(view));
721 } else {
722 panic!("Window does not exist");
723 }
724 self.window_invalidations
725 .entry(window_id)
726 .or_default()
727 .updated
728 .insert(view_id);
729 Some(ViewHandle::new(window_id, view_id, &self.ctx.ref_counts))
730 } else {
731 None
732 };
733 self.flush_effects();
734 handle
735 }
736
737 fn remove_dropped_entities(&mut self) {
738 loop {
739 let (dropped_models, dropped_views) = self.ctx.ref_counts.lock().take_dropped();
740 if dropped_models.is_empty() && dropped_views.is_empty() {
741 break;
742 }
743
744 for model_id in dropped_models {
745 self.ctx.models.remove(&model_id);
746 self.subscriptions.remove(&model_id);
747 self.observations.remove(&model_id);
748 }
749
750 for (window_id, view_id) in dropped_views {
751 self.subscriptions.remove(&view_id);
752 self.observations.remove(&view_id);
753 if let Some(window) = self.ctx.windows.get_mut(&window_id) {
754 self.window_invalidations
755 .entry(window_id)
756 .or_default()
757 .removed
758 .push(view_id);
759 window.views.remove(&view_id);
760 }
761 }
762 }
763 }
764
765 fn flush_effects(&mut self) {
766 self.pending_flushes -= 1;
767
768 if !self.flushing_effects && self.pending_flushes == 0 {
769 self.flushing_effects = true;
770
771 while let Some(effect) = self.pending_effects.pop_front() {
772 match effect {
773 Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload),
774 Effect::ModelNotification { model_id } => self.notify_model_observers(model_id),
775 Effect::ViewNotification { window_id, view_id } => {
776 self.notify_view_observers(window_id, view_id)
777 }
778 Effect::Focus { window_id, view_id } => {
779 self.focus(window_id, view_id);
780 }
781 }
782 }
783
784 self.flushing_effects = false;
785 self.remove_dropped_entities();
786 self.update_windows();
787 }
788 }
789
790 fn update_windows(&mut self) {
791 let mut invalidations = HashMap::new();
792 std::mem::swap(&mut invalidations, &mut self.window_invalidations);
793
794 for (window_id, invalidation) in invalidations {
795 if let Some(mut callback) = self.invalidation_callbacks.remove(&window_id) {
796 callback(invalidation, self);
797 self.invalidation_callbacks.insert(window_id, callback);
798 }
799 }
800 }
801
802 fn emit_event(&mut self, entity_id: usize, payload: Box<dyn Any>) {
803 if let Some(subscriptions) = self.subscriptions.remove(&entity_id) {
804 for mut subscription in subscriptions {
805 let alive = match &mut subscription {
806 Subscription::FromModel { model_id, callback } => {
807 if let Some(mut model) = self.ctx.models.remove(model_id) {
808 callback(model.as_any_mut(), payload.as_ref(), self, *model_id);
809 self.ctx.models.insert(*model_id, model);
810 true
811 } else {
812 false
813 }
814 }
815 Subscription::FromView {
816 window_id,
817 view_id,
818 callback,
819 } => {
820 if let Some(mut view) = self
821 .ctx
822 .windows
823 .get_mut(&window_id)
824 .and_then(|window| window.views.remove(view_id))
825 {
826 callback(
827 view.as_any_mut(),
828 payload.as_ref(),
829 self,
830 *window_id,
831 *view_id,
832 );
833 self.ctx
834 .windows
835 .get_mut(&window_id)
836 .unwrap()
837 .views
838 .insert(*view_id, view);
839 true
840 } else {
841 false
842 }
843 }
844 };
845
846 if alive {
847 self.subscriptions
848 .entry(entity_id)
849 .or_default()
850 .push(subscription);
851 }
852 }
853 }
854 }
855
856 fn notify_model_observers(&mut self, observed_id: usize) {
857 if let Some(observations) = self.observations.remove(&observed_id) {
858 if self.ctx.models.contains_key(&observed_id) {
859 for mut observation in observations {
860 let alive = match &mut observation {
861 Observation::FromModel { model_id, callback } => {
862 if let Some(mut model) = self.ctx.models.remove(model_id) {
863 callback(model.as_any_mut(), observed_id, self, *model_id);
864 self.ctx.models.insert(*model_id, model);
865 true
866 } else {
867 false
868 }
869 }
870 Observation::FromView {
871 window_id,
872 view_id,
873 callback,
874 } => {
875 if let Some(mut view) = self
876 .ctx
877 .windows
878 .get_mut(window_id)
879 .and_then(|w| w.views.remove(view_id))
880 {
881 callback(
882 view.as_any_mut(),
883 observed_id,
884 self,
885 *window_id,
886 *view_id,
887 );
888 self.ctx
889 .windows
890 .get_mut(window_id)
891 .unwrap()
892 .views
893 .insert(*view_id, view);
894 true
895 } else {
896 false
897 }
898 }
899 };
900
901 if alive {
902 self.observations
903 .entry(observed_id)
904 .or_default()
905 .push(observation);
906 }
907 }
908 }
909 }
910 }
911
912 fn notify_view_observers(&mut self, window_id: usize, view_id: usize) {
913 self.window_invalidations
914 .entry(window_id)
915 .or_default()
916 .updated
917 .insert(view_id);
918 }
919
920 fn focus(&mut self, window_id: usize, focused_id: usize) {
921 if self
922 .ctx
923 .windows
924 .get(&window_id)
925 .and_then(|w| w.focused_view)
926 .map_or(false, |cur_focused| cur_focused == focused_id)
927 {
928 return;
929 }
930
931 self.pending_flushes += 1;
932
933 if let Some((blurred_id, mut blurred)) =
934 self.ctx.windows.get_mut(&window_id).and_then(|w| {
935 let blurred_view = w.focused_view;
936 w.focused_view = Some(focused_id);
937 blurred_view.and_then(|id| w.views.remove(&id).map(|view| (id, view)))
938 })
939 {
940 blurred.on_blur(self, window_id, blurred_id);
941 self.ctx
942 .windows
943 .get_mut(&window_id)
944 .unwrap()
945 .views
946 .insert(blurred_id, blurred);
947 }
948
949 if let Some(mut focused) = self
950 .ctx
951 .windows
952 .get_mut(&window_id)
953 .and_then(|w| w.views.remove(&focused_id))
954 {
955 focused.on_focus(self, window_id, focused_id);
956 self.ctx
957 .windows
958 .get_mut(&window_id)
959 .unwrap()
960 .views
961 .insert(focused_id, focused);
962 }
963
964 self.flush_effects();
965 }
966
967 fn spawn<F, T>(&mut self, future: F) -> Task<Option<T>>
968 where
969 F: 'static + Future,
970 T: 'static,
971 {
972 let task_id = post_inc(&mut self.next_task_id);
973 let app = self.weak_self.as_ref().unwrap().upgrade().unwrap();
974 let task = {
975 let app = app.clone();
976 self.foreground.spawn(async move {
977 let output = future.await;
978 app.borrow_mut()
979 .handle_future_output(task_id, Box::new(output))
980 .map(|result| *result.downcast::<T>().unwrap())
981 })
982 };
983 Task::new(
984 task_id,
985 task,
986 TaskHandlerMap::Future(self.future_handlers.clone()),
987 self.task_done.clone(),
988 )
989 }
990
991 fn spawn_stream<F, T>(&mut self, mut stream: F) -> Task<Option<T>>
992 where
993 F: 'static + Stream + Unpin,
994 T: 'static,
995 {
996 let task_id = post_inc(&mut self.next_task_id);
997 let app = self.weak_self.as_ref().unwrap().upgrade().unwrap();
998 let task = {
999 let app = app.clone();
1000 self.foreground.spawn(async move {
1001 loop {
1002 match stream.next().await {
1003 Some(item) => {
1004 let mut app = app.borrow_mut();
1005 if app.handle_stream_item(task_id, Box::new(item)) {
1006 break;
1007 }
1008 }
1009 None => {
1010 break;
1011 }
1012 }
1013 }
1014
1015 app.borrow_mut()
1016 .stream_completed(task_id)
1017 .map(|result| *result.downcast::<T>().unwrap())
1018 })
1019 };
1020
1021 Task::new(
1022 task_id,
1023 task,
1024 TaskHandlerMap::Stream(self.stream_handlers.clone()),
1025 self.task_done.clone(),
1026 )
1027 }
1028
1029 fn handle_future_output(
1030 &mut self,
1031 task_id: usize,
1032 output: Box<dyn Any>,
1033 ) -> Option<Box<dyn Any>> {
1034 self.pending_flushes += 1;
1035 let future_callback = self.future_handlers.borrow_mut().remove(&task_id).unwrap();
1036
1037 let mut result = None;
1038
1039 match future_callback {
1040 FutureHandler::Model { model_id, callback } => {
1041 if let Some(mut model) = self.ctx.models.remove(&model_id) {
1042 result = Some(callback(model.as_any_mut(), output, self, model_id));
1043 self.ctx.models.insert(model_id, model);
1044 }
1045 }
1046 FutureHandler::View {
1047 window_id,
1048 view_id,
1049 callback,
1050 } => {
1051 if let Some(mut view) = self
1052 .ctx
1053 .windows
1054 .get_mut(&window_id)
1055 .and_then(|w| w.views.remove(&view_id))
1056 {
1057 result = Some(callback(view.as_mut(), output, self, window_id, view_id));
1058 self.ctx
1059 .windows
1060 .get_mut(&window_id)
1061 .unwrap()
1062 .views
1063 .insert(view_id, view);
1064 }
1065 }
1066 };
1067
1068 self.flush_effects();
1069 self.task_done.notify_all();
1070 result
1071 }
1072
1073 fn handle_stream_item(&mut self, task_id: usize, output: Box<dyn Any>) -> bool {
1074 self.pending_flushes += 1;
1075
1076 let mut handler = self.stream_handlers.borrow_mut().remove(&task_id).unwrap();
1077 let halt = match &mut handler {
1078 StreamHandler::Model {
1079 model_id,
1080 item_callback,
1081 ..
1082 } => {
1083 if let Some(mut model) = self.ctx.models.remove(&model_id) {
1084 let halt = item_callback(model.as_any_mut(), output, self, *model_id);
1085 self.ctx.models.insert(*model_id, model);
1086 self.stream_handlers.borrow_mut().insert(task_id, handler);
1087 halt
1088 } else {
1089 true
1090 }
1091 }
1092 StreamHandler::View {
1093 window_id,
1094 view_id,
1095 item_callback,
1096 ..
1097 } => {
1098 if let Some(mut view) = self
1099 .ctx
1100 .windows
1101 .get_mut(&window_id)
1102 .and_then(|w| w.views.remove(&view_id))
1103 {
1104 let halt = item_callback(view.as_mut(), output, self, *window_id, *view_id);
1105 self.ctx
1106 .windows
1107 .get_mut(&window_id)
1108 .unwrap()
1109 .views
1110 .insert(*view_id, view);
1111 self.stream_handlers.borrow_mut().insert(task_id, handler);
1112 halt
1113 } else {
1114 true
1115 }
1116 }
1117 };
1118
1119 self.flush_effects();
1120 halt
1121 }
1122
1123 fn stream_completed(&mut self, task_id: usize) -> Option<Box<dyn Any>> {
1124 self.pending_flushes += 1;
1125
1126 let stream_handler = self.stream_handlers.borrow_mut().remove(&task_id).unwrap();
1127 let result = match stream_handler {
1128 StreamHandler::Model {
1129 model_id,
1130 done_callback,
1131 ..
1132 } => {
1133 if let Some(mut model) = self.ctx.models.remove(&model_id) {
1134 let result = done_callback(model.as_any_mut(), self, model_id);
1135 self.ctx.models.insert(model_id, model);
1136 Some(result)
1137 } else {
1138 None
1139 }
1140 }
1141 StreamHandler::View {
1142 window_id,
1143 view_id,
1144 done_callback,
1145 ..
1146 } => {
1147 if let Some(mut view) = self
1148 .ctx
1149 .windows
1150 .get_mut(&window_id)
1151 .and_then(|w| w.views.remove(&view_id))
1152 {
1153 let result = done_callback(view.as_mut(), self, window_id, view_id);
1154 self.ctx
1155 .windows
1156 .get_mut(&window_id)
1157 .unwrap()
1158 .views
1159 .insert(view_id, view);
1160 Some(result)
1161 } else {
1162 None
1163 }
1164 }
1165 };
1166
1167 self.flush_effects();
1168 self.task_done.notify_all();
1169 result
1170 }
1171
1172 pub fn finish_pending_tasks(&self) -> impl Future<Output = ()> {
1173 let mut pending_tasks = self
1174 .future_handlers
1175 .borrow()
1176 .keys()
1177 .cloned()
1178 .collect::<HashSet<_>>();
1179 pending_tasks.extend(self.stream_handlers.borrow().keys());
1180
1181 let task_done = self.task_done.clone();
1182 let future_handlers = self.future_handlers.clone();
1183 let stream_handlers = self.stream_handlers.clone();
1184
1185 async move {
1186 // A Condvar expects the condition to be protected by a Mutex, but in this case we know
1187 // that this logic will always run on the main thread.
1188 let mutex = async_std::sync::Mutex::new(());
1189 loop {
1190 {
1191 let future_handlers = future_handlers.borrow();
1192 let stream_handlers = stream_handlers.borrow();
1193 pending_tasks.retain(|task_id| {
1194 future_handlers.contains_key(task_id)
1195 || stream_handlers.contains_key(task_id)
1196 });
1197 if pending_tasks.is_empty() {
1198 break;
1199 }
1200 }
1201 task_done.wait(mutex.lock().await).await;
1202 }
1203 }
1204 }
1205}
1206
1207impl ModelAsRef for MutableAppContext {
1208 fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1209 if let Some(model) = self.ctx.models.get(&handle.model_id) {
1210 model
1211 .as_any()
1212 .downcast_ref()
1213 .expect("Downcast is type safe")
1214 } else {
1215 panic!("Circular model reference");
1216 }
1217 }
1218}
1219
1220impl UpdateModel for MutableAppContext {
1221 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1222 where
1223 T: Entity,
1224 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1225 {
1226 if let Some(mut model) = self.ctx.models.remove(&handle.model_id) {
1227 self.pending_flushes += 1;
1228 let mut ctx = ModelContext::new(self, handle.model_id);
1229 let result = update(
1230 model
1231 .as_any_mut()
1232 .downcast_mut()
1233 .expect("Downcast is type safe"),
1234 &mut ctx,
1235 );
1236 self.ctx.models.insert(handle.model_id, model);
1237 self.flush_effects();
1238 result
1239 } else {
1240 panic!("Circular model update");
1241 }
1242 }
1243}
1244
1245impl ViewAsRef for MutableAppContext {
1246 fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1247 if let Some(window) = self.ctx.windows.get(&handle.window_id) {
1248 if let Some(view) = window.views.get(&handle.view_id) {
1249 view.as_any().downcast_ref().expect("Downcast is type safe")
1250 } else {
1251 panic!("Circular view reference");
1252 }
1253 } else {
1254 panic!("Window does not exist");
1255 }
1256 }
1257}
1258
1259impl UpdateView for MutableAppContext {
1260 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
1261 where
1262 T: View,
1263 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
1264 {
1265 self.pending_flushes += 1;
1266 let mut view = if let Some(window) = self.ctx.windows.get_mut(&handle.window_id) {
1267 if let Some(view) = window.views.remove(&handle.view_id) {
1268 view
1269 } else {
1270 panic!("Circular view update");
1271 }
1272 } else {
1273 panic!("Window does not exist");
1274 };
1275
1276 let mut ctx = ViewContext::new(self, handle.window_id, handle.view_id);
1277 let result = update(
1278 view.as_any_mut()
1279 .downcast_mut()
1280 .expect("Downcast is type safe"),
1281 &mut ctx,
1282 );
1283 self.ctx
1284 .windows
1285 .get_mut(&handle.window_id)
1286 .unwrap()
1287 .views
1288 .insert(handle.view_id, view);
1289 self.flush_effects();
1290 result
1291 }
1292}
1293
1294pub struct AppContext {
1295 models: HashMap<usize, Box<dyn AnyModel>>,
1296 windows: HashMap<usize, Window>,
1297 ref_counts: Arc<Mutex<RefCounts>>,
1298}
1299
1300impl AppContext {
1301 pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
1302 self.windows
1303 .get(&window_id)
1304 .and_then(|window| window.root_view.as_ref().map(|v| v.id()))
1305 }
1306
1307 pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
1308 self.windows
1309 .get(&window_id)
1310 .and_then(|window| window.focused_view)
1311 }
1312
1313 pub fn render_view(&self, window_id: usize, view_id: usize) -> Result<ElementBox> {
1314 self.windows
1315 .get(&window_id)
1316 .and_then(|w| w.views.get(&view_id))
1317 .map(|v| v.render(self))
1318 .ok_or(anyhow!("view not found"))
1319 }
1320
1321 pub fn render_views(&self, window_id: usize) -> Result<HashMap<usize, ElementBox>> {
1322 self.windows
1323 .get(&window_id)
1324 .map(|w| {
1325 w.views
1326 .iter()
1327 .map(|(id, view)| (*id, view.render(self)))
1328 .collect::<HashMap<_, ElementBox>>()
1329 })
1330 .ok_or(anyhow!("window not found"))
1331 }
1332}
1333
1334impl ModelAsRef for AppContext {
1335 fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1336 if let Some(model) = self.models.get(&handle.model_id) {
1337 model
1338 .as_any()
1339 .downcast_ref()
1340 .expect("downcast should be type safe")
1341 } else {
1342 panic!("circular model reference");
1343 }
1344 }
1345}
1346
1347impl ViewAsRef for AppContext {
1348 fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1349 if let Some(window) = self.windows.get(&handle.window_id) {
1350 if let Some(view) = window.views.get(&handle.view_id) {
1351 view.as_any()
1352 .downcast_ref()
1353 .expect("downcast should be type safe")
1354 } else {
1355 panic!("circular view reference");
1356 }
1357 } else {
1358 panic!("window does not exist");
1359 }
1360 }
1361}
1362
1363#[derive(Default)]
1364struct Window {
1365 views: HashMap<usize, Box<dyn AnyView>>,
1366 root_view: Option<AnyViewHandle>,
1367 focused_view: Option<usize>,
1368}
1369
1370#[derive(Default, Clone)]
1371pub struct WindowInvalidation {
1372 pub updated: HashSet<usize>,
1373 pub removed: Vec<usize>,
1374}
1375
1376pub enum Effect {
1377 Event {
1378 entity_id: usize,
1379 payload: Box<dyn Any>,
1380 },
1381 ModelNotification {
1382 model_id: usize,
1383 },
1384 ViewNotification {
1385 window_id: usize,
1386 view_id: usize,
1387 },
1388 Focus {
1389 window_id: usize,
1390 view_id: usize,
1391 },
1392}
1393
1394pub trait AnyModel: Send + Sync {
1395 fn as_any(&self) -> &dyn Any;
1396 fn as_any_mut(&mut self) -> &mut dyn Any;
1397}
1398
1399impl<T> AnyModel for T
1400where
1401 T: Entity,
1402{
1403 fn as_any(&self) -> &dyn Any {
1404 self
1405 }
1406
1407 fn as_any_mut(&mut self) -> &mut dyn Any {
1408 self
1409 }
1410}
1411
1412pub trait AnyView: Send + Sync {
1413 fn as_any(&self) -> &dyn Any;
1414 fn as_any_mut(&mut self) -> &mut dyn Any;
1415 fn ui_name(&self) -> &'static str;
1416 fn render<'a>(&self, app: &AppContext) -> ElementBox;
1417 fn on_focus(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize);
1418 fn on_blur(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize);
1419 fn keymap_context(&self, app: &AppContext) -> keymap::Context;
1420}
1421
1422impl<T> AnyView for T
1423where
1424 T: View,
1425{
1426 fn as_any(&self) -> &dyn Any {
1427 self
1428 }
1429
1430 fn as_any_mut(&mut self) -> &mut dyn Any {
1431 self
1432 }
1433
1434 fn ui_name(&self) -> &'static str {
1435 T::ui_name()
1436 }
1437
1438 fn render<'a>(&self, app: &AppContext) -> ElementBox {
1439 View::render(self, app)
1440 }
1441
1442 fn on_focus(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize) {
1443 let mut ctx = ViewContext::new(app, window_id, view_id);
1444 View::on_focus(self, &mut ctx);
1445 }
1446
1447 fn on_blur(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize) {
1448 let mut ctx = ViewContext::new(app, window_id, view_id);
1449 View::on_blur(self, &mut ctx);
1450 }
1451
1452 fn keymap_context(&self, app: &AppContext) -> keymap::Context {
1453 View::keymap_context(self, app)
1454 }
1455}
1456
1457pub struct ModelContext<'a, T: ?Sized> {
1458 app: &'a mut MutableAppContext,
1459 model_id: usize,
1460 model_type: PhantomData<T>,
1461 halt_stream: bool,
1462}
1463
1464impl<'a, T: Entity> ModelContext<'a, T> {
1465 fn new(app: &'a mut MutableAppContext, model_id: usize) -> Self {
1466 Self {
1467 app,
1468 model_id,
1469 model_type: PhantomData,
1470 halt_stream: false,
1471 }
1472 }
1473
1474 pub fn app(&self) -> &AppContext {
1475 &self.app.ctx
1476 }
1477
1478 pub fn app_mut(&mut self) -> &mut MutableAppContext {
1479 self.app
1480 }
1481
1482 pub fn background_executor(&self) -> &Arc<executor::Background> {
1483 &self.app.background
1484 }
1485
1486 pub fn halt_stream(&mut self) {
1487 self.halt_stream = true;
1488 }
1489
1490 pub fn model_id(&self) -> usize {
1491 self.model_id
1492 }
1493
1494 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
1495 where
1496 S: Entity,
1497 F: FnOnce(&mut ModelContext<S>) -> S,
1498 {
1499 self.app.add_model(build_model)
1500 }
1501
1502 pub fn subscribe<S: Entity, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1503 where
1504 S::Event: 'static,
1505 F: 'static + FnMut(&mut T, &S::Event, &mut ModelContext<T>),
1506 {
1507 self.app
1508 .subscriptions
1509 .entry(handle.model_id)
1510 .or_default()
1511 .push(Subscription::FromModel {
1512 model_id: self.model_id,
1513 callback: Box::new(move |model, payload, app, model_id| {
1514 let model = model.downcast_mut().expect("downcast is type safe");
1515 let payload = payload.downcast_ref().expect("downcast is type safe");
1516 let mut ctx = ModelContext::new(app, model_id);
1517 callback(model, payload, &mut ctx);
1518 }),
1519 });
1520 }
1521
1522 pub fn emit(&mut self, payload: T::Event) {
1523 self.app.pending_effects.push_back(Effect::Event {
1524 entity_id: self.model_id,
1525 payload: Box::new(payload),
1526 });
1527 }
1528
1529 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1530 where
1531 S: Entity,
1532 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ModelContext<T>),
1533 {
1534 self.app
1535 .observations
1536 .entry(handle.model_id)
1537 .or_default()
1538 .push(Observation::FromModel {
1539 model_id: self.model_id,
1540 callback: Box::new(move |model, observed_id, app, model_id| {
1541 let model = model.downcast_mut().expect("downcast is type safe");
1542 let observed = ModelHandle::new(observed_id, &app.ctx.ref_counts);
1543 let mut ctx = ModelContext::new(app, model_id);
1544 callback(model, observed, &mut ctx);
1545 }),
1546 });
1547 }
1548
1549 pub fn notify(&mut self) {
1550 self.app
1551 .pending_effects
1552 .push_back(Effect::ModelNotification {
1553 model_id: self.model_id,
1554 });
1555 }
1556
1557 pub fn spawn<S, F, U>(&mut self, future: S, callback: F) -> Task<Option<U>>
1558 where
1559 S: 'static + Future,
1560 F: 'static + FnOnce(&mut T, S::Output, &mut ModelContext<T>) -> U,
1561 U: 'static,
1562 {
1563 let task = self.app.spawn::<S, U>(future);
1564
1565 self.app.future_handlers.borrow_mut().insert(
1566 task.id,
1567 FutureHandler::Model {
1568 model_id: self.model_id,
1569 callback: Box::new(move |model, output, app, model_id| {
1570 let model = model.downcast_mut().unwrap();
1571 let output = *output.downcast().unwrap();
1572 Box::new(callback(
1573 model,
1574 output,
1575 &mut ModelContext::new(app, model_id),
1576 ))
1577 }),
1578 },
1579 );
1580
1581 task
1582 }
1583
1584 pub fn spawn_stream<S, F, G, U>(
1585 &mut self,
1586 stream: S,
1587 mut item_callback: F,
1588 done_callback: G,
1589 ) -> Task<Option<U>>
1590 where
1591 S: 'static + Stream + Unpin,
1592 F: 'static + FnMut(&mut T, S::Item, &mut ModelContext<T>),
1593 G: 'static + FnOnce(&mut T, &mut ModelContext<T>) -> U,
1594 U: 'static + Any,
1595 {
1596 let task = self.app.spawn_stream(stream);
1597 self.app.stream_handlers.borrow_mut().insert(
1598 task.id,
1599 StreamHandler::Model {
1600 model_id: self.model_id,
1601 item_callback: Box::new(move |model, output, app, model_id| {
1602 let model = model.downcast_mut().unwrap();
1603 let output = *output.downcast().unwrap();
1604 let mut ctx = ModelContext::new(app, model_id);
1605 item_callback(model, output, &mut ctx);
1606 ctx.halt_stream
1607 }),
1608 done_callback: Box::new(
1609 move |model: &mut dyn Any, app: &mut MutableAppContext, model_id| {
1610 let model = model.downcast_mut().unwrap();
1611 let mut ctx = ModelContext::new(app, model_id);
1612 Box::new(done_callback(model, &mut ctx))
1613 },
1614 ),
1615 },
1616 );
1617
1618 task
1619 }
1620}
1621
1622impl<M> ModelAsRef for ModelContext<'_, M> {
1623 fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1624 self.app.model(handle)
1625 }
1626}
1627
1628impl<M> UpdateModel for ModelContext<'_, M> {
1629 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1630 where
1631 T: Entity,
1632 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1633 {
1634 self.app.update_model(handle, update)
1635 }
1636}
1637
1638pub struct ViewContext<'a, T: ?Sized> {
1639 app: &'a mut MutableAppContext,
1640 window_id: usize,
1641 view_id: usize,
1642 view_type: PhantomData<T>,
1643 halt_action_dispatch: bool,
1644 halt_stream: bool,
1645}
1646
1647impl<'a, T: View> ViewContext<'a, T> {
1648 fn new(app: &'a mut MutableAppContext, window_id: usize, view_id: usize) -> Self {
1649 Self {
1650 app,
1651 window_id,
1652 view_id,
1653 view_type: PhantomData,
1654 halt_action_dispatch: true,
1655 halt_stream: false,
1656 }
1657 }
1658
1659 pub fn handle(&self) -> WeakViewHandle<T> {
1660 WeakViewHandle::new(self.window_id, self.view_id)
1661 }
1662
1663 pub fn window_id(&self) -> usize {
1664 self.window_id
1665 }
1666
1667 pub fn app(&self) -> &AppContext {
1668 &self.app.ctx
1669 }
1670
1671 pub fn app_mut(&mut self) -> &mut MutableAppContext {
1672 self.app
1673 }
1674
1675 pub fn background_executor(&self) -> &Arc<executor::Background> {
1676 &self.app.background
1677 }
1678
1679 pub fn focus<S>(&mut self, handle: S)
1680 where
1681 S: Into<AnyViewHandle>,
1682 {
1683 let handle = handle.into();
1684 self.app.pending_effects.push_back(Effect::Focus {
1685 window_id: handle.window_id,
1686 view_id: handle.view_id,
1687 });
1688 }
1689
1690 pub fn focus_self(&mut self) {
1691 self.app.pending_effects.push_back(Effect::Focus {
1692 window_id: self.window_id,
1693 view_id: self.view_id,
1694 });
1695 }
1696
1697 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
1698 where
1699 S: Entity,
1700 F: FnOnce(&mut ModelContext<S>) -> S,
1701 {
1702 self.app.add_model(build_model)
1703 }
1704
1705 pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
1706 where
1707 S: View,
1708 F: FnOnce(&mut ViewContext<S>) -> S,
1709 {
1710 self.app.add_view(self.window_id, build_view)
1711 }
1712
1713 pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
1714 where
1715 S: View,
1716 F: FnOnce(&mut ViewContext<S>) -> Option<S>,
1717 {
1718 self.app.add_option_view(self.window_id, build_view)
1719 }
1720
1721 pub fn subscribe_to_model<E, F>(&mut self, handle: &ModelHandle<E>, mut callback: F)
1722 where
1723 E: Entity,
1724 E::Event: 'static,
1725 F: 'static + FnMut(&mut T, ModelHandle<E>, &E::Event, &mut ViewContext<T>),
1726 {
1727 let emitter_handle = handle.downgrade();
1728 self.app
1729 .subscriptions
1730 .entry(handle.id())
1731 .or_default()
1732 .push(Subscription::FromView {
1733 window_id: self.window_id,
1734 view_id: self.view_id,
1735 callback: Box::new(move |view, payload, app, window_id, view_id| {
1736 if let Some(emitter_handle) = emitter_handle.upgrade(app.downgrade()) {
1737 let model = view.downcast_mut().expect("downcast is type safe");
1738 let payload = payload.downcast_ref().expect("downcast is type safe");
1739 let mut ctx = ViewContext::new(app, window_id, view_id);
1740 callback(model, emitter_handle, payload, &mut ctx);
1741 }
1742 }),
1743 });
1744 }
1745
1746 pub fn subscribe_to_view<V, F>(&mut self, handle: &ViewHandle<V>, mut callback: F)
1747 where
1748 V: View,
1749 V::Event: 'static,
1750 F: 'static + FnMut(&mut T, ViewHandle<V>, &V::Event, &mut ViewContext<T>),
1751 {
1752 let emitter_handle = handle.downgrade();
1753
1754 self.app
1755 .subscriptions
1756 .entry(handle.id())
1757 .or_default()
1758 .push(Subscription::FromView {
1759 window_id: self.window_id,
1760 view_id: self.view_id,
1761 callback: Box::new(move |view, payload, app, window_id, view_id| {
1762 if let Some(emitter_handle) = emitter_handle.upgrade(app.downgrade()) {
1763 let model = view.downcast_mut().expect("downcast is type safe");
1764 let payload = payload.downcast_ref().expect("downcast is type safe");
1765 let mut ctx = ViewContext::new(app, window_id, view_id);
1766 callback(model, emitter_handle, payload, &mut ctx);
1767 }
1768 }),
1769 });
1770 }
1771
1772 pub fn emit(&mut self, payload: T::Event) {
1773 self.app.pending_effects.push_back(Effect::Event {
1774 entity_id: self.view_id,
1775 payload: Box::new(payload),
1776 });
1777 }
1778
1779 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1780 where
1781 S: Entity,
1782 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ViewContext<T>),
1783 {
1784 self.app
1785 .observations
1786 .entry(handle.id())
1787 .or_default()
1788 .push(Observation::FromView {
1789 window_id: self.window_id,
1790 view_id: self.view_id,
1791 callback: Box::new(move |view, observed_id, app, window_id, view_id| {
1792 let view = view.downcast_mut().expect("downcast is type safe");
1793 let observed = ModelHandle::new(observed_id, &app.ctx.ref_counts);
1794 let mut ctx = ViewContext::new(app, window_id, view_id);
1795 callback(view, observed, &mut ctx);
1796 }),
1797 });
1798 }
1799
1800 pub fn notify(&mut self) {
1801 self.app
1802 .pending_effects
1803 .push_back(Effect::ViewNotification {
1804 window_id: self.window_id,
1805 view_id: self.view_id,
1806 });
1807 }
1808
1809 pub fn propagate_action(&mut self) {
1810 self.halt_action_dispatch = false;
1811 }
1812
1813 pub fn halt_stream(&mut self) {
1814 self.halt_stream = true;
1815 }
1816
1817 pub fn spawn<S, F, U>(&mut self, future: S, callback: F) -> Task<Option<U>>
1818 where
1819 S: 'static + Future,
1820 F: 'static + FnOnce(&mut T, S::Output, &mut ViewContext<T>) -> U,
1821 U: 'static,
1822 {
1823 let task = self.app.spawn(future);
1824
1825 self.app.future_handlers.borrow_mut().insert(
1826 task.id,
1827 FutureHandler::View {
1828 window_id: self.window_id,
1829 view_id: self.view_id,
1830 callback: Box::new(move |view, output, app, window_id, view_id| {
1831 let view = view.as_any_mut().downcast_mut().unwrap();
1832 let output = *output.downcast().unwrap();
1833 Box::new(callback(
1834 view,
1835 output,
1836 &mut ViewContext::new(app, window_id, view_id),
1837 ))
1838 }),
1839 },
1840 );
1841
1842 task
1843 }
1844
1845 pub fn spawn_stream<S, F, G, U>(
1846 &mut self,
1847 stream: S,
1848 mut item_callback: F,
1849 done_callback: G,
1850 ) -> Task<Option<U>>
1851 where
1852 S: 'static + Stream + Unpin,
1853 F: 'static + FnMut(&mut T, S::Item, &mut ViewContext<T>),
1854 G: 'static + FnOnce(&mut T, &mut ViewContext<T>) -> U,
1855 U: 'static + Any,
1856 {
1857 let task = self.app.spawn_stream(stream);
1858 self.app.stream_handlers.borrow_mut().insert(
1859 task.id,
1860 StreamHandler::View {
1861 window_id: self.window_id,
1862 view_id: self.view_id,
1863 item_callback: Box::new(move |view, output, app, window_id, view_id| {
1864 let view = view.as_any_mut().downcast_mut().unwrap();
1865 let output = *output.downcast().unwrap();
1866 let mut ctx = ViewContext::new(app, window_id, view_id);
1867 item_callback(view, output, &mut ctx);
1868 ctx.halt_stream
1869 }),
1870 done_callback: Box::new(move |view, app, window_id, view_id| {
1871 let view = view.as_any_mut().downcast_mut().unwrap();
1872 let mut ctx = ViewContext::new(app, window_id, view_id);
1873 Box::new(done_callback(view, &mut ctx))
1874 }),
1875 },
1876 );
1877 task
1878 }
1879}
1880
1881impl<V> ModelAsRef for ViewContext<'_, V> {
1882 fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1883 self.app.model(handle)
1884 }
1885}
1886
1887impl<V: View> UpdateModel for ViewContext<'_, V> {
1888 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1889 where
1890 T: Entity,
1891 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1892 {
1893 self.app.update_model(handle, update)
1894 }
1895}
1896
1897impl<V: View> ViewAsRef for ViewContext<'_, V> {
1898 fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1899 self.app.view(handle)
1900 }
1901}
1902
1903impl<V: View> UpdateView for ViewContext<'_, V> {
1904 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
1905 where
1906 T: View,
1907 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
1908 {
1909 self.app.update_view(handle, update)
1910 }
1911}
1912
1913pub trait Handle<T> {
1914 fn id(&self) -> usize;
1915 fn location(&self) -> EntityLocation;
1916}
1917
1918#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
1919pub enum EntityLocation {
1920 Model(usize),
1921 View(usize, usize),
1922}
1923
1924pub struct ModelHandle<T> {
1925 model_id: usize,
1926 model_type: PhantomData<T>,
1927 ref_counts: Weak<Mutex<RefCounts>>,
1928}
1929
1930impl<T: Entity> ModelHandle<T> {
1931 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
1932 ref_counts.lock().inc(model_id);
1933 Self {
1934 model_id,
1935 model_type: PhantomData,
1936 ref_counts: Arc::downgrade(ref_counts),
1937 }
1938 }
1939
1940 fn downgrade(&self) -> WeakModelHandle<T> {
1941 WeakModelHandle::new(self.model_id)
1942 }
1943
1944 pub fn id(&self) -> usize {
1945 self.model_id
1946 }
1947
1948 pub fn as_ref<'a, A: ModelAsRef>(&self, app: &'a A) -> &'a T {
1949 app.model(self)
1950 }
1951
1952 pub fn read<'a, S, F>(&self, app: &'a App, read: F) -> S
1953 where
1954 F: FnOnce(&T, &AppContext) -> S,
1955 {
1956 app.read_model(self, read)
1957 }
1958
1959 pub fn update<A, F, S>(&self, app: &mut A, update: F) -> S
1960 where
1961 A: UpdateModel,
1962 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1963 {
1964 app.update_model(self, update)
1965 }
1966}
1967
1968impl<T> Clone for ModelHandle<T> {
1969 fn clone(&self) -> Self {
1970 if let Some(ref_counts) = self.ref_counts.upgrade() {
1971 ref_counts.lock().inc(self.model_id);
1972 }
1973
1974 Self {
1975 model_id: self.model_id,
1976 model_type: PhantomData,
1977 ref_counts: self.ref_counts.clone(),
1978 }
1979 }
1980}
1981
1982impl<T> PartialEq for ModelHandle<T> {
1983 fn eq(&self, other: &Self) -> bool {
1984 self.model_id == other.model_id
1985 }
1986}
1987
1988impl<T> Eq for ModelHandle<T> {}
1989
1990impl<T> Hash for ModelHandle<T> {
1991 fn hash<H: Hasher>(&self, state: &mut H) {
1992 self.model_id.hash(state);
1993 }
1994}
1995
1996impl<T> std::borrow::Borrow<usize> for ModelHandle<T> {
1997 fn borrow(&self) -> &usize {
1998 &self.model_id
1999 }
2000}
2001
2002impl<T> Debug for ModelHandle<T> {
2003 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2004 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
2005 .field(&self.model_id)
2006 .finish()
2007 }
2008}
2009
2010unsafe impl<T> Send for ModelHandle<T> {}
2011unsafe impl<T> Sync for ModelHandle<T> {}
2012
2013impl<T> Drop for ModelHandle<T> {
2014 fn drop(&mut self) {
2015 if let Some(ref_counts) = self.ref_counts.upgrade() {
2016 ref_counts.lock().dec_model(self.model_id);
2017 }
2018 }
2019}
2020
2021impl<T> Handle<T> for ModelHandle<T> {
2022 fn id(&self) -> usize {
2023 self.model_id
2024 }
2025
2026 fn location(&self) -> EntityLocation {
2027 EntityLocation::Model(self.model_id)
2028 }
2029}
2030
2031pub struct WeakModelHandle<T> {
2032 model_id: usize,
2033 model_type: PhantomData<T>,
2034}
2035
2036impl<T: Entity> WeakModelHandle<T> {
2037 fn new(model_id: usize) -> Self {
2038 Self {
2039 model_id,
2040 model_type: PhantomData,
2041 }
2042 }
2043
2044 pub fn upgrade(&self, app: &AppContext) -> Option<ModelHandle<T>> {
2045 if app.models.contains_key(&self.model_id) {
2046 Some(ModelHandle::new(self.model_id, &app.ref_counts))
2047 } else {
2048 None
2049 }
2050 }
2051}
2052
2053pub struct ViewHandle<T> {
2054 window_id: usize,
2055 view_id: usize,
2056 view_type: PhantomData<T>,
2057 ref_counts: Weak<Mutex<RefCounts>>,
2058}
2059
2060impl<T: View> ViewHandle<T> {
2061 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
2062 ref_counts.lock().inc(view_id);
2063 Self {
2064 window_id,
2065 view_id,
2066 view_type: PhantomData,
2067 ref_counts: Arc::downgrade(ref_counts),
2068 }
2069 }
2070
2071 fn downgrade(&self) -> WeakViewHandle<T> {
2072 WeakViewHandle::new(self.window_id, self.view_id)
2073 }
2074
2075 pub fn window_id(&self) -> usize {
2076 self.window_id
2077 }
2078
2079 pub fn id(&self) -> usize {
2080 self.view_id
2081 }
2082
2083 pub fn as_ref<'a, A: ViewAsRef>(&self, app: &'a A) -> &'a T {
2084 app.view(self)
2085 }
2086
2087 pub fn read<'a, F, S>(&self, app: &'a App, read: F) -> S
2088 where
2089 F: FnOnce(&T, &AppContext) -> S,
2090 {
2091 app.read_view(self, read)
2092 }
2093
2094 pub fn update<A, F, S>(&self, app: &mut A, update: F) -> S
2095 where
2096 A: UpdateView,
2097 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
2098 {
2099 app.update_view(self, update)
2100 }
2101
2102 pub fn is_focused(&self, app: &AppContext) -> bool {
2103 app.focused_view_id(self.window_id)
2104 .map_or(false, |focused_id| focused_id == self.view_id)
2105 }
2106}
2107
2108impl<T> Clone for ViewHandle<T> {
2109 fn clone(&self) -> Self {
2110 if let Some(ref_counts) = self.ref_counts.upgrade() {
2111 ref_counts.lock().inc(self.view_id);
2112 }
2113
2114 Self {
2115 window_id: self.window_id,
2116 view_id: self.view_id,
2117 view_type: PhantomData,
2118 ref_counts: self.ref_counts.clone(),
2119 }
2120 }
2121}
2122
2123impl<T> PartialEq for ViewHandle<T> {
2124 fn eq(&self, other: &Self) -> bool {
2125 self.window_id == other.window_id && self.view_id == other.view_id
2126 }
2127}
2128
2129impl<T> Eq for ViewHandle<T> {}
2130
2131impl<T> Debug for ViewHandle<T> {
2132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2133 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
2134 .field("window_id", &self.window_id)
2135 .field("view_id", &self.view_id)
2136 .finish()
2137 }
2138}
2139
2140impl<T> Drop for ViewHandle<T> {
2141 fn drop(&mut self) {
2142 if let Some(ref_counts) = self.ref_counts.upgrade() {
2143 ref_counts.lock().dec_view(self.window_id, self.view_id);
2144 }
2145 }
2146}
2147
2148impl<T> Handle<T> for ViewHandle<T> {
2149 fn id(&self) -> usize {
2150 self.view_id
2151 }
2152
2153 fn location(&self) -> EntityLocation {
2154 EntityLocation::View(self.window_id, self.view_id)
2155 }
2156}
2157
2158#[derive(Clone)]
2159pub struct AnyViewHandle {
2160 window_id: usize,
2161 view_id: usize,
2162 view_type: TypeId,
2163 ref_counts: Weak<Mutex<RefCounts>>,
2164}
2165
2166impl AnyViewHandle {
2167 pub fn id(&self) -> usize {
2168 self.view_id
2169 }
2170
2171 pub fn is<T: 'static>(&self) -> bool {
2172 TypeId::of::<T>() == self.view_type
2173 }
2174
2175 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
2176 if self.is::<T>() {
2177 if let Some(ref_counts) = self.ref_counts.upgrade() {
2178 return Some(ViewHandle::new(self.window_id, self.view_id, &ref_counts));
2179 }
2180 }
2181 None
2182 }
2183}
2184
2185impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
2186 fn from(handle: &ViewHandle<T>) -> Self {
2187 if let Some(ref_counts) = handle.ref_counts.upgrade() {
2188 ref_counts.lock().inc(handle.view_id);
2189 }
2190 AnyViewHandle {
2191 window_id: handle.window_id,
2192 view_id: handle.view_id,
2193 view_type: TypeId::of::<T>(),
2194 ref_counts: handle.ref_counts.clone(),
2195 }
2196 }
2197}
2198
2199impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
2200 fn from(handle: ViewHandle<T>) -> Self {
2201 (&handle).into()
2202 }
2203}
2204
2205pub struct WeakViewHandle<T> {
2206 window_id: usize,
2207 view_id: usize,
2208 view_type: PhantomData<T>,
2209}
2210
2211impl<T: View> WeakViewHandle<T> {
2212 fn new(window_id: usize, view_id: usize) -> Self {
2213 Self {
2214 window_id,
2215 view_id,
2216 view_type: PhantomData,
2217 }
2218 }
2219
2220 pub fn upgrade(&self, app: &AppContext) -> Option<ViewHandle<T>> {
2221 if app
2222 .windows
2223 .get(&self.window_id)
2224 .and_then(|w| w.views.get(&self.view_id))
2225 .is_some()
2226 {
2227 Some(ViewHandle::new(
2228 self.window_id,
2229 self.view_id,
2230 &app.ref_counts,
2231 ))
2232 } else {
2233 None
2234 }
2235 }
2236}
2237
2238impl<T> Clone for WeakViewHandle<T> {
2239 fn clone(&self) -> Self {
2240 Self {
2241 window_id: self.window_id,
2242 view_id: self.view_id,
2243 view_type: PhantomData,
2244 }
2245 }
2246}
2247
2248#[derive(Default)]
2249struct RefCounts {
2250 counts: HashMap<usize, usize>,
2251 dropped_models: HashSet<usize>,
2252 dropped_views: HashSet<(usize, usize)>,
2253}
2254
2255impl RefCounts {
2256 fn inc(&mut self, model_id: usize) {
2257 *self.counts.entry(model_id).or_insert(0) += 1;
2258 }
2259
2260 fn dec_model(&mut self, model_id: usize) {
2261 if let Some(count) = self.counts.get_mut(&model_id) {
2262 *count -= 1;
2263 if *count == 0 {
2264 self.counts.remove(&model_id);
2265 self.dropped_models.insert(model_id);
2266 }
2267 } else {
2268 panic!("Expected ref count to be positive")
2269 }
2270 }
2271
2272 fn dec_view(&mut self, window_id: usize, view_id: usize) {
2273 if let Some(count) = self.counts.get_mut(&view_id) {
2274 *count -= 1;
2275 if *count == 0 {
2276 self.counts.remove(&view_id);
2277 self.dropped_views.insert((window_id, view_id));
2278 }
2279 } else {
2280 panic!("Expected ref count to be positive")
2281 }
2282 }
2283
2284 fn take_dropped(&mut self) -> (HashSet<usize>, HashSet<(usize, usize)>) {
2285 let mut dropped_models = HashSet::new();
2286 let mut dropped_views = HashSet::new();
2287 std::mem::swap(&mut self.dropped_models, &mut dropped_models);
2288 std::mem::swap(&mut self.dropped_views, &mut dropped_views);
2289 (dropped_models, dropped_views)
2290 }
2291}
2292
2293enum Subscription {
2294 FromModel {
2295 model_id: usize,
2296 callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize)>,
2297 },
2298 FromView {
2299 window_id: usize,
2300 view_id: usize,
2301 callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize, usize)>,
2302 },
2303}
2304
2305enum Observation {
2306 FromModel {
2307 model_id: usize,
2308 callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize)>,
2309 },
2310 FromView {
2311 window_id: usize,
2312 view_id: usize,
2313 callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize, usize)>,
2314 },
2315}
2316
2317enum FutureHandler {
2318 Model {
2319 model_id: usize,
2320 callback: Box<
2321 dyn FnOnce(&mut dyn Any, Box<dyn Any>, &mut MutableAppContext, usize) -> Box<dyn Any>,
2322 >,
2323 },
2324 View {
2325 window_id: usize,
2326 view_id: usize,
2327 callback: Box<
2328 dyn FnOnce(
2329 &mut dyn AnyView,
2330 Box<dyn Any>,
2331 &mut MutableAppContext,
2332 usize,
2333 usize,
2334 ) -> Box<dyn Any>,
2335 >,
2336 },
2337}
2338
2339enum StreamHandler {
2340 Model {
2341 model_id: usize,
2342 item_callback:
2343 Box<dyn FnMut(&mut dyn Any, Box<dyn Any>, &mut MutableAppContext, usize) -> bool>,
2344 done_callback: Box<dyn FnOnce(&mut dyn Any, &mut MutableAppContext, usize) -> Box<dyn Any>>,
2345 },
2346 View {
2347 window_id: usize,
2348 view_id: usize,
2349 item_callback: Box<
2350 dyn FnMut(&mut dyn AnyView, Box<dyn Any>, &mut MutableAppContext, usize, usize) -> bool,
2351 >,
2352 done_callback:
2353 Box<dyn FnOnce(&mut dyn AnyView, &mut MutableAppContext, usize, usize) -> Box<dyn Any>>,
2354 },
2355}
2356
2357#[must_use]
2358pub struct Task<T> {
2359 id: usize,
2360 task: Option<executor::Task<T>>,
2361 handler_map: TaskHandlerMap,
2362 task_done: Arc<Condvar>,
2363}
2364
2365enum TaskHandlerMap {
2366 Detached,
2367 Future(Rc<RefCell<HashMap<usize, FutureHandler>>>),
2368 Stream(Rc<RefCell<HashMap<usize, StreamHandler>>>),
2369}
2370
2371impl<T> Task<T> {
2372 fn new(
2373 id: usize,
2374 task: executor::Task<T>,
2375 handler_map: TaskHandlerMap,
2376 task_done: Arc<Condvar>,
2377 ) -> Self {
2378 Self {
2379 id,
2380 task: Some(task),
2381 handler_map,
2382 task_done,
2383 }
2384 }
2385
2386 pub fn detach(mut self) {
2387 self.handler_map = TaskHandlerMap::Detached;
2388 self.task.take().unwrap().detach();
2389 }
2390
2391 pub async fn cancel(mut self) -> Option<T> {
2392 let task = self.task.take().unwrap();
2393 task.cancel().await
2394 }
2395}
2396
2397impl<T> Future for Task<T> {
2398 type Output = T;
2399
2400 fn poll(
2401 self: std::pin::Pin<&mut Self>,
2402 ctx: &mut std::task::Context<'_>,
2403 ) -> std::task::Poll<Self::Output> {
2404 let task = unsafe { self.map_unchecked_mut(|task| task.task.as_mut().unwrap()) };
2405 task.poll(ctx)
2406 }
2407}
2408
2409impl<T> Drop for Task<T> {
2410 fn drop(self: &mut Self) {
2411 match &self.handler_map {
2412 TaskHandlerMap::Detached => {
2413 return;
2414 }
2415 TaskHandlerMap::Future(map) => {
2416 map.borrow_mut().remove(&self.id);
2417 }
2418 TaskHandlerMap::Stream(map) => {
2419 map.borrow_mut().remove(&self.id);
2420 }
2421 }
2422 self.task_done.notify_all();
2423 }
2424}
2425
2426#[cfg(test)]
2427mod tests {
2428 use super::*;
2429 use crate::elements::*;
2430
2431 #[test]
2432 fn test_model_handles() {
2433 struct Model {
2434 other: Option<ModelHandle<Model>>,
2435 events: Vec<String>,
2436 }
2437
2438 impl Entity for Model {
2439 type Event = usize;
2440 }
2441
2442 impl Model {
2443 fn new(other: Option<ModelHandle<Self>>, ctx: &mut ModelContext<Self>) -> Self {
2444 if let Some(other) = other.as_ref() {
2445 ctx.observe(other, |me, _, _| {
2446 me.events.push("notified".into());
2447 });
2448 ctx.subscribe(other, |me, event, _| {
2449 me.events.push(format!("observed event {}", event));
2450 });
2451 }
2452
2453 Self {
2454 other,
2455 events: Vec::new(),
2456 }
2457 }
2458 }
2459
2460 App::test((), |mut app| async move {
2461 let app = &mut app;
2462
2463 let handle_1 = app.add_model(|ctx| Model::new(None, ctx));
2464 let handle_2 = app.add_model(|ctx| Model::new(Some(handle_1.clone()), ctx));
2465 assert_eq!(app.0.borrow().ctx.models.len(), 2);
2466
2467 handle_1.update(app, |model, ctx| {
2468 model.events.push("updated".into());
2469 ctx.emit(1);
2470 ctx.notify();
2471 ctx.emit(2);
2472 });
2473 handle_1.read(app, |model, _| {
2474 assert_eq!(model.events, vec!["updated".to_string()]);
2475 });
2476 handle_2.read(app, |model, _| {
2477 assert_eq!(
2478 model.events,
2479 vec![
2480 "observed event 1".to_string(),
2481 "notified".to_string(),
2482 "observed event 2".to_string(),
2483 ]
2484 );
2485 });
2486
2487 handle_2.update(app, |model, _| {
2488 drop(handle_1);
2489 model.other.take();
2490 });
2491
2492 let app_state = app.0.borrow();
2493 assert_eq!(app_state.ctx.models.len(), 1);
2494 assert!(app_state.subscriptions.is_empty());
2495 assert!(app_state.observations.is_empty());
2496 })
2497 }
2498
2499 #[test]
2500 fn test_subscribe_and_emit_from_model() {
2501 #[derive(Default)]
2502 struct Model {
2503 events: Vec<usize>,
2504 }
2505
2506 impl Entity for Model {
2507 type Event = usize;
2508 }
2509
2510 App::test((), |mut app| async move {
2511 let app = &mut app;
2512 let handle_1 = app.add_model(|_| Model::default());
2513 let handle_2 = app.add_model(|_| Model::default());
2514 let handle_2b = handle_2.clone();
2515
2516 handle_1.update(app, |_, c| {
2517 c.subscribe(&handle_2, move |model: &mut Model, event, c| {
2518 model.events.push(*event);
2519
2520 c.subscribe(&handle_2b, |model, event, _| {
2521 model.events.push(*event * 2);
2522 });
2523 });
2524 });
2525
2526 handle_2.update(app, |_, c| c.emit(7));
2527 handle_1.read(app, |model, _| assert_eq!(model.events, vec![7]));
2528
2529 handle_2.update(app, |_, c| c.emit(5));
2530 handle_1.read(app, |model, _| assert_eq!(model.events, vec![7, 10, 5]));
2531 })
2532 }
2533
2534 #[test]
2535 fn test_observe_and_notify_from_model() {
2536 #[derive(Default)]
2537 struct Model {
2538 count: usize,
2539 events: Vec<usize>,
2540 }
2541
2542 impl Entity for Model {
2543 type Event = ();
2544 }
2545
2546 App::test((), |mut app| async move {
2547 let app = &mut app;
2548 let handle_1 = app.add_model(|_| Model::default());
2549 let handle_2 = app.add_model(|_| Model::default());
2550 let handle_2b = handle_2.clone();
2551
2552 handle_1.update(app, |_, c| {
2553 c.observe(&handle_2, move |model, observed, c| {
2554 model.events.push(observed.as_ref(c).count);
2555 c.observe(&handle_2b, |model, observed, c| {
2556 model.events.push(observed.as_ref(c).count * 2);
2557 });
2558 });
2559 });
2560
2561 handle_2.update(app, |model, c| {
2562 model.count = 7;
2563 c.notify()
2564 });
2565 handle_1.read(app, |model, _| assert_eq!(model.events, vec![7]));
2566
2567 handle_2.update(app, |model, c| {
2568 model.count = 5;
2569 c.notify()
2570 });
2571 handle_1.read(app, |model, _| assert_eq!(model.events, vec![7, 10, 5]))
2572 })
2573 }
2574
2575 #[test]
2576 fn test_spawn_from_model() {
2577 #[derive(Default)]
2578 struct Model {
2579 count: usize,
2580 }
2581
2582 impl Entity for Model {
2583 type Event = ();
2584 }
2585
2586 App::test((), |mut app| async move {
2587 let handle = app.add_model(|_| Model::default());
2588 handle
2589 .update(&mut app, |_, c| {
2590 c.spawn(async { 7 }, |model, output, _| {
2591 model.count = output;
2592 })
2593 })
2594 .await;
2595 handle.read(&app, |model, _| assert_eq!(model.count, 7));
2596
2597 handle
2598 .update(&mut app, |_, c| {
2599 c.spawn(async { 14 }, |model, output, _| {
2600 model.count = output;
2601 })
2602 })
2603 .await;
2604 handle.read(&app, |model, _| assert_eq!(model.count, 14));
2605 });
2606 }
2607
2608 #[test]
2609 fn test_spawn_stream_local_from_model() {
2610 #[derive(Default)]
2611 struct Model {
2612 events: Vec<Option<usize>>,
2613 }
2614
2615 impl Entity for Model {
2616 type Event = ();
2617 }
2618
2619 App::test((), |mut app| async move {
2620 let handle = app.add_model(|_| Model::default());
2621 handle
2622 .update(&mut app, |_, c| {
2623 c.spawn_stream(
2624 smol::stream::iter(vec![1, 2, 3]),
2625 |model, output, _| {
2626 model.events.push(Some(output));
2627 },
2628 |model, _| {
2629 model.events.push(None);
2630 },
2631 )
2632 })
2633 .await;
2634
2635 handle.read(&app, |model, _| {
2636 assert_eq!(model.events, [Some(1), Some(2), Some(3), None])
2637 });
2638 })
2639 }
2640
2641 #[test]
2642 fn test_view_handles() {
2643 struct View {
2644 other: Option<ViewHandle<View>>,
2645 events: Vec<String>,
2646 }
2647
2648 impl Entity for View {
2649 type Event = usize;
2650 }
2651
2652 impl super::View for View {
2653 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2654 Empty::new().boxed()
2655 }
2656
2657 fn ui_name() -> &'static str {
2658 "View"
2659 }
2660 }
2661
2662 impl View {
2663 fn new(other: Option<ViewHandle<View>>, ctx: &mut ViewContext<Self>) -> Self {
2664 if let Some(other) = other.as_ref() {
2665 ctx.subscribe_to_view(other, |me, _, event, _| {
2666 me.events.push(format!("observed event {}", event));
2667 });
2668 }
2669 Self {
2670 other,
2671 events: Vec::new(),
2672 }
2673 }
2674 }
2675
2676 App::test((), |mut app| async move {
2677 let app = &mut app;
2678 let (window_id, _) = app.add_window(|ctx| View::new(None, ctx));
2679 let handle_1 = app.add_view(window_id, |ctx| View::new(None, ctx));
2680 let handle_2 = app.add_view(window_id, |ctx| View::new(Some(handle_1.clone()), ctx));
2681 assert_eq!(app.0.borrow().ctx.windows[&window_id].views.len(), 3);
2682
2683 handle_1.update(app, |view, ctx| {
2684 view.events.push("updated".into());
2685 ctx.emit(1);
2686 ctx.emit(2);
2687 });
2688 handle_1.read(app, |view, _| {
2689 assert_eq!(view.events, vec!["updated".to_string()]);
2690 });
2691 handle_2.read(app, |view, _| {
2692 assert_eq!(
2693 view.events,
2694 vec![
2695 "observed event 1".to_string(),
2696 "observed event 2".to_string(),
2697 ]
2698 );
2699 });
2700
2701 handle_2.update(app, |view, _| {
2702 drop(handle_1);
2703 view.other.take();
2704 });
2705
2706 let app_state = app.0.borrow();
2707 assert_eq!(app_state.ctx.windows[&window_id].views.len(), 2);
2708 assert!(app_state.subscriptions.is_empty());
2709 assert!(app_state.observations.is_empty());
2710 })
2711 }
2712
2713 #[test]
2714 fn test_subscribe_and_emit_from_view() {
2715 #[derive(Default)]
2716 struct View {
2717 events: Vec<usize>,
2718 }
2719
2720 impl Entity for View {
2721 type Event = usize;
2722 }
2723
2724 impl super::View for View {
2725 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2726 Empty::new().boxed()
2727 }
2728
2729 fn ui_name() -> &'static str {
2730 "View"
2731 }
2732 }
2733
2734 struct Model;
2735
2736 impl Entity for Model {
2737 type Event = usize;
2738 }
2739
2740 App::test((), |mut app| async move {
2741 let app = &mut app;
2742 let (window_id, handle_1) = app.add_window(|_| View::default());
2743 let handle_2 = app.add_view(window_id, |_| View::default());
2744 let handle_2b = handle_2.clone();
2745 let handle_3 = app.add_model(|_| Model);
2746
2747 handle_1.update(app, |_, c| {
2748 c.subscribe_to_view(&handle_2, move |me, _, event, c| {
2749 me.events.push(*event);
2750
2751 c.subscribe_to_view(&handle_2b, |me, _, event, _| {
2752 me.events.push(*event * 2);
2753 });
2754 });
2755
2756 c.subscribe_to_model(&handle_3, |me, _, event, _| {
2757 me.events.push(*event);
2758 })
2759 });
2760
2761 handle_2.update(app, |_, c| c.emit(7));
2762 handle_1.read(app, |view, _| assert_eq!(view.events, vec![7]));
2763
2764 handle_2.update(app, |_, c| c.emit(5));
2765 handle_1.read(app, |view, _| assert_eq!(view.events, vec![7, 10, 5]));
2766
2767 handle_3.update(app, |_, c| c.emit(9));
2768 handle_1.read(app, |view, _| assert_eq!(view.events, vec![7, 10, 5, 9]));
2769 })
2770 }
2771
2772 #[test]
2773 fn test_dropping_subscribers() {
2774 struct View;
2775
2776 impl Entity for View {
2777 type Event = ();
2778 }
2779
2780 impl super::View for View {
2781 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2782 Empty::new().boxed()
2783 }
2784
2785 fn ui_name() -> &'static str {
2786 "View"
2787 }
2788 }
2789
2790 struct Model;
2791
2792 impl Entity for Model {
2793 type Event = ();
2794 }
2795
2796 App::test((), |mut app| async move {
2797 let app = &mut app;
2798
2799 let (window_id, _) = app.add_window(|_| View);
2800 let observing_view = app.add_view(window_id, |_| View);
2801 let emitting_view = app.add_view(window_id, |_| View);
2802 let observing_model = app.add_model(|_| Model);
2803 let observed_model = app.add_model(|_| Model);
2804
2805 observing_view.update(app, |_, ctx| {
2806 ctx.subscribe_to_view(&emitting_view, |_, _, _, _| {});
2807 ctx.subscribe_to_model(&observed_model, |_, _, _, _| {});
2808 });
2809 observing_model.update(app, |_, ctx| {
2810 ctx.subscribe(&observed_model, |_, _, _| {});
2811 });
2812
2813 app.update(|_| {
2814 drop(observing_view);
2815 drop(observing_model);
2816 });
2817
2818 emitting_view.update(app, |_, ctx| ctx.emit(()));
2819 observed_model.update(app, |_, ctx| ctx.emit(()));
2820 })
2821 }
2822
2823 #[test]
2824 fn test_observe_and_notify_from_view() {
2825 #[derive(Default)]
2826 struct View {
2827 events: Vec<usize>,
2828 }
2829
2830 impl Entity for View {
2831 type Event = usize;
2832 }
2833
2834 impl super::View for View {
2835 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2836 Empty::new().boxed()
2837 }
2838
2839 fn ui_name() -> &'static str {
2840 "View"
2841 }
2842 }
2843
2844 #[derive(Default)]
2845 struct Model {
2846 count: usize,
2847 }
2848
2849 impl Entity for Model {
2850 type Event = ();
2851 }
2852
2853 App::test((), |mut app| async move {
2854 let app = &mut app;
2855 let (_, view) = app.add_window(|_| View::default());
2856 let model = app.add_model(|_| Model::default());
2857
2858 view.update(app, |_, c| {
2859 c.observe(&model, |me, observed, c| {
2860 me.events.push(observed.as_ref(c).count)
2861 });
2862 });
2863
2864 model.update(app, |model, c| {
2865 model.count = 11;
2866 c.notify();
2867 });
2868 view.read(app, |view, _| assert_eq!(view.events, vec![11]));
2869 })
2870 }
2871
2872 #[test]
2873 fn test_dropping_observers() {
2874 struct View;
2875
2876 impl Entity for View {
2877 type Event = ();
2878 }
2879
2880 impl super::View for View {
2881 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2882 Empty::new().boxed()
2883 }
2884
2885 fn ui_name() -> &'static str {
2886 "View"
2887 }
2888 }
2889
2890 struct Model;
2891
2892 impl Entity for Model {
2893 type Event = ();
2894 }
2895
2896 App::test((), |mut app| async move {
2897 let app = &mut app;
2898
2899 let (window_id, _) = app.add_window(|_| View);
2900 let observing_view = app.add_view(window_id, |_| View);
2901 let observing_model = app.add_model(|_| Model);
2902 let observed_model = app.add_model(|_| Model);
2903
2904 observing_view.update(app, |_, ctx| {
2905 ctx.observe(&observed_model, |_, _, _| {});
2906 });
2907 observing_model.update(app, |_, ctx| {
2908 ctx.observe(&observed_model, |_, _, _| {});
2909 });
2910
2911 app.update(|_| {
2912 drop(observing_view);
2913 drop(observing_model);
2914 });
2915
2916 observed_model.update(app, |_, ctx| ctx.notify());
2917 })
2918 }
2919
2920 #[test]
2921 fn test_focus() {
2922 #[derive(Default)]
2923 struct View {
2924 events: Vec<String>,
2925 }
2926
2927 impl Entity for View {
2928 type Event = String;
2929 }
2930
2931 impl super::View for View {
2932 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2933 Empty::new().boxed()
2934 }
2935
2936 fn ui_name() -> &'static str {
2937 "View"
2938 }
2939
2940 fn on_focus(&mut self, ctx: &mut ViewContext<Self>) {
2941 self.events.push("self focused".into());
2942 ctx.emit("focused".into());
2943 }
2944
2945 fn on_blur(&mut self, ctx: &mut ViewContext<Self>) {
2946 self.events.push("self blurred".into());
2947 ctx.emit("blurred".into());
2948 }
2949 }
2950
2951 App::test((), |mut app| async move {
2952 let app = &mut app;
2953 let (window_id, view_1) = app.add_window(|_| View::default());
2954 let view_2 = app.add_view(window_id, |_| View::default());
2955
2956 view_1.update(app, |_, ctx| {
2957 ctx.subscribe_to_view(&view_2, |view_1, _, event, _| {
2958 view_1.events.push(format!("view 2 {}", event));
2959 });
2960 ctx.focus(&view_2);
2961 });
2962
2963 view_1.update(app, |_, ctx| {
2964 ctx.focus(&view_1);
2965 });
2966
2967 view_1.read(app, |view_1, _| {
2968 assert_eq!(
2969 view_1.events,
2970 [
2971 "self focused".to_string(),
2972 "self blurred".to_string(),
2973 "view 2 focused".to_string(),
2974 "self focused".to_string(),
2975 "view 2 blurred".to_string(),
2976 ],
2977 );
2978 });
2979 })
2980 }
2981
2982 #[test]
2983 fn test_spawn_from_view() {
2984 #[derive(Default)]
2985 struct View {
2986 count: usize,
2987 }
2988
2989 impl Entity for View {
2990 type Event = ();
2991 }
2992
2993 impl super::View for View {
2994 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2995 Empty::new().boxed()
2996 }
2997
2998 fn ui_name() -> &'static str {
2999 "View"
3000 }
3001 }
3002
3003 App::test((), |mut app| async move {
3004 let (_, handle) = app.add_window(|_| View::default());
3005 handle
3006 .update(&mut app, |_, c| {
3007 c.spawn(async { 7 }, |me, output, _| {
3008 me.count = output;
3009 })
3010 })
3011 .await;
3012 handle.read(&app, |view, _| assert_eq!(view.count, 7));
3013 handle
3014 .update(&mut app, |_, c| {
3015 c.spawn(async { 14 }, |me, output, _| {
3016 me.count = output;
3017 })
3018 })
3019 .await;
3020 handle.read(&app, |view, _| assert_eq!(view.count, 14));
3021 });
3022 }
3023
3024 #[test]
3025 fn test_spawn_stream_local_from_view() {
3026 #[derive(Default)]
3027 struct View {
3028 events: Vec<Option<usize>>,
3029 }
3030
3031 impl Entity for View {
3032 type Event = ();
3033 }
3034
3035 impl super::View for View {
3036 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3037 Empty::new().boxed()
3038 }
3039
3040 fn ui_name() -> &'static str {
3041 "View"
3042 }
3043 }
3044
3045 App::test((), |mut app| async move {
3046 let (_, handle) = app.add_window(|_| View::default());
3047 handle
3048 .update(&mut app, |_, c| {
3049 c.spawn_stream(
3050 smol::stream::iter(vec![1_usize, 2, 3]),
3051 |me, output, _| {
3052 me.events.push(Some(output));
3053 },
3054 |me, _| {
3055 me.events.push(None);
3056 },
3057 )
3058 })
3059 .await;
3060
3061 handle.read(&app, |view, _| {
3062 assert_eq!(view.events, [Some(1), Some(2), Some(3), None])
3063 });
3064 });
3065 }
3066
3067 #[test]
3068 fn test_dispatch_action() {
3069 struct ViewA {
3070 id: usize,
3071 }
3072
3073 impl Entity for ViewA {
3074 type Event = ();
3075 }
3076
3077 impl View for ViewA {
3078 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3079 Empty::new().boxed()
3080 }
3081
3082 fn ui_name() -> &'static str {
3083 "View"
3084 }
3085 }
3086
3087 struct ViewB {
3088 id: usize,
3089 }
3090
3091 impl Entity for ViewB {
3092 type Event = ();
3093 }
3094
3095 impl View for ViewB {
3096 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3097 Empty::new().boxed()
3098 }
3099
3100 fn ui_name() -> &'static str {
3101 "View"
3102 }
3103 }
3104
3105 struct ActionArg {
3106 foo: String,
3107 }
3108
3109 App::test((), |mut app| async move {
3110 let actions = Rc::new(RefCell::new(Vec::new()));
3111
3112 let actions_clone = actions.clone();
3113 app.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
3114 actions_clone.borrow_mut().push("global a".to_string());
3115 });
3116
3117 let actions_clone = actions.clone();
3118 app.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
3119 actions_clone.borrow_mut().push("global b".to_string());
3120 });
3121
3122 let actions_clone = actions.clone();
3123 app.add_action("action", move |view: &mut ViewA, arg: &ActionArg, ctx| {
3124 assert_eq!(arg.foo, "bar");
3125 ctx.propagate_action();
3126 actions_clone.borrow_mut().push(format!("{} a", view.id));
3127 });
3128
3129 let actions_clone = actions.clone();
3130 app.add_action("action", move |view: &mut ViewA, _: &ActionArg, ctx| {
3131 if view.id != 1 {
3132 ctx.propagate_action();
3133 }
3134 actions_clone.borrow_mut().push(format!("{} b", view.id));
3135 });
3136
3137 let actions_clone = actions.clone();
3138 app.add_action("action", move |view: &mut ViewB, _: &ActionArg, ctx| {
3139 ctx.propagate_action();
3140 actions_clone.borrow_mut().push(format!("{} c", view.id));
3141 });
3142
3143 let actions_clone = actions.clone();
3144 app.add_action("action", move |view: &mut ViewB, _: &ActionArg, ctx| {
3145 ctx.propagate_action();
3146 actions_clone.borrow_mut().push(format!("{} d", view.id));
3147 });
3148
3149 let (window_id, view_1) = app.add_window(|_| ViewA { id: 1 });
3150 let view_2 = app.add_view(window_id, |_| ViewB { id: 2 });
3151 let view_3 = app.add_view(window_id, |_| ViewA { id: 3 });
3152 let view_4 = app.add_view(window_id, |_| ViewB { id: 4 });
3153
3154 app.dispatch_action(
3155 window_id,
3156 vec![view_1.id(), view_2.id(), view_3.id(), view_4.id()],
3157 "action",
3158 ActionArg { foo: "bar".into() },
3159 );
3160
3161 assert_eq!(
3162 *actions.borrow(),
3163 vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "1 b"]
3164 );
3165
3166 // Remove view_1, which doesn't propagate the action
3167 actions.borrow_mut().clear();
3168 app.dispatch_action(
3169 window_id,
3170 vec![view_2.id(), view_3.id(), view_4.id()],
3171 "action",
3172 ActionArg { foo: "bar".into() },
3173 );
3174
3175 assert_eq!(
3176 *actions.borrow(),
3177 vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "global b", "global a"]
3178 );
3179 })
3180 }
3181
3182 #[test]
3183 fn test_dispatch_keystroke() -> Result<()> {
3184 use std::cell::Cell;
3185
3186 #[derive(Clone)]
3187 struct ActionArg {
3188 key: String,
3189 }
3190
3191 struct View {
3192 id: usize,
3193 keymap_context: keymap::Context,
3194 }
3195
3196 impl Entity for View {
3197 type Event = ();
3198 }
3199
3200 impl super::View for View {
3201 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3202 Empty::new().boxed()
3203 }
3204
3205 fn ui_name() -> &'static str {
3206 "View"
3207 }
3208
3209 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
3210 self.keymap_context.clone()
3211 }
3212 }
3213
3214 impl View {
3215 fn new(id: usize) -> Self {
3216 View {
3217 id,
3218 keymap_context: keymap::Context::default(),
3219 }
3220 }
3221 }
3222
3223 App::test((), |mut app| async move {
3224 let mut view_1 = View::new(1);
3225 let mut view_2 = View::new(2);
3226 let mut view_3 = View::new(3);
3227 view_1.keymap_context.set.insert("a".into());
3228 view_2.keymap_context.set.insert("b".into());
3229 view_3.keymap_context.set.insert("c".into());
3230
3231 let (window_id, view_1) = app.add_window(|_| view_1);
3232 let view_2 = app.add_view(window_id, |_| view_2);
3233 let view_3 = app.add_view(window_id, |_| view_3);
3234
3235 // This keymap's only binding dispatches an action on view 2 because that view will have
3236 // "a" and "b" in its context, but not "c".
3237 let binding = keymap::Binding::new("a", "action", Some("a && b && !c"))
3238 .with_arg(ActionArg { key: "a".into() });
3239 app.add_bindings(vec![binding]);
3240
3241 let handled_action = Rc::new(Cell::new(false));
3242 let handled_action_clone = handled_action.clone();
3243 app.add_action("action", move |view: &mut View, arg: &ActionArg, _ctx| {
3244 handled_action_clone.set(true);
3245 assert_eq!(view.id, 2);
3246 assert_eq!(arg.key, "a");
3247 });
3248
3249 app.dispatch_keystroke(
3250 window_id,
3251 vec![view_1.id(), view_2.id(), view_3.id()],
3252 &Keystroke::parse("a")?,
3253 )?;
3254
3255 assert!(handled_action.get());
3256 Ok(())
3257 })
3258 }
3259
3260 // #[test]
3261 // fn test_ui_and_window_updates() {
3262 // struct View {
3263 // count: usize,
3264 // }
3265
3266 // impl Entity for View {
3267 // type Event = ();
3268 // }
3269
3270 // impl super::View for View {
3271 // fn render<'a>(&self, _: &AppContext) -> ElementBox {
3272 // Empty::new().boxed()
3273 // }
3274
3275 // fn ui_name() -> &'static str {
3276 // "View"
3277 // }
3278 // }
3279
3280 // App::test(|mut app| async move {
3281 // let (window_id, _) = app.add_window(|_| View { count: 3 });
3282 // let view_1 = app.add_view(window_id, |_| View { count: 1 });
3283 // let view_2 = app.add_view(window_id, |_| View { count: 2 });
3284
3285 // // Ensure that registering for UI updates after mutating the app still gives us all the
3286 // // updates.
3287 // let ui_updates = Rc::new(RefCell::new(Vec::new()));
3288 // let ui_updates_ = ui_updates.clone();
3289 // app.on_ui_update(move |update, _| ui_updates_.borrow_mut().push(update));
3290
3291 // assert_eq!(
3292 // ui_updates.borrow_mut().drain(..).collect::<Vec<_>>(),
3293 // vec![UiUpdate::OpenWindow {
3294 // window_id,
3295 // width: 1024.0,
3296 // height: 768.0,
3297 // }]
3298 // );
3299
3300 // let window_invalidations = Rc::new(RefCell::new(Vec::new()));
3301 // let window_invalidations_ = window_invalidations.clone();
3302 // app.on_window_invalidated(window_id, move |update, _| {
3303 // window_invalidations_.borrow_mut().push(update)
3304 // });
3305
3306 // let view_2_id = view_2.id();
3307 // view_1.update(&mut app, |view, ctx| {
3308 // view.count = 7;
3309 // ctx.notify();
3310 // drop(view_2);
3311 // });
3312
3313 // let invalidation = window_invalidations.borrow_mut().drain(..).next().unwrap();
3314 // assert_eq!(invalidation.updated.len(), 1);
3315 // assert!(invalidation.updated.contains(&view_1.id()));
3316 // assert_eq!(invalidation.removed, vec![view_2_id]);
3317
3318 // let view_3 = view_1.update(&mut app, |_, ctx| ctx.add_view(|_| View { count: 8 }));
3319
3320 // let invalidation = window_invalidations.borrow_mut().drain(..).next().unwrap();
3321 // assert_eq!(invalidation.updated.len(), 1);
3322 // assert!(invalidation.updated.contains(&view_3.id()));
3323 // assert!(invalidation.removed.is_empty());
3324
3325 // view_3
3326 // .update(&mut app, |_, ctx| {
3327 // ctx.spawn_local(async { 9 }, |me, output, ctx| {
3328 // me.count = output;
3329 // ctx.notify();
3330 // })
3331 // })
3332 // .await;
3333
3334 // let invalidation = window_invalidations.borrow_mut().drain(..).next().unwrap();
3335 // assert_eq!(invalidation.updated.len(), 1);
3336 // assert!(invalidation.updated.contains(&view_3.id()));
3337 // assert!(invalidation.removed.is_empty());
3338 // });
3339 // }
3340
3341 #[test]
3342 fn test_finish_pending_tasks() {
3343 struct View;
3344
3345 impl Entity for View {
3346 type Event = ();
3347 }
3348
3349 impl super::View for View {
3350 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3351 Empty::new().boxed()
3352 }
3353
3354 fn ui_name() -> &'static str {
3355 "View"
3356 }
3357 }
3358
3359 struct Model;
3360
3361 impl Entity for Model {
3362 type Event = ();
3363 }
3364
3365 App::test((), |mut app| async move {
3366 let model = app.add_model(|_| Model);
3367 let (_, view) = app.add_window(|_| View);
3368
3369 model.update(&mut app, |_, ctx| {
3370 ctx.spawn(async {}, |_, _, _| {}).detach();
3371 // Cancel this task
3372 drop(ctx.spawn(async {}, |_, _, _| {}));
3373 });
3374
3375 view.update(&mut app, |_, ctx| {
3376 ctx.spawn(async {}, |_, _, _| {}).detach();
3377 // Cancel this task
3378 drop(ctx.spawn(async {}, |_, _, _| {}));
3379 });
3380
3381 assert!(!app.0.borrow().future_handlers.borrow().is_empty());
3382 app.finish_pending_tasks().await;
3383 assert!(app.0.borrow().future_handlers.borrow().is_empty());
3384 app.finish_pending_tasks().await; // Don't block if there are no tasks
3385
3386 model.update(&mut app, |_, ctx| {
3387 ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {})
3388 .detach();
3389 // Cancel this task
3390 drop(ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {}));
3391 });
3392
3393 view.update(&mut app, |_, ctx| {
3394 ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {})
3395 .detach();
3396 // Cancel this task
3397 drop(ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {}));
3398 });
3399
3400 assert!(!app.0.borrow().stream_handlers.borrow().is_empty());
3401 app.finish_pending_tasks().await;
3402 assert!(app.0.borrow().stream_handlers.borrow().is_empty());
3403 app.finish_pending_tasks().await; // Don't block if there are no tasks
3404
3405 // Tasks are considered finished when we drop handles
3406 let mut tasks = Vec::new();
3407 model.update(&mut app, |_, ctx| {
3408 tasks.push(Box::new(ctx.spawn(async {}, |_, _, _| {})));
3409 tasks.push(Box::new(ctx.spawn_stream(
3410 smol::stream::iter(vec![1, 2, 3]),
3411 |_, _, _| {},
3412 |_, _| {},
3413 )));
3414 });
3415
3416 view.update(&mut app, |_, ctx| {
3417 tasks.push(Box::new(ctx.spawn(async {}, |_, _, _| {})));
3418 tasks.push(Box::new(ctx.spawn_stream(
3419 smol::stream::iter(vec![1, 2, 3]),
3420 |_, _, _| {},
3421 |_, _| {},
3422 )));
3423 });
3424
3425 assert!(!app.0.borrow().stream_handlers.borrow().is_empty());
3426
3427 let finish_pending_tasks = app.finish_pending_tasks();
3428 drop(tasks);
3429 finish_pending_tasks.await;
3430 assert!(app.0.borrow().stream_handlers.borrow().is_empty());
3431 app.finish_pending_tasks().await; // Don't block if there are no tasks
3432 });
3433 }
3434}