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