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