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