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::current::app(); // TODO: Make a test platform 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 let task_done = self.task_done.1.clone();
1163
1164 async move {
1165 while !pending_tasks.is_empty() {
1166 if let Ok(task_id) = task_done.recv().await {
1167 pending_tasks.remove(&task_id);
1168 } else {
1169 break;
1170 }
1171 }
1172 }
1173 }
1174}
1175
1176impl ModelAsRef for MutableAppContext {
1177 fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1178 if let Some(model) = self.ctx.models.get(&handle.model_id) {
1179 model
1180 .as_any()
1181 .downcast_ref()
1182 .expect("Downcast is type safe")
1183 } else {
1184 panic!("Circular model reference");
1185 }
1186 }
1187}
1188
1189impl UpdateModel for MutableAppContext {
1190 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1191 where
1192 T: Entity,
1193 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1194 {
1195 if let Some(mut model) = self.ctx.models.remove(&handle.model_id) {
1196 self.pending_flushes += 1;
1197 let mut ctx = ModelContext::new(self, handle.model_id);
1198 let result = update(
1199 model
1200 .as_any_mut()
1201 .downcast_mut()
1202 .expect("Downcast is type safe"),
1203 &mut ctx,
1204 );
1205 self.ctx.models.insert(handle.model_id, model);
1206 self.flush_effects();
1207 result
1208 } else {
1209 panic!("Circular model update");
1210 }
1211 }
1212}
1213
1214impl ViewAsRef for MutableAppContext {
1215 fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1216 if let Some(window) = self.ctx.windows.get(&handle.window_id) {
1217 if let Some(view) = window.views.get(&handle.view_id) {
1218 view.as_any().downcast_ref().expect("Downcast is type safe")
1219 } else {
1220 panic!("Circular view reference");
1221 }
1222 } else {
1223 panic!("Window does not exist");
1224 }
1225 }
1226}
1227
1228impl UpdateView for MutableAppContext {
1229 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
1230 where
1231 T: View,
1232 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
1233 {
1234 self.pending_flushes += 1;
1235 let mut view = if let Some(window) = self.ctx.windows.get_mut(&handle.window_id) {
1236 if let Some(view) = window.views.remove(&handle.view_id) {
1237 view
1238 } else {
1239 panic!("Circular view update");
1240 }
1241 } else {
1242 panic!("Window does not exist");
1243 };
1244
1245 let mut ctx = ViewContext::new(self, handle.window_id, handle.view_id);
1246 let result = update(
1247 view.as_any_mut()
1248 .downcast_mut()
1249 .expect("Downcast is type safe"),
1250 &mut ctx,
1251 );
1252 self.ctx
1253 .windows
1254 .get_mut(&handle.window_id)
1255 .unwrap()
1256 .views
1257 .insert(handle.view_id, view);
1258 self.flush_effects();
1259 result
1260 }
1261}
1262
1263pub struct AppContext {
1264 models: HashMap<usize, Box<dyn AnyModel>>,
1265 windows: HashMap<usize, Window>,
1266 ref_counts: Arc<Mutex<RefCounts>>,
1267}
1268
1269impl AppContext {
1270 pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
1271 self.windows
1272 .get(&window_id)
1273 .and_then(|window| window.root_view.as_ref().map(|v| v.id()))
1274 }
1275
1276 pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
1277 self.windows
1278 .get(&window_id)
1279 .and_then(|window| window.focused_view)
1280 }
1281
1282 pub fn render_view(&self, window_id: usize, view_id: usize) -> Result<ElementBox> {
1283 self.windows
1284 .get(&window_id)
1285 .and_then(|w| w.views.get(&view_id))
1286 .map(|v| v.render(self))
1287 .ok_or(anyhow!("view not found"))
1288 }
1289
1290 pub fn render_views(&self, window_id: usize) -> Result<HashMap<usize, ElementBox>> {
1291 self.windows
1292 .get(&window_id)
1293 .map(|w| {
1294 w.views
1295 .iter()
1296 .map(|(id, view)| (*id, view.render(self)))
1297 .collect::<HashMap<_, ElementBox>>()
1298 })
1299 .ok_or(anyhow!("window not found"))
1300 }
1301}
1302
1303impl ModelAsRef for AppContext {
1304 fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1305 if let Some(model) = self.models.get(&handle.model_id) {
1306 model
1307 .as_any()
1308 .downcast_ref()
1309 .expect("downcast should be type safe")
1310 } else {
1311 panic!("circular model reference");
1312 }
1313 }
1314}
1315
1316impl ViewAsRef for AppContext {
1317 fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1318 if let Some(window) = self.windows.get(&handle.window_id) {
1319 if let Some(view) = window.views.get(&handle.view_id) {
1320 view.as_any()
1321 .downcast_ref()
1322 .expect("downcast should be type safe")
1323 } else {
1324 panic!("circular view reference");
1325 }
1326 } else {
1327 panic!("window does not exist");
1328 }
1329 }
1330}
1331
1332#[derive(Default)]
1333struct Window {
1334 views: HashMap<usize, Box<dyn AnyView>>,
1335 root_view: Option<AnyViewHandle>,
1336 focused_view: Option<usize>,
1337}
1338
1339#[derive(Default, Clone)]
1340pub struct WindowInvalidation {
1341 pub updated: HashSet<usize>,
1342 pub removed: Vec<usize>,
1343}
1344
1345pub enum Effect {
1346 Event {
1347 entity_id: usize,
1348 payload: Box<dyn Any>,
1349 },
1350 ModelNotification {
1351 model_id: usize,
1352 },
1353 ViewNotification {
1354 window_id: usize,
1355 view_id: usize,
1356 },
1357 Focus {
1358 window_id: usize,
1359 view_id: usize,
1360 },
1361}
1362
1363pub trait AnyModel: Send + Sync {
1364 fn as_any(&self) -> &dyn Any;
1365 fn as_any_mut(&mut self) -> &mut dyn Any;
1366}
1367
1368impl<T> AnyModel for T
1369where
1370 T: Entity,
1371{
1372 fn as_any(&self) -> &dyn Any {
1373 self
1374 }
1375
1376 fn as_any_mut(&mut self) -> &mut dyn Any {
1377 self
1378 }
1379}
1380
1381pub trait AnyView: Send + Sync {
1382 fn as_any(&self) -> &dyn Any;
1383 fn as_any_mut(&mut self) -> &mut dyn Any;
1384 fn ui_name(&self) -> &'static str;
1385 fn render<'a>(&self, app: &AppContext) -> ElementBox;
1386 fn on_focus(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize);
1387 fn on_blur(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize);
1388 fn keymap_context(&self, app: &AppContext) -> keymap::Context;
1389}
1390
1391impl<T> AnyView for T
1392where
1393 T: View,
1394{
1395 fn as_any(&self) -> &dyn Any {
1396 self
1397 }
1398
1399 fn as_any_mut(&mut self) -> &mut dyn Any {
1400 self
1401 }
1402
1403 fn ui_name(&self) -> &'static str {
1404 T::ui_name()
1405 }
1406
1407 fn render<'a>(&self, app: &AppContext) -> ElementBox {
1408 View::render(self, app)
1409 }
1410
1411 fn on_focus(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize) {
1412 let mut ctx = ViewContext::new(app, window_id, view_id);
1413 View::on_focus(self, &mut ctx);
1414 }
1415
1416 fn on_blur(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize) {
1417 let mut ctx = ViewContext::new(app, window_id, view_id);
1418 View::on_blur(self, &mut ctx);
1419 }
1420
1421 fn keymap_context(&self, app: &AppContext) -> keymap::Context {
1422 View::keymap_context(self, app)
1423 }
1424}
1425
1426pub struct ModelContext<'a, T: ?Sized> {
1427 app: &'a mut MutableAppContext,
1428 model_id: usize,
1429 model_type: PhantomData<T>,
1430 halt_stream: bool,
1431}
1432
1433impl<'a, T: Entity> ModelContext<'a, T> {
1434 fn new(app: &'a mut MutableAppContext, model_id: usize) -> Self {
1435 Self {
1436 app,
1437 model_id,
1438 model_type: PhantomData,
1439 halt_stream: false,
1440 }
1441 }
1442
1443 pub fn app(&self) -> &AppContext {
1444 &self.app.ctx
1445 }
1446
1447 pub fn app_mut(&mut self) -> &mut MutableAppContext {
1448 self.app
1449 }
1450
1451 pub fn background_executor(&self) -> &Arc<executor::Background> {
1452 &self.app.background
1453 }
1454
1455 pub fn halt_stream(&mut self) {
1456 self.halt_stream = true;
1457 }
1458
1459 pub fn model_id(&self) -> usize {
1460 self.model_id
1461 }
1462
1463 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
1464 where
1465 S: Entity,
1466 F: FnOnce(&mut ModelContext<S>) -> S,
1467 {
1468 self.app.add_model(build_model)
1469 }
1470
1471 pub fn subscribe<S: Entity, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1472 where
1473 S::Event: 'static,
1474 F: 'static + FnMut(&mut T, &S::Event, &mut ModelContext<T>),
1475 {
1476 self.app
1477 .subscriptions
1478 .entry(handle.model_id)
1479 .or_default()
1480 .push(Subscription::FromModel {
1481 model_id: self.model_id,
1482 callback: Box::new(move |model, payload, app, model_id| {
1483 let model = model.downcast_mut().expect("downcast is type safe");
1484 let payload = payload.downcast_ref().expect("downcast is type safe");
1485 let mut ctx = ModelContext::new(app, model_id);
1486 callback(model, payload, &mut ctx);
1487 }),
1488 });
1489 }
1490
1491 pub fn emit(&mut self, payload: T::Event) {
1492 self.app.pending_effects.push_back(Effect::Event {
1493 entity_id: self.model_id,
1494 payload: Box::new(payload),
1495 });
1496 }
1497
1498 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1499 where
1500 S: Entity,
1501 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ModelContext<T>),
1502 {
1503 self.app
1504 .observations
1505 .entry(handle.model_id)
1506 .or_default()
1507 .push(Observation::FromModel {
1508 model_id: self.model_id,
1509 callback: Box::new(move |model, observed_id, app, model_id| {
1510 let model = model.downcast_mut().expect("downcast is type safe");
1511 let observed = ModelHandle::new(observed_id, &app.ctx.ref_counts);
1512 let mut ctx = ModelContext::new(app, model_id);
1513 callback(model, observed, &mut ctx);
1514 }),
1515 });
1516 }
1517
1518 pub fn notify(&mut self) {
1519 self.app
1520 .pending_effects
1521 .push_back(Effect::ModelNotification {
1522 model_id: self.model_id,
1523 });
1524 }
1525
1526 pub fn spawn<S, F, U>(&mut self, future: S, callback: F) -> ForegroundTask<Option<U>>
1527 where
1528 S: 'static + Future,
1529 F: 'static + FnOnce(&mut T, S::Output, &mut ModelContext<T>) -> U,
1530 U: 'static,
1531 {
1532 let (task_id, task) = self.app.spawn::<S, U>(future);
1533
1534 self.app.future_handlers.insert(
1535 task_id,
1536 FutureHandler::Model {
1537 model_id: self.model_id,
1538 callback: Box::new(move |model, output, app, model_id| {
1539 let model = model.downcast_mut().unwrap();
1540 let output = *output.downcast().unwrap();
1541 Box::new(callback(
1542 model,
1543 output,
1544 &mut ModelContext::new(app, model_id),
1545 ))
1546 }),
1547 },
1548 );
1549
1550 task
1551 }
1552
1553 pub fn spawn_stream<S, F, G, U>(
1554 &mut self,
1555 stream: S,
1556 mut item_callback: F,
1557 done_callback: G,
1558 ) -> ForegroundTask<Option<U>>
1559 where
1560 S: 'static + Stream + Unpin,
1561 F: 'static + FnMut(&mut T, S::Item, &mut ModelContext<T>),
1562 G: 'static + FnOnce(&mut T, &mut ModelContext<T>) -> U,
1563 U: 'static + Any,
1564 {
1565 let (task_id, task) = self.app.spawn_stream(stream);
1566 self.app.stream_handlers.insert(
1567 task_id,
1568 StreamHandler::Model {
1569 model_id: self.model_id,
1570 item_callback: Box::new(move |model, output, app, model_id| {
1571 let model = model.downcast_mut().unwrap();
1572 let output = *output.downcast().unwrap();
1573 let mut ctx = ModelContext::new(app, model_id);
1574 item_callback(model, output, &mut ctx);
1575 ctx.halt_stream
1576 }),
1577 done_callback: Box::new(
1578 move |model: &mut dyn Any, app: &mut MutableAppContext, model_id| {
1579 let model = model.downcast_mut().unwrap();
1580 let mut ctx = ModelContext::new(app, model_id);
1581 Box::new(done_callback(model, &mut ctx))
1582 },
1583 ),
1584 },
1585 );
1586
1587 task
1588 }
1589}
1590
1591impl<M> ModelAsRef for ModelContext<'_, M> {
1592 fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1593 self.app.model(handle)
1594 }
1595}
1596
1597impl<M> UpdateModel for ModelContext<'_, M> {
1598 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1599 where
1600 T: Entity,
1601 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1602 {
1603 self.app.update_model(handle, update)
1604 }
1605}
1606
1607pub struct ViewContext<'a, T: ?Sized> {
1608 app: &'a mut MutableAppContext,
1609 window_id: usize,
1610 view_id: usize,
1611 view_type: PhantomData<T>,
1612 halt_action_dispatch: bool,
1613 halt_stream: bool,
1614}
1615
1616impl<'a, T: View> ViewContext<'a, T> {
1617 fn new(app: &'a mut MutableAppContext, window_id: usize, view_id: usize) -> Self {
1618 Self {
1619 app,
1620 window_id,
1621 view_id,
1622 view_type: PhantomData,
1623 halt_action_dispatch: true,
1624 halt_stream: false,
1625 }
1626 }
1627
1628 pub fn handle(&self) -> WeakViewHandle<T> {
1629 WeakViewHandle::new(self.window_id, self.view_id)
1630 }
1631
1632 pub fn window_id(&self) -> usize {
1633 self.window_id
1634 }
1635
1636 pub fn app(&self) -> &AppContext {
1637 &self.app.ctx
1638 }
1639
1640 pub fn app_mut(&mut self) -> &mut MutableAppContext {
1641 self.app
1642 }
1643
1644 pub fn background_executor(&self) -> &Arc<executor::Background> {
1645 &self.app.background
1646 }
1647
1648 pub fn focus<S>(&mut self, handle: S)
1649 where
1650 S: Into<AnyViewHandle>,
1651 {
1652 let handle = handle.into();
1653 self.app.pending_effects.push_back(Effect::Focus {
1654 window_id: handle.window_id,
1655 view_id: handle.view_id,
1656 });
1657 }
1658
1659 pub fn focus_self(&mut self) {
1660 self.app.pending_effects.push_back(Effect::Focus {
1661 window_id: self.window_id,
1662 view_id: self.view_id,
1663 });
1664 }
1665
1666 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
1667 where
1668 S: Entity,
1669 F: FnOnce(&mut ModelContext<S>) -> S,
1670 {
1671 self.app.add_model(build_model)
1672 }
1673
1674 pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
1675 where
1676 S: View,
1677 F: FnOnce(&mut ViewContext<S>) -> S,
1678 {
1679 self.app.add_view(self.window_id, build_view)
1680 }
1681
1682 pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
1683 where
1684 S: View,
1685 F: FnOnce(&mut ViewContext<S>) -> Option<S>,
1686 {
1687 self.app.add_option_view(self.window_id, build_view)
1688 }
1689
1690 pub fn subscribe_to_model<E, F>(&mut self, handle: &ModelHandle<E>, mut callback: F)
1691 where
1692 E: Entity,
1693 E::Event: 'static,
1694 F: 'static + FnMut(&mut T, ModelHandle<E>, &E::Event, &mut ViewContext<T>),
1695 {
1696 let emitter_handle = handle.downgrade();
1697 self.app
1698 .subscriptions
1699 .entry(handle.id())
1700 .or_default()
1701 .push(Subscription::FromView {
1702 window_id: self.window_id,
1703 view_id: self.view_id,
1704 callback: Box::new(move |view, payload, app, window_id, view_id| {
1705 if let Some(emitter_handle) = emitter_handle.upgrade(app.downgrade()) {
1706 let model = view.downcast_mut().expect("downcast is type safe");
1707 let payload = payload.downcast_ref().expect("downcast is type safe");
1708 let mut ctx = ViewContext::new(app, window_id, view_id);
1709 callback(model, emitter_handle, payload, &mut ctx);
1710 }
1711 }),
1712 });
1713 }
1714
1715 pub fn subscribe_to_view<V, F>(&mut self, handle: &ViewHandle<V>, mut callback: F)
1716 where
1717 V: View,
1718 V::Event: 'static,
1719 F: 'static + FnMut(&mut T, ViewHandle<V>, &V::Event, &mut ViewContext<T>),
1720 {
1721 let emitter_handle = handle.downgrade();
1722
1723 self.app
1724 .subscriptions
1725 .entry(handle.id())
1726 .or_default()
1727 .push(Subscription::FromView {
1728 window_id: self.window_id,
1729 view_id: self.view_id,
1730 callback: Box::new(move |view, payload, app, window_id, view_id| {
1731 if let Some(emitter_handle) = emitter_handle.upgrade(app.downgrade()) {
1732 let model = view.downcast_mut().expect("downcast is type safe");
1733 let payload = payload.downcast_ref().expect("downcast is type safe");
1734 let mut ctx = ViewContext::new(app, window_id, view_id);
1735 callback(model, emitter_handle, payload, &mut ctx);
1736 }
1737 }),
1738 });
1739 }
1740
1741 pub fn emit(&mut self, payload: T::Event) {
1742 self.app.pending_effects.push_back(Effect::Event {
1743 entity_id: self.view_id,
1744 payload: Box::new(payload),
1745 });
1746 }
1747
1748 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1749 where
1750 S: Entity,
1751 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ViewContext<T>),
1752 {
1753 self.app
1754 .observations
1755 .entry(handle.id())
1756 .or_default()
1757 .push(Observation::FromView {
1758 window_id: self.window_id,
1759 view_id: self.view_id,
1760 callback: Box::new(move |view, observed_id, app, window_id, view_id| {
1761 let view = view.downcast_mut().expect("downcast is type safe");
1762 let observed = ModelHandle::new(observed_id, &app.ctx.ref_counts);
1763 let mut ctx = ViewContext::new(app, window_id, view_id);
1764 callback(view, observed, &mut ctx);
1765 }),
1766 });
1767 }
1768
1769 pub fn notify(&mut self) {
1770 self.app
1771 .pending_effects
1772 .push_back(Effect::ViewNotification {
1773 window_id: self.window_id,
1774 view_id: self.view_id,
1775 });
1776 }
1777
1778 pub fn propagate_action(&mut self) {
1779 self.halt_action_dispatch = false;
1780 }
1781
1782 pub fn halt_stream(&mut self) {
1783 self.halt_stream = true;
1784 }
1785
1786 pub fn spawn<S, F, U>(&mut self, future: S, callback: F) -> ForegroundTask<Option<U>>
1787 where
1788 S: 'static + Future,
1789 F: 'static + FnOnce(&mut T, S::Output, &mut ViewContext<T>) -> U,
1790 U: 'static,
1791 {
1792 let (task_id, task) = self.app.spawn(future);
1793
1794 self.app.future_handlers.insert(
1795 task_id,
1796 FutureHandler::View {
1797 window_id: self.window_id,
1798 view_id: self.view_id,
1799 callback: Box::new(move |view, output, app, window_id, view_id| {
1800 let view = view.as_any_mut().downcast_mut().unwrap();
1801 let output = *output.downcast().unwrap();
1802 Box::new(callback(
1803 view,
1804 output,
1805 &mut ViewContext::new(app, window_id, view_id),
1806 ))
1807 }),
1808 },
1809 );
1810
1811 task
1812 }
1813
1814 pub fn spawn_stream<S, F, G, U>(
1815 &mut self,
1816 stream: S,
1817 mut item_callback: F,
1818 done_callback: G,
1819 ) -> ForegroundTask<Option<U>>
1820 where
1821 S: 'static + Stream + Unpin,
1822 F: 'static + FnMut(&mut T, S::Item, &mut ViewContext<T>),
1823 G: 'static + FnOnce(&mut T, &mut ViewContext<T>) -> U,
1824 U: 'static + Any,
1825 {
1826 let (task_id, task) = self.app.spawn_stream(stream);
1827 self.app.stream_handlers.insert(
1828 task_id,
1829 StreamHandler::View {
1830 window_id: self.window_id,
1831 view_id: self.view_id,
1832 item_callback: Box::new(move |view, output, app, window_id, view_id| {
1833 let view = view.as_any_mut().downcast_mut().unwrap();
1834 let output = *output.downcast().unwrap();
1835 let mut ctx = ViewContext::new(app, window_id, view_id);
1836 item_callback(view, output, &mut ctx);
1837 ctx.halt_stream
1838 }),
1839 done_callback: Box::new(move |view, app, window_id, view_id| {
1840 let view = view.as_any_mut().downcast_mut().unwrap();
1841 let mut ctx = ViewContext::new(app, window_id, view_id);
1842 Box::new(done_callback(view, &mut ctx))
1843 }),
1844 },
1845 );
1846 task
1847 }
1848}
1849
1850impl<V> ModelAsRef for ViewContext<'_, V> {
1851 fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1852 self.app.model(handle)
1853 }
1854}
1855
1856impl<V: View> UpdateModel for ViewContext<'_, V> {
1857 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1858 where
1859 T: Entity,
1860 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1861 {
1862 self.app.update_model(handle, update)
1863 }
1864}
1865
1866impl<V: View> ViewAsRef for ViewContext<'_, V> {
1867 fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1868 self.app.view(handle)
1869 }
1870}
1871
1872impl<V: View> UpdateView for ViewContext<'_, V> {
1873 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
1874 where
1875 T: View,
1876 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
1877 {
1878 self.app.update_view(handle, update)
1879 }
1880}
1881
1882pub trait Handle<T> {
1883 fn id(&self) -> usize;
1884 fn location(&self) -> EntityLocation;
1885}
1886
1887#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
1888pub enum EntityLocation {
1889 Model(usize),
1890 View(usize, usize),
1891}
1892
1893pub struct ModelHandle<T> {
1894 model_id: usize,
1895 model_type: PhantomData<T>,
1896 ref_counts: Weak<Mutex<RefCounts>>,
1897}
1898
1899impl<T: Entity> ModelHandle<T> {
1900 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
1901 ref_counts.lock().inc(model_id);
1902 Self {
1903 model_id,
1904 model_type: PhantomData,
1905 ref_counts: Arc::downgrade(ref_counts),
1906 }
1907 }
1908
1909 fn downgrade(&self) -> WeakModelHandle<T> {
1910 WeakModelHandle::new(self.model_id)
1911 }
1912
1913 pub fn id(&self) -> usize {
1914 self.model_id
1915 }
1916
1917 pub fn as_ref<'a, A: ModelAsRef>(&self, app: &'a A) -> &'a T {
1918 app.model(self)
1919 }
1920
1921 pub fn read<'a, S, F>(&self, app: &'a App, read: F) -> S
1922 where
1923 F: FnOnce(&T, &AppContext) -> S,
1924 {
1925 app.read_model(self, read)
1926 }
1927
1928 pub fn update<A, F, S>(&self, app: &mut A, update: F) -> S
1929 where
1930 A: UpdateModel,
1931 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1932 {
1933 app.update_model(self, update)
1934 }
1935}
1936
1937impl<T> Clone for ModelHandle<T> {
1938 fn clone(&self) -> Self {
1939 if let Some(ref_counts) = self.ref_counts.upgrade() {
1940 ref_counts.lock().inc(self.model_id);
1941 }
1942
1943 Self {
1944 model_id: self.model_id,
1945 model_type: PhantomData,
1946 ref_counts: self.ref_counts.clone(),
1947 }
1948 }
1949}
1950
1951impl<T> PartialEq for ModelHandle<T> {
1952 fn eq(&self, other: &Self) -> bool {
1953 self.model_id == other.model_id
1954 }
1955}
1956
1957impl<T> Eq for ModelHandle<T> {}
1958
1959impl<T> Hash for ModelHandle<T> {
1960 fn hash<H: Hasher>(&self, state: &mut H) {
1961 self.model_id.hash(state);
1962 }
1963}
1964
1965impl<T> std::borrow::Borrow<usize> for ModelHandle<T> {
1966 fn borrow(&self) -> &usize {
1967 &self.model_id
1968 }
1969}
1970
1971impl<T> Debug for ModelHandle<T> {
1972 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1973 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
1974 .field(&self.model_id)
1975 .finish()
1976 }
1977}
1978
1979unsafe impl<T> Send for ModelHandle<T> {}
1980unsafe impl<T> Sync for ModelHandle<T> {}
1981
1982impl<T> Drop for ModelHandle<T> {
1983 fn drop(&mut self) {
1984 if let Some(ref_counts) = self.ref_counts.upgrade() {
1985 ref_counts.lock().dec_model(self.model_id);
1986 }
1987 }
1988}
1989
1990impl<T> Handle<T> for ModelHandle<T> {
1991 fn id(&self) -> usize {
1992 self.model_id
1993 }
1994
1995 fn location(&self) -> EntityLocation {
1996 EntityLocation::Model(self.model_id)
1997 }
1998}
1999
2000pub struct WeakModelHandle<T> {
2001 model_id: usize,
2002 model_type: PhantomData<T>,
2003}
2004
2005impl<T: Entity> WeakModelHandle<T> {
2006 fn new(model_id: usize) -> Self {
2007 Self {
2008 model_id,
2009 model_type: PhantomData,
2010 }
2011 }
2012
2013 pub fn upgrade(&self, app: &AppContext) -> Option<ModelHandle<T>> {
2014 if app.models.contains_key(&self.model_id) {
2015 Some(ModelHandle::new(self.model_id, &app.ref_counts))
2016 } else {
2017 None
2018 }
2019 }
2020}
2021
2022pub struct ViewHandle<T> {
2023 window_id: usize,
2024 view_id: usize,
2025 view_type: PhantomData<T>,
2026 ref_counts: Weak<Mutex<RefCounts>>,
2027}
2028
2029impl<T: View> ViewHandle<T> {
2030 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
2031 ref_counts.lock().inc(view_id);
2032 Self {
2033 window_id,
2034 view_id,
2035 view_type: PhantomData,
2036 ref_counts: Arc::downgrade(ref_counts),
2037 }
2038 }
2039
2040 fn downgrade(&self) -> WeakViewHandle<T> {
2041 WeakViewHandle::new(self.window_id, self.view_id)
2042 }
2043
2044 pub fn window_id(&self) -> usize {
2045 self.window_id
2046 }
2047
2048 pub fn id(&self) -> usize {
2049 self.view_id
2050 }
2051
2052 pub fn as_ref<'a, A: ViewAsRef>(&self, app: &'a A) -> &'a T {
2053 app.view(self)
2054 }
2055
2056 pub fn read<'a, F, S>(&self, app: &'a App, read: F) -> S
2057 where
2058 F: FnOnce(&T, &AppContext) -> S,
2059 {
2060 app.read_view(self, read)
2061 }
2062
2063 pub fn update<A, F, S>(&self, app: &mut A, update: F) -> S
2064 where
2065 A: UpdateView,
2066 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
2067 {
2068 app.update_view(self, update)
2069 }
2070
2071 pub fn is_focused(&self, app: &AppContext) -> bool {
2072 app.focused_view_id(self.window_id)
2073 .map_or(false, |focused_id| focused_id == self.view_id)
2074 }
2075}
2076
2077impl<T> Clone for ViewHandle<T> {
2078 fn clone(&self) -> Self {
2079 if let Some(ref_counts) = self.ref_counts.upgrade() {
2080 ref_counts.lock().inc(self.view_id);
2081 }
2082
2083 Self {
2084 window_id: self.window_id,
2085 view_id: self.view_id,
2086 view_type: PhantomData,
2087 ref_counts: self.ref_counts.clone(),
2088 }
2089 }
2090}
2091
2092impl<T> PartialEq for ViewHandle<T> {
2093 fn eq(&self, other: &Self) -> bool {
2094 self.window_id == other.window_id && self.view_id == other.view_id
2095 }
2096}
2097
2098impl<T> Eq for ViewHandle<T> {}
2099
2100impl<T> Debug for ViewHandle<T> {
2101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2102 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
2103 .field("window_id", &self.window_id)
2104 .field("view_id", &self.view_id)
2105 .finish()
2106 }
2107}
2108
2109impl<T> Drop for ViewHandle<T> {
2110 fn drop(&mut self) {
2111 if let Some(ref_counts) = self.ref_counts.upgrade() {
2112 ref_counts.lock().dec_view(self.window_id, self.view_id);
2113 }
2114 }
2115}
2116
2117impl<T> Handle<T> for ViewHandle<T> {
2118 fn id(&self) -> usize {
2119 self.view_id
2120 }
2121
2122 fn location(&self) -> EntityLocation {
2123 EntityLocation::View(self.window_id, self.view_id)
2124 }
2125}
2126
2127#[derive(Clone)]
2128pub struct AnyViewHandle {
2129 window_id: usize,
2130 view_id: usize,
2131 view_type: TypeId,
2132 ref_counts: Weak<Mutex<RefCounts>>,
2133}
2134
2135impl AnyViewHandle {
2136 pub fn id(&self) -> usize {
2137 self.view_id
2138 }
2139
2140 pub fn is<T: 'static>(&self) -> bool {
2141 TypeId::of::<T>() == self.view_type
2142 }
2143
2144 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
2145 if self.is::<T>() {
2146 if let Some(ref_counts) = self.ref_counts.upgrade() {
2147 return Some(ViewHandle::new(self.window_id, self.view_id, &ref_counts));
2148 }
2149 }
2150 None
2151 }
2152}
2153
2154impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
2155 fn from(handle: &ViewHandle<T>) -> Self {
2156 if let Some(ref_counts) = handle.ref_counts.upgrade() {
2157 ref_counts.lock().inc(handle.view_id);
2158 }
2159 AnyViewHandle {
2160 window_id: handle.window_id,
2161 view_id: handle.view_id,
2162 view_type: TypeId::of::<T>(),
2163 ref_counts: handle.ref_counts.clone(),
2164 }
2165 }
2166}
2167
2168impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
2169 fn from(handle: ViewHandle<T>) -> Self {
2170 (&handle).into()
2171 }
2172}
2173
2174pub struct WeakViewHandle<T> {
2175 window_id: usize,
2176 view_id: usize,
2177 view_type: PhantomData<T>,
2178}
2179
2180impl<T: View> WeakViewHandle<T> {
2181 fn new(window_id: usize, view_id: usize) -> Self {
2182 Self {
2183 window_id,
2184 view_id,
2185 view_type: PhantomData,
2186 }
2187 }
2188
2189 pub fn upgrade(&self, app: &AppContext) -> Option<ViewHandle<T>> {
2190 if app
2191 .windows
2192 .get(&self.window_id)
2193 .and_then(|w| w.views.get(&self.view_id))
2194 .is_some()
2195 {
2196 Some(ViewHandle::new(
2197 self.window_id,
2198 self.view_id,
2199 &app.ref_counts,
2200 ))
2201 } else {
2202 None
2203 }
2204 }
2205}
2206
2207impl<T> Clone for WeakViewHandle<T> {
2208 fn clone(&self) -> Self {
2209 Self {
2210 window_id: self.window_id,
2211 view_id: self.view_id,
2212 view_type: PhantomData,
2213 }
2214 }
2215}
2216
2217#[derive(Default)]
2218struct RefCounts {
2219 counts: HashMap<usize, usize>,
2220 dropped_models: HashSet<usize>,
2221 dropped_views: HashSet<(usize, usize)>,
2222}
2223
2224impl RefCounts {
2225 fn inc(&mut self, model_id: usize) {
2226 *self.counts.entry(model_id).or_insert(0) += 1;
2227 }
2228
2229 fn dec_model(&mut self, model_id: usize) {
2230 if let Some(count) = self.counts.get_mut(&model_id) {
2231 *count -= 1;
2232 if *count == 0 {
2233 self.counts.remove(&model_id);
2234 self.dropped_models.insert(model_id);
2235 }
2236 } else {
2237 panic!("Expected ref count to be positive")
2238 }
2239 }
2240
2241 fn dec_view(&mut self, window_id: usize, view_id: usize) {
2242 if let Some(count) = self.counts.get_mut(&view_id) {
2243 *count -= 1;
2244 if *count == 0 {
2245 self.counts.remove(&view_id);
2246 self.dropped_views.insert((window_id, view_id));
2247 }
2248 } else {
2249 panic!("Expected ref count to be positive")
2250 }
2251 }
2252
2253 fn take_dropped(&mut self) -> (HashSet<usize>, HashSet<(usize, usize)>) {
2254 let mut dropped_models = HashSet::new();
2255 let mut dropped_views = HashSet::new();
2256 std::mem::swap(&mut self.dropped_models, &mut dropped_models);
2257 std::mem::swap(&mut self.dropped_views, &mut dropped_views);
2258 (dropped_models, dropped_views)
2259 }
2260}
2261
2262enum Subscription {
2263 FromModel {
2264 model_id: usize,
2265 callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize)>,
2266 },
2267 FromView {
2268 window_id: usize,
2269 view_id: usize,
2270 callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize, usize)>,
2271 },
2272}
2273
2274enum Observation {
2275 FromModel {
2276 model_id: usize,
2277 callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize)>,
2278 },
2279 FromView {
2280 window_id: usize,
2281 view_id: usize,
2282 callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize, usize)>,
2283 },
2284}
2285
2286enum FutureHandler {
2287 Model {
2288 model_id: usize,
2289 callback: Box<
2290 dyn FnOnce(&mut dyn Any, Box<dyn Any>, &mut MutableAppContext, usize) -> Box<dyn Any>,
2291 >,
2292 },
2293 View {
2294 window_id: usize,
2295 view_id: usize,
2296 callback: Box<
2297 dyn FnOnce(
2298 &mut dyn AnyView,
2299 Box<dyn Any>,
2300 &mut MutableAppContext,
2301 usize,
2302 usize,
2303 ) -> Box<dyn Any>,
2304 >,
2305 },
2306}
2307
2308enum StreamHandler {
2309 Model {
2310 model_id: usize,
2311 item_callback:
2312 Box<dyn FnMut(&mut dyn Any, Box<dyn Any>, &mut MutableAppContext, usize) -> bool>,
2313 done_callback: Box<dyn FnOnce(&mut dyn Any, &mut MutableAppContext, usize) -> Box<dyn Any>>,
2314 },
2315 View {
2316 window_id: usize,
2317 view_id: usize,
2318 item_callback: Box<
2319 dyn FnMut(&mut dyn AnyView, Box<dyn Any>, &mut MutableAppContext, usize, usize) -> bool,
2320 >,
2321 done_callback:
2322 Box<dyn FnOnce(&mut dyn AnyView, &mut MutableAppContext, usize, usize) -> Box<dyn Any>>,
2323 },
2324}
2325
2326#[cfg(test)]
2327mod tests {
2328 use super::*;
2329 use crate::elements::*;
2330
2331 #[test]
2332 fn test_model_handles() {
2333 struct Model {
2334 other: Option<ModelHandle<Model>>,
2335 events: Vec<String>,
2336 }
2337
2338 impl Entity for Model {
2339 type Event = usize;
2340 }
2341
2342 impl Model {
2343 fn new(other: Option<ModelHandle<Self>>, ctx: &mut ModelContext<Self>) -> Self {
2344 if let Some(other) = other.as_ref() {
2345 ctx.observe(other, |me, _, _| {
2346 me.events.push("notified".into());
2347 });
2348 ctx.subscribe(other, |me, event, _| {
2349 me.events.push(format!("observed event {}", event));
2350 });
2351 }
2352
2353 Self {
2354 other,
2355 events: Vec::new(),
2356 }
2357 }
2358 }
2359
2360 App::test((), |mut app| async move {
2361 let app = &mut app;
2362
2363 let handle_1 = app.add_model(|ctx| Model::new(None, ctx));
2364 let handle_2 = app.add_model(|ctx| Model::new(Some(handle_1.clone()), ctx));
2365 assert_eq!(app.0.borrow().ctx.models.len(), 2);
2366
2367 handle_1.update(app, |model, ctx| {
2368 model.events.push("updated".into());
2369 ctx.emit(1);
2370 ctx.notify();
2371 ctx.emit(2);
2372 });
2373 handle_1.read(app, |model, _| {
2374 assert_eq!(model.events, vec!["updated".to_string()]);
2375 });
2376 handle_2.read(app, |model, _| {
2377 assert_eq!(
2378 model.events,
2379 vec![
2380 "observed event 1".to_string(),
2381 "notified".to_string(),
2382 "observed event 2".to_string(),
2383 ]
2384 );
2385 });
2386
2387 handle_2.update(app, |model, _| {
2388 drop(handle_1);
2389 model.other.take();
2390 });
2391
2392 let app_state = app.0.borrow();
2393 assert_eq!(app_state.ctx.models.len(), 1);
2394 assert!(app_state.subscriptions.is_empty());
2395 assert!(app_state.observations.is_empty());
2396 })
2397 }
2398
2399 #[test]
2400 fn test_subscribe_and_emit_from_model() {
2401 #[derive(Default)]
2402 struct Model {
2403 events: Vec<usize>,
2404 }
2405
2406 impl Entity for Model {
2407 type Event = usize;
2408 }
2409
2410 App::test((), |mut app| async move {
2411 let app = &mut app;
2412 let handle_1 = app.add_model(|_| Model::default());
2413 let handle_2 = app.add_model(|_| Model::default());
2414 let handle_2b = handle_2.clone();
2415
2416 handle_1.update(app, |_, c| {
2417 c.subscribe(&handle_2, move |model: &mut Model, event, c| {
2418 model.events.push(*event);
2419
2420 c.subscribe(&handle_2b, |model, event, _| {
2421 model.events.push(*event * 2);
2422 });
2423 });
2424 });
2425
2426 handle_2.update(app, |_, c| c.emit(7));
2427 handle_1.read(app, |model, _| assert_eq!(model.events, vec![7]));
2428
2429 handle_2.update(app, |_, c| c.emit(5));
2430 handle_1.read(app, |model, _| assert_eq!(model.events, vec![7, 10, 5]));
2431 })
2432 }
2433
2434 #[test]
2435 fn test_observe_and_notify_from_model() {
2436 #[derive(Default)]
2437 struct Model {
2438 count: usize,
2439 events: Vec<usize>,
2440 }
2441
2442 impl Entity for Model {
2443 type Event = ();
2444 }
2445
2446 App::test((), |mut app| async move {
2447 let app = &mut app;
2448 let handle_1 = app.add_model(|_| Model::default());
2449 let handle_2 = app.add_model(|_| Model::default());
2450 let handle_2b = handle_2.clone();
2451
2452 handle_1.update(app, |_, c| {
2453 c.observe(&handle_2, move |model, observed, c| {
2454 model.events.push(observed.as_ref(c).count);
2455 c.observe(&handle_2b, |model, observed, c| {
2456 model.events.push(observed.as_ref(c).count * 2);
2457 });
2458 });
2459 });
2460
2461 handle_2.update(app, |model, c| {
2462 model.count = 7;
2463 c.notify()
2464 });
2465 handle_1.read(app, |model, _| assert_eq!(model.events, vec![7]));
2466
2467 handle_2.update(app, |model, c| {
2468 model.count = 5;
2469 c.notify()
2470 });
2471 handle_1.read(app, |model, _| assert_eq!(model.events, vec![7, 10, 5]))
2472 })
2473 }
2474
2475 #[test]
2476 fn test_spawn_from_model() {
2477 #[derive(Default)]
2478 struct Model {
2479 count: usize,
2480 }
2481
2482 impl Entity for Model {
2483 type Event = ();
2484 }
2485
2486 App::test((), |mut app| async move {
2487 let handle = app.add_model(|_| Model::default());
2488 handle
2489 .update(&mut app, |_, c| {
2490 c.spawn(async { 7 }, |model, output, _| {
2491 model.count = output;
2492 })
2493 })
2494 .await;
2495 handle.read(&app, |model, _| assert_eq!(model.count, 7));
2496
2497 handle
2498 .update(&mut app, |_, c| {
2499 c.spawn(async { 14 }, |model, output, _| {
2500 model.count = output;
2501 })
2502 })
2503 .await;
2504 handle.read(&app, |model, _| assert_eq!(model.count, 14));
2505 });
2506 }
2507
2508 #[test]
2509 fn test_spawn_stream_local_from_model() {
2510 #[derive(Default)]
2511 struct Model {
2512 events: Vec<Option<usize>>,
2513 }
2514
2515 impl Entity for Model {
2516 type Event = ();
2517 }
2518
2519 App::test((), |mut app| async move {
2520 let handle = app.add_model(|_| Model::default());
2521 handle
2522 .update(&mut app, |_, c| {
2523 c.spawn_stream(
2524 smol::stream::iter(vec![1, 2, 3]),
2525 |model, output, _| {
2526 model.events.push(Some(output));
2527 },
2528 |model, _| {
2529 model.events.push(None);
2530 },
2531 )
2532 })
2533 .await;
2534
2535 handle.read(&app, |model, _| {
2536 assert_eq!(model.events, [Some(1), Some(2), Some(3), None])
2537 });
2538 })
2539 }
2540
2541 #[test]
2542 fn test_view_handles() {
2543 struct View {
2544 other: Option<ViewHandle<View>>,
2545 events: Vec<String>,
2546 }
2547
2548 impl Entity for View {
2549 type Event = usize;
2550 }
2551
2552 impl super::View for View {
2553 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2554 Empty::new().boxed()
2555 }
2556
2557 fn ui_name() -> &'static str {
2558 "View"
2559 }
2560 }
2561
2562 impl View {
2563 fn new(other: Option<ViewHandle<View>>, ctx: &mut ViewContext<Self>) -> Self {
2564 if let Some(other) = other.as_ref() {
2565 ctx.subscribe_to_view(other, |me, _, event, _| {
2566 me.events.push(format!("observed event {}", event));
2567 });
2568 }
2569 Self {
2570 other,
2571 events: Vec::new(),
2572 }
2573 }
2574 }
2575
2576 App::test((), |mut app| async move {
2577 let app = &mut app;
2578 let (window_id, _) = app.add_window(|ctx| View::new(None, ctx));
2579 let handle_1 = app.add_view(window_id, |ctx| View::new(None, ctx));
2580 let handle_2 = app.add_view(window_id, |ctx| View::new(Some(handle_1.clone()), ctx));
2581 assert_eq!(app.0.borrow().ctx.windows[&window_id].views.len(), 3);
2582
2583 handle_1.update(app, |view, ctx| {
2584 view.events.push("updated".into());
2585 ctx.emit(1);
2586 ctx.emit(2);
2587 });
2588 handle_1.read(app, |view, _| {
2589 assert_eq!(view.events, vec!["updated".to_string()]);
2590 });
2591 handle_2.read(app, |view, _| {
2592 assert_eq!(
2593 view.events,
2594 vec![
2595 "observed event 1".to_string(),
2596 "observed event 2".to_string(),
2597 ]
2598 );
2599 });
2600
2601 handle_2.update(app, |view, _| {
2602 drop(handle_1);
2603 view.other.take();
2604 });
2605
2606 let app_state = app.0.borrow();
2607 assert_eq!(app_state.ctx.windows[&window_id].views.len(), 2);
2608 assert!(app_state.subscriptions.is_empty());
2609 assert!(app_state.observations.is_empty());
2610 })
2611 }
2612
2613 #[test]
2614 fn test_subscribe_and_emit_from_view() {
2615 #[derive(Default)]
2616 struct View {
2617 events: Vec<usize>,
2618 }
2619
2620 impl Entity for View {
2621 type Event = usize;
2622 }
2623
2624 impl super::View for View {
2625 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2626 Empty::new().boxed()
2627 }
2628
2629 fn ui_name() -> &'static str {
2630 "View"
2631 }
2632 }
2633
2634 struct Model;
2635
2636 impl Entity for Model {
2637 type Event = usize;
2638 }
2639
2640 App::test((), |mut app| async move {
2641 let app = &mut app;
2642 let (window_id, handle_1) = app.add_window(|_| View::default());
2643 let handle_2 = app.add_view(window_id, |_| View::default());
2644 let handle_2b = handle_2.clone();
2645 let handle_3 = app.add_model(|_| Model);
2646
2647 handle_1.update(app, |_, c| {
2648 c.subscribe_to_view(&handle_2, move |me, _, event, c| {
2649 me.events.push(*event);
2650
2651 c.subscribe_to_view(&handle_2b, |me, _, event, _| {
2652 me.events.push(*event * 2);
2653 });
2654 });
2655
2656 c.subscribe_to_model(&handle_3, |me, _, event, _| {
2657 me.events.push(*event);
2658 })
2659 });
2660
2661 handle_2.update(app, |_, c| c.emit(7));
2662 handle_1.read(app, |view, _| assert_eq!(view.events, vec![7]));
2663
2664 handle_2.update(app, |_, c| c.emit(5));
2665 handle_1.read(app, |view, _| assert_eq!(view.events, vec![7, 10, 5]));
2666
2667 handle_3.update(app, |_, c| c.emit(9));
2668 handle_1.read(app, |view, _| assert_eq!(view.events, vec![7, 10, 5, 9]));
2669 })
2670 }
2671
2672 #[test]
2673 fn test_dropping_subscribers() {
2674 struct View;
2675
2676 impl Entity for View {
2677 type Event = ();
2678 }
2679
2680 impl super::View for View {
2681 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2682 Empty::new().boxed()
2683 }
2684
2685 fn ui_name() -> &'static str {
2686 "View"
2687 }
2688 }
2689
2690 struct Model;
2691
2692 impl Entity for Model {
2693 type Event = ();
2694 }
2695
2696 App::test((), |mut app| async move {
2697 let app = &mut app;
2698
2699 let (window_id, _) = app.add_window(|_| View);
2700 let observing_view = app.add_view(window_id, |_| View);
2701 let emitting_view = app.add_view(window_id, |_| View);
2702 let observing_model = app.add_model(|_| Model);
2703 let observed_model = app.add_model(|_| Model);
2704
2705 observing_view.update(app, |_, ctx| {
2706 ctx.subscribe_to_view(&emitting_view, |_, _, _, _| {});
2707 ctx.subscribe_to_model(&observed_model, |_, _, _, _| {});
2708 });
2709 observing_model.update(app, |_, ctx| {
2710 ctx.subscribe(&observed_model, |_, _, _| {});
2711 });
2712
2713 app.update(|_| {
2714 drop(observing_view);
2715 drop(observing_model);
2716 });
2717
2718 emitting_view.update(app, |_, ctx| ctx.emit(()));
2719 observed_model.update(app, |_, ctx| ctx.emit(()));
2720 })
2721 }
2722
2723 #[test]
2724 fn test_observe_and_notify_from_view() {
2725 #[derive(Default)]
2726 struct View {
2727 events: Vec<usize>,
2728 }
2729
2730 impl Entity for View {
2731 type Event = usize;
2732 }
2733
2734 impl super::View for View {
2735 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2736 Empty::new().boxed()
2737 }
2738
2739 fn ui_name() -> &'static str {
2740 "View"
2741 }
2742 }
2743
2744 #[derive(Default)]
2745 struct Model {
2746 count: usize,
2747 }
2748
2749 impl Entity for Model {
2750 type Event = ();
2751 }
2752
2753 App::test((), |mut app| async move {
2754 let app = &mut app;
2755 let (_, view) = app.add_window(|_| View::default());
2756 let model = app.add_model(|_| Model::default());
2757
2758 view.update(app, |_, c| {
2759 c.observe(&model, |me, observed, c| {
2760 me.events.push(observed.as_ref(c).count)
2761 });
2762 });
2763
2764 model.update(app, |model, c| {
2765 model.count = 11;
2766 c.notify();
2767 });
2768 view.read(app, |view, _| assert_eq!(view.events, vec![11]));
2769 })
2770 }
2771
2772 #[test]
2773 fn test_dropping_observers() {
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 observing_model = app.add_model(|_| Model);
2802 let observed_model = app.add_model(|_| Model);
2803
2804 observing_view.update(app, |_, ctx| {
2805 ctx.observe(&observed_model, |_, _, _| {});
2806 });
2807 observing_model.update(app, |_, ctx| {
2808 ctx.observe(&observed_model, |_, _, _| {});
2809 });
2810
2811 app.update(|_| {
2812 drop(observing_view);
2813 drop(observing_model);
2814 });
2815
2816 observed_model.update(app, |_, ctx| ctx.notify());
2817 })
2818 }
2819
2820 #[test]
2821 fn test_focus() {
2822 #[derive(Default)]
2823 struct View {
2824 events: Vec<String>,
2825 }
2826
2827 impl Entity for View {
2828 type Event = String;
2829 }
2830
2831 impl super::View for View {
2832 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2833 Empty::new().boxed()
2834 }
2835
2836 fn ui_name() -> &'static str {
2837 "View"
2838 }
2839
2840 fn on_focus(&mut self, ctx: &mut ViewContext<Self>) {
2841 self.events.push("self focused".into());
2842 ctx.emit("focused".into());
2843 }
2844
2845 fn on_blur(&mut self, ctx: &mut ViewContext<Self>) {
2846 self.events.push("self blurred".into());
2847 ctx.emit("blurred".into());
2848 }
2849 }
2850
2851 App::test((), |mut app| async move {
2852 let app = &mut app;
2853 let (window_id, view_1) = app.add_window(|_| View::default());
2854 let view_2 = app.add_view(window_id, |_| View::default());
2855
2856 view_1.update(app, |_, ctx| {
2857 ctx.subscribe_to_view(&view_2, |view_1, _, event, _| {
2858 view_1.events.push(format!("view 2 {}", event));
2859 });
2860 ctx.focus(&view_2);
2861 });
2862
2863 view_1.update(app, |_, ctx| {
2864 ctx.focus(&view_1);
2865 });
2866
2867 view_1.read(app, |view_1, _| {
2868 assert_eq!(
2869 view_1.events,
2870 [
2871 "self focused".to_string(),
2872 "self blurred".to_string(),
2873 "view 2 focused".to_string(),
2874 "self focused".to_string(),
2875 "view 2 blurred".to_string(),
2876 ],
2877 );
2878 });
2879 })
2880 }
2881
2882 #[test]
2883 fn test_spawn_from_view() {
2884 #[derive(Default)]
2885 struct View {
2886 count: usize,
2887 }
2888
2889 impl Entity for View {
2890 type Event = ();
2891 }
2892
2893 impl super::View for View {
2894 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2895 Empty::new().boxed()
2896 }
2897
2898 fn ui_name() -> &'static str {
2899 "View"
2900 }
2901 }
2902
2903 App::test((), |mut app| async move {
2904 let (_, handle) = app.add_window(|_| View::default());
2905 handle
2906 .update(&mut app, |_, c| {
2907 c.spawn(async { 7 }, |me, output, _| {
2908 me.count = output;
2909 })
2910 })
2911 .await;
2912 handle.read(&app, |view, _| assert_eq!(view.count, 7));
2913 handle
2914 .update(&mut app, |_, c| {
2915 c.spawn(async { 14 }, |me, output, _| {
2916 me.count = output;
2917 })
2918 })
2919 .await;
2920 handle.read(&app, |view, _| assert_eq!(view.count, 14));
2921 });
2922 }
2923
2924 #[test]
2925 fn test_spawn_stream_local_from_view() {
2926 #[derive(Default)]
2927 struct View {
2928 events: Vec<Option<usize>>,
2929 }
2930
2931 impl Entity for View {
2932 type Event = ();
2933 }
2934
2935 impl super::View for View {
2936 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2937 Empty::new().boxed()
2938 }
2939
2940 fn ui_name() -> &'static str {
2941 "View"
2942 }
2943 }
2944
2945 App::test((), |mut app| async move {
2946 let (_, handle) = app.add_window(|_| View::default());
2947 handle
2948 .update(&mut app, |_, c| {
2949 c.spawn_stream(
2950 smol::stream::iter(vec![1_usize, 2, 3]),
2951 |me, output, _| {
2952 me.events.push(Some(output));
2953 },
2954 |me, _| {
2955 me.events.push(None);
2956 },
2957 )
2958 })
2959 .await;
2960
2961 handle.read(&app, |view, _| {
2962 assert_eq!(view.events, [Some(1), Some(2), Some(3), None])
2963 });
2964 });
2965 }
2966
2967 #[test]
2968 fn test_dispatch_action() {
2969 struct ViewA {
2970 id: usize,
2971 }
2972
2973 impl Entity for ViewA {
2974 type Event = ();
2975 }
2976
2977 impl View for ViewA {
2978 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2979 Empty::new().boxed()
2980 }
2981
2982 fn ui_name() -> &'static str {
2983 "View"
2984 }
2985 }
2986
2987 struct ViewB {
2988 id: usize,
2989 }
2990
2991 impl Entity for ViewB {
2992 type Event = ();
2993 }
2994
2995 impl View for ViewB {
2996 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2997 Empty::new().boxed()
2998 }
2999
3000 fn ui_name() -> &'static str {
3001 "View"
3002 }
3003 }
3004
3005 struct ActionArg {
3006 foo: String,
3007 }
3008
3009 App::test((), |mut app| async move {
3010 let actions = Rc::new(RefCell::new(Vec::new()));
3011
3012 let actions_clone = actions.clone();
3013 app.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
3014 actions_clone.borrow_mut().push("global a".to_string());
3015 });
3016
3017 let actions_clone = actions.clone();
3018 app.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
3019 actions_clone.borrow_mut().push("global b".to_string());
3020 });
3021
3022 let actions_clone = actions.clone();
3023 app.add_action("action", move |view: &mut ViewA, arg: &ActionArg, ctx| {
3024 assert_eq!(arg.foo, "bar");
3025 ctx.propagate_action();
3026 actions_clone.borrow_mut().push(format!("{} a", view.id));
3027 });
3028
3029 let actions_clone = actions.clone();
3030 app.add_action("action", move |view: &mut ViewA, _: &ActionArg, ctx| {
3031 if view.id != 1 {
3032 ctx.propagate_action();
3033 }
3034 actions_clone.borrow_mut().push(format!("{} b", view.id));
3035 });
3036
3037 let actions_clone = actions.clone();
3038 app.add_action("action", move |view: &mut ViewB, _: &ActionArg, ctx| {
3039 ctx.propagate_action();
3040 actions_clone.borrow_mut().push(format!("{} c", view.id));
3041 });
3042
3043 let actions_clone = actions.clone();
3044 app.add_action("action", move |view: &mut ViewB, _: &ActionArg, ctx| {
3045 ctx.propagate_action();
3046 actions_clone.borrow_mut().push(format!("{} d", view.id));
3047 });
3048
3049 let (window_id, view_1) = app.add_window(|_| ViewA { id: 1 });
3050 let view_2 = app.add_view(window_id, |_| ViewB { id: 2 });
3051 let view_3 = app.add_view(window_id, |_| ViewA { id: 3 });
3052 let view_4 = app.add_view(window_id, |_| ViewB { id: 4 });
3053
3054 app.dispatch_action(
3055 window_id,
3056 vec![view_1.id(), view_2.id(), view_3.id(), view_4.id()],
3057 "action",
3058 ActionArg { foo: "bar".into() },
3059 );
3060
3061 assert_eq!(
3062 *actions.borrow(),
3063 vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "1 b"]
3064 );
3065
3066 // Remove view_1, which doesn't propagate the action
3067 actions.borrow_mut().clear();
3068 app.dispatch_action(
3069 window_id,
3070 vec![view_2.id(), view_3.id(), view_4.id()],
3071 "action",
3072 ActionArg { foo: "bar".into() },
3073 );
3074
3075 assert_eq!(
3076 *actions.borrow(),
3077 vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "global b", "global a"]
3078 );
3079 })
3080 }
3081
3082 #[test]
3083 fn test_dispatch_keystroke() -> Result<()> {
3084 use std::cell::Cell;
3085
3086 #[derive(Clone)]
3087 struct ActionArg {
3088 key: String,
3089 }
3090
3091 struct View {
3092 id: usize,
3093 keymap_context: keymap::Context,
3094 }
3095
3096 impl Entity for View {
3097 type Event = ();
3098 }
3099
3100 impl super::View for View {
3101 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3102 Empty::new().boxed()
3103 }
3104
3105 fn ui_name() -> &'static str {
3106 "View"
3107 }
3108
3109 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
3110 self.keymap_context.clone()
3111 }
3112 }
3113
3114 impl View {
3115 fn new(id: usize) -> Self {
3116 View {
3117 id,
3118 keymap_context: keymap::Context::default(),
3119 }
3120 }
3121 }
3122
3123 App::test((), |mut app| async move {
3124 let mut view_1 = View::new(1);
3125 let mut view_2 = View::new(2);
3126 let mut view_3 = View::new(3);
3127 view_1.keymap_context.set.insert("a".into());
3128 view_2.keymap_context.set.insert("b".into());
3129 view_3.keymap_context.set.insert("c".into());
3130
3131 let (window_id, view_1) = app.add_window(|_| view_1);
3132 let view_2 = app.add_view(window_id, |_| view_2);
3133 let view_3 = app.add_view(window_id, |_| view_3);
3134
3135 // This keymap's only binding dispatches an action on view 2 because that view will have
3136 // "a" and "b" in its context, but not "c".
3137 let binding = keymap::Binding::new("a", "action", Some("a && b && !c"))
3138 .with_arg(ActionArg { key: "a".into() });
3139 app.add_bindings(vec![binding]);
3140
3141 let handled_action = Rc::new(Cell::new(false));
3142 let handled_action_clone = handled_action.clone();
3143 app.add_action("action", move |view: &mut View, arg: &ActionArg, _ctx| {
3144 handled_action_clone.set(true);
3145 assert_eq!(view.id, 2);
3146 assert_eq!(arg.key, "a");
3147 });
3148
3149 app.dispatch_keystroke(
3150 window_id,
3151 vec![view_1.id(), view_2.id(), view_3.id()],
3152 &Keystroke::parse("a")?,
3153 )?;
3154
3155 assert!(handled_action.get());
3156 Ok(())
3157 })
3158 }
3159
3160 // #[test]
3161 // fn test_ui_and_window_updates() {
3162 // struct View {
3163 // count: usize,
3164 // }
3165
3166 // impl Entity for View {
3167 // type Event = ();
3168 // }
3169
3170 // impl super::View for View {
3171 // fn render<'a>(&self, _: &AppContext) -> ElementBox {
3172 // Empty::new().boxed()
3173 // }
3174
3175 // fn ui_name() -> &'static str {
3176 // "View"
3177 // }
3178 // }
3179
3180 // App::test(|mut app| async move {
3181 // let (window_id, _) = app.add_window(|_| View { count: 3 });
3182 // let view_1 = app.add_view(window_id, |_| View { count: 1 });
3183 // let view_2 = app.add_view(window_id, |_| View { count: 2 });
3184
3185 // // Ensure that registering for UI updates after mutating the app still gives us all the
3186 // // updates.
3187 // let ui_updates = Rc::new(RefCell::new(Vec::new()));
3188 // let ui_updates_ = ui_updates.clone();
3189 // app.on_ui_update(move |update, _| ui_updates_.borrow_mut().push(update));
3190
3191 // assert_eq!(
3192 // ui_updates.borrow_mut().drain(..).collect::<Vec<_>>(),
3193 // vec![UiUpdate::OpenWindow {
3194 // window_id,
3195 // width: 1024.0,
3196 // height: 768.0,
3197 // }]
3198 // );
3199
3200 // let window_invalidations = Rc::new(RefCell::new(Vec::new()));
3201 // let window_invalidations_ = window_invalidations.clone();
3202 // app.on_window_invalidated(window_id, move |update, _| {
3203 // window_invalidations_.borrow_mut().push(update)
3204 // });
3205
3206 // let view_2_id = view_2.id();
3207 // view_1.update(&mut app, |view, ctx| {
3208 // view.count = 7;
3209 // ctx.notify();
3210 // drop(view_2);
3211 // });
3212
3213 // let invalidation = window_invalidations.borrow_mut().drain(..).next().unwrap();
3214 // assert_eq!(invalidation.updated.len(), 1);
3215 // assert!(invalidation.updated.contains(&view_1.id()));
3216 // assert_eq!(invalidation.removed, vec![view_2_id]);
3217
3218 // let view_3 = view_1.update(&mut app, |_, ctx| ctx.add_view(|_| View { count: 8 }));
3219
3220 // let invalidation = window_invalidations.borrow_mut().drain(..).next().unwrap();
3221 // assert_eq!(invalidation.updated.len(), 1);
3222 // assert!(invalidation.updated.contains(&view_3.id()));
3223 // assert!(invalidation.removed.is_empty());
3224
3225 // view_3
3226 // .update(&mut app, |_, ctx| {
3227 // ctx.spawn_local(async { 9 }, |me, output, ctx| {
3228 // me.count = output;
3229 // ctx.notify();
3230 // })
3231 // })
3232 // .await;
3233
3234 // let invalidation = window_invalidations.borrow_mut().drain(..).next().unwrap();
3235 // assert_eq!(invalidation.updated.len(), 1);
3236 // assert!(invalidation.updated.contains(&view_3.id()));
3237 // assert!(invalidation.removed.is_empty());
3238 // });
3239 // }
3240
3241 #[test]
3242 fn test_finish_pending_tasks() {
3243 struct View;
3244
3245 impl Entity for View {
3246 type Event = ();
3247 }
3248
3249 impl super::View for View {
3250 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3251 Empty::new().boxed()
3252 }
3253
3254 fn ui_name() -> &'static str {
3255 "View"
3256 }
3257 }
3258
3259 struct Model;
3260
3261 impl Entity for Model {
3262 type Event = ();
3263 }
3264
3265 App::test((), |mut app| async move {
3266 let model = app.add_model(|_| Model);
3267 let (_, view) = app.add_window(|_| View);
3268
3269 model.update(&mut app, |_, ctx| {
3270 let _ = ctx.spawn(async {}, |_, _, _| {});
3271 let _ = ctx.spawn(async {}, |_, _, _| {});
3272 let _ =
3273 ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {});
3274 });
3275
3276 view.update(&mut app, |_, ctx| {
3277 let _ = ctx.spawn(async {}, |_, _, _| {});
3278 let _ = ctx.spawn(async {}, |_, _, _| {});
3279 let _ =
3280 ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {});
3281 });
3282
3283 assert!(!app.0.borrow().future_handlers.is_empty());
3284 app.finish_pending_tasks().await;
3285 assert!(app.0.borrow().future_handlers.is_empty());
3286 app.finish_pending_tasks().await; // Don't block if there are no tasks
3287 });
3288 }
3289}