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