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