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