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