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