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 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
1766 where
1767 F: FnOnce(WeakModelHandle<T>, AsyncAppContext) -> Fut,
1768 Fut: 'static + Future<Output = S>,
1769 S: 'static,
1770 {
1771 let handle = self.handle().downgrade();
1772 self.app.spawn(|cx| f(handle, cx))
1773 }
1774}
1775
1776impl<M> AsRef<AppContext> for ModelContext<'_, M> {
1777 fn as_ref(&self) -> &AppContext {
1778 &self.app.cx
1779 }
1780}
1781
1782impl<M> AsMut<MutableAppContext> for ModelContext<'_, M> {
1783 fn as_mut(&mut self) -> &mut MutableAppContext {
1784 self.app
1785 }
1786}
1787
1788impl<M> ReadModel for ModelContext<'_, M> {
1789 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1790 self.app.read_model(handle)
1791 }
1792}
1793
1794impl<M> UpdateModel for ModelContext<'_, M> {
1795 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1796 where
1797 T: Entity,
1798 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1799 {
1800 self.app.update_model(handle, update)
1801 }
1802}
1803
1804pub struct ViewContext<'a, T: ?Sized> {
1805 app: &'a mut MutableAppContext,
1806 window_id: usize,
1807 view_id: usize,
1808 view_type: PhantomData<T>,
1809 halt_action_dispatch: bool,
1810}
1811
1812impl<'a, T: View> ViewContext<'a, T> {
1813 fn new(app: &'a mut MutableAppContext, window_id: usize, view_id: usize) -> Self {
1814 Self {
1815 app,
1816 window_id,
1817 view_id,
1818 view_type: PhantomData,
1819 halt_action_dispatch: true,
1820 }
1821 }
1822
1823 pub fn handle(&self) -> ViewHandle<T> {
1824 ViewHandle::new(self.window_id, self.view_id, &self.app.cx.ref_counts)
1825 }
1826
1827 pub fn window_id(&self) -> usize {
1828 self.window_id
1829 }
1830
1831 pub fn view_id(&self) -> usize {
1832 self.view_id
1833 }
1834
1835 pub fn foreground(&self) -> &Rc<executor::Foreground> {
1836 self.app.foreground()
1837 }
1838
1839 pub fn background_executor(&self) -> &Arc<executor::Background> {
1840 &self.app.cx.background
1841 }
1842
1843 pub fn platform(&self) -> Arc<dyn Platform> {
1844 self.app.platform()
1845 }
1846
1847 pub fn prompt<F>(&self, level: PromptLevel, msg: &str, answers: &[&str], done_fn: F)
1848 where
1849 F: 'static + FnOnce(usize, &mut MutableAppContext),
1850 {
1851 self.app
1852 .prompt(self.window_id, level, msg, answers, done_fn)
1853 }
1854
1855 pub fn prompt_for_paths<F>(&self, options: PathPromptOptions, done_fn: F)
1856 where
1857 F: 'static + FnOnce(Option<Vec<PathBuf>>, &mut MutableAppContext),
1858 {
1859 self.app.prompt_for_paths(options, done_fn)
1860 }
1861
1862 pub fn prompt_for_new_path<F>(&self, directory: &Path, done_fn: F)
1863 where
1864 F: 'static + FnOnce(Option<PathBuf>, &mut MutableAppContext),
1865 {
1866 self.app.prompt_for_new_path(directory, done_fn)
1867 }
1868
1869 pub fn debug_elements(&self) -> crate::json::Value {
1870 self.app.debug_elements(self.window_id).unwrap()
1871 }
1872
1873 pub fn focus<S>(&mut self, handle: S)
1874 where
1875 S: Into<AnyViewHandle>,
1876 {
1877 let handle = handle.into();
1878 self.app.pending_effects.push_back(Effect::Focus {
1879 window_id: handle.window_id,
1880 view_id: handle.view_id,
1881 });
1882 }
1883
1884 pub fn focus_self(&mut self) {
1885 self.app.pending_effects.push_back(Effect::Focus {
1886 window_id: self.window_id,
1887 view_id: self.view_id,
1888 });
1889 }
1890
1891 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
1892 where
1893 S: Entity,
1894 F: FnOnce(&mut ModelContext<S>) -> S,
1895 {
1896 self.app.add_model(build_model)
1897 }
1898
1899 pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
1900 where
1901 S: View,
1902 F: FnOnce(&mut ViewContext<S>) -> S,
1903 {
1904 self.app.add_view(self.window_id, build_view)
1905 }
1906
1907 pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
1908 where
1909 S: View,
1910 F: FnOnce(&mut ViewContext<S>) -> Option<S>,
1911 {
1912 self.app.add_option_view(self.window_id, build_view)
1913 }
1914
1915 pub fn subscribe_to_model<E, F>(&mut self, handle: &ModelHandle<E>, mut callback: F)
1916 where
1917 E: Entity,
1918 E::Event: 'static,
1919 F: 'static + FnMut(&mut T, ModelHandle<E>, &E::Event, &mut ViewContext<T>),
1920 {
1921 let emitter_handle = handle.downgrade();
1922 self.subscribe(handle, move |model, payload, cx| {
1923 if let Some(emitter_handle) = emitter_handle.upgrade(cx.as_ref()) {
1924 callback(model, emitter_handle, payload, cx);
1925 }
1926 });
1927 }
1928
1929 pub fn subscribe_to_view<V, F>(&mut self, handle: &ViewHandle<V>, mut callback: F)
1930 where
1931 V: View,
1932 V::Event: 'static,
1933 F: 'static + FnMut(&mut T, ViewHandle<V>, &V::Event, &mut ViewContext<T>),
1934 {
1935 let emitter_handle = handle.downgrade();
1936 self.subscribe(handle, move |view, payload, cx| {
1937 if let Some(emitter_handle) = emitter_handle.upgrade(cx.as_ref()) {
1938 callback(view, emitter_handle, payload, cx);
1939 }
1940 });
1941 }
1942
1943 pub fn subscribe<E, F>(&mut self, handle: &impl Handle<E>, mut callback: F)
1944 where
1945 E: Entity,
1946 E::Event: 'static,
1947 F: 'static + FnMut(&mut T, &E::Event, &mut ViewContext<T>),
1948 {
1949 self.app
1950 .subscriptions
1951 .entry(handle.id())
1952 .or_default()
1953 .push(Subscription::FromView {
1954 window_id: self.window_id,
1955 view_id: self.view_id,
1956 callback: Box::new(move |entity, payload, app, window_id, view_id| {
1957 let entity = entity.downcast_mut().expect("downcast is type safe");
1958 let payload = payload.downcast_ref().expect("downcast is type safe");
1959 let mut cx = ViewContext::new(app, window_id, view_id);
1960 callback(entity, payload, &mut cx);
1961 }),
1962 });
1963 }
1964
1965 pub fn emit(&mut self, payload: T::Event) {
1966 self.app.pending_effects.push_back(Effect::Event {
1967 entity_id: self.view_id,
1968 payload: Box::new(payload),
1969 });
1970 }
1971
1972 pub fn observe_model<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1973 where
1974 S: Entity,
1975 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ViewContext<T>),
1976 {
1977 self.app
1978 .model_observations
1979 .entry(handle.id())
1980 .or_default()
1981 .push(ModelObservation::FromView {
1982 window_id: self.window_id,
1983 view_id: self.view_id,
1984 callback: Box::new(move |view, observed_id, app, window_id, view_id| {
1985 let view = view.downcast_mut().expect("downcast is type safe");
1986 let observed = ModelHandle::new(observed_id, &app.cx.ref_counts);
1987 let mut cx = ViewContext::new(app, window_id, view_id);
1988 callback(view, observed, &mut cx);
1989 }),
1990 });
1991 }
1992
1993 pub fn observe_view<S, F>(&mut self, handle: &ViewHandle<S>, mut callback: F)
1994 where
1995 S: View,
1996 F: 'static + FnMut(&mut T, ViewHandle<S>, &mut ViewContext<T>),
1997 {
1998 self.app
1999 .view_observations
2000 .entry(handle.id())
2001 .or_default()
2002 .push(ViewObservation {
2003 window_id: self.window_id,
2004 view_id: self.view_id,
2005 callback: Box::new(
2006 move |view,
2007 observed_view_id,
2008 observed_window_id,
2009 app,
2010 observing_window_id,
2011 observing_view_id| {
2012 let view = view.downcast_mut().expect("downcast is type safe");
2013 let observed_handle = ViewHandle::new(
2014 observed_view_id,
2015 observed_window_id,
2016 &app.cx.ref_counts,
2017 );
2018 let mut cx = ViewContext::new(app, observing_window_id, observing_view_id);
2019 callback(view, observed_handle, &mut cx);
2020 },
2021 ),
2022 });
2023 }
2024
2025 pub fn notify(&mut self) {
2026 self.app.notify_view(self.window_id, self.view_id);
2027 }
2028
2029 pub fn propagate_action(&mut self) {
2030 self.halt_action_dispatch = false;
2031 }
2032
2033 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
2034 where
2035 F: FnOnce(ViewHandle<T>, AsyncAppContext) -> Fut,
2036 Fut: 'static + Future<Output = S>,
2037 S: 'static,
2038 {
2039 let handle = self.handle();
2040 self.app.spawn(|cx| f(handle, cx))
2041 }
2042}
2043
2044impl AsRef<AppContext> for &AppContext {
2045 fn as_ref(&self) -> &AppContext {
2046 self
2047 }
2048}
2049
2050impl<M> AsRef<AppContext> for ViewContext<'_, M> {
2051 fn as_ref(&self) -> &AppContext {
2052 &self.app.cx
2053 }
2054}
2055
2056impl<M> AsMut<MutableAppContext> for ViewContext<'_, M> {
2057 fn as_mut(&mut self) -> &mut MutableAppContext {
2058 self.app
2059 }
2060}
2061
2062impl<V> ReadModel for ViewContext<'_, V> {
2063 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2064 self.app.read_model(handle)
2065 }
2066}
2067
2068impl<V: View> UpdateModel for ViewContext<'_, V> {
2069 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
2070 where
2071 T: Entity,
2072 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
2073 {
2074 self.app.update_model(handle, update)
2075 }
2076}
2077
2078impl<V: View> ReadView for ViewContext<'_, V> {
2079 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2080 self.app.read_view(handle)
2081 }
2082}
2083
2084impl<V: View> UpdateView for ViewContext<'_, V> {
2085 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
2086 where
2087 T: View,
2088 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
2089 {
2090 self.app.update_view(handle, update)
2091 }
2092}
2093
2094pub trait Handle<T> {
2095 fn id(&self) -> usize;
2096 fn location(&self) -> EntityLocation;
2097}
2098
2099#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
2100pub enum EntityLocation {
2101 Model(usize),
2102 View(usize, usize),
2103}
2104
2105pub struct ModelHandle<T> {
2106 model_id: usize,
2107 model_type: PhantomData<T>,
2108 ref_counts: Arc<Mutex<RefCounts>>,
2109}
2110
2111impl<T: Entity> ModelHandle<T> {
2112 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
2113 ref_counts.lock().inc_model(model_id);
2114 Self {
2115 model_id,
2116 model_type: PhantomData,
2117 ref_counts: ref_counts.clone(),
2118 }
2119 }
2120
2121 pub fn downgrade(&self) -> WeakModelHandle<T> {
2122 WeakModelHandle::new(self.model_id)
2123 }
2124
2125 pub fn id(&self) -> usize {
2126 self.model_id
2127 }
2128
2129 pub fn read<'a, C: ReadModel>(&self, cx: &'a C) -> &'a T {
2130 cx.read_model(self)
2131 }
2132
2133 pub fn read_with<'a, C, F, S>(&self, cx: &C, read: F) -> S
2134 where
2135 C: ReadModelWith,
2136 F: FnOnce(&T, &AppContext) -> S,
2137 {
2138 cx.read_model_with(self, read)
2139 }
2140
2141 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
2142 where
2143 C: UpdateModel,
2144 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
2145 {
2146 cx.update_model(self, update)
2147 }
2148
2149 pub fn condition(
2150 &self,
2151 cx: &TestAppContext,
2152 mut predicate: impl FnMut(&T, &AppContext) -> bool,
2153 ) -> impl Future<Output = ()> {
2154 let (tx, mut rx) = mpsc::channel(1024);
2155
2156 let mut cx = cx.cx.borrow_mut();
2157 self.update(&mut *cx, |_, cx| {
2158 cx.observe(self, {
2159 let mut tx = tx.clone();
2160 move |_, _, _| {
2161 tx.blocking_send(()).ok();
2162 }
2163 });
2164 cx.subscribe(self, {
2165 let mut tx = tx.clone();
2166 move |_, _, _| {
2167 tx.blocking_send(()).ok();
2168 }
2169 })
2170 });
2171
2172 let cx = cx.weak_self.as_ref().unwrap().upgrade().unwrap();
2173 let handle = self.downgrade();
2174 let duration = if std::env::var("CI").is_ok() {
2175 Duration::from_secs(5)
2176 } else {
2177 Duration::from_secs(1)
2178 };
2179
2180 async move {
2181 timeout(duration, async move {
2182 loop {
2183 {
2184 let cx = cx.borrow();
2185 let cx = cx.as_ref();
2186 if predicate(
2187 handle
2188 .upgrade(cx)
2189 .expect("model dropped with pending condition")
2190 .read(cx),
2191 cx,
2192 ) {
2193 break;
2194 }
2195 }
2196
2197 rx.recv()
2198 .await
2199 .expect("model dropped with pending condition");
2200 }
2201 })
2202 .await
2203 .expect("condition timed out");
2204 }
2205 }
2206}
2207
2208impl<T> Clone for ModelHandle<T> {
2209 fn clone(&self) -> Self {
2210 self.ref_counts.lock().inc_model(self.model_id);
2211 Self {
2212 model_id: self.model_id,
2213 model_type: PhantomData,
2214 ref_counts: self.ref_counts.clone(),
2215 }
2216 }
2217}
2218
2219impl<T> PartialEq for ModelHandle<T> {
2220 fn eq(&self, other: &Self) -> bool {
2221 self.model_id == other.model_id
2222 }
2223}
2224
2225impl<T> Eq for ModelHandle<T> {}
2226
2227impl<T> Hash for ModelHandle<T> {
2228 fn hash<H: Hasher>(&self, state: &mut H) {
2229 self.model_id.hash(state);
2230 }
2231}
2232
2233impl<T> std::borrow::Borrow<usize> for ModelHandle<T> {
2234 fn borrow(&self) -> &usize {
2235 &self.model_id
2236 }
2237}
2238
2239impl<T> Debug for ModelHandle<T> {
2240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2241 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
2242 .field(&self.model_id)
2243 .finish()
2244 }
2245}
2246
2247unsafe impl<T> Send for ModelHandle<T> {}
2248unsafe impl<T> Sync for ModelHandle<T> {}
2249
2250impl<T> Drop for ModelHandle<T> {
2251 fn drop(&mut self) {
2252 self.ref_counts.lock().dec_model(self.model_id);
2253 }
2254}
2255
2256impl<T> Handle<T> for ModelHandle<T> {
2257 fn id(&self) -> usize {
2258 self.model_id
2259 }
2260
2261 fn location(&self) -> EntityLocation {
2262 EntityLocation::Model(self.model_id)
2263 }
2264}
2265
2266pub struct WeakModelHandle<T> {
2267 model_id: usize,
2268 model_type: PhantomData<T>,
2269}
2270
2271impl<T: Entity> WeakModelHandle<T> {
2272 fn new(model_id: usize) -> Self {
2273 Self {
2274 model_id,
2275 model_type: PhantomData,
2276 }
2277 }
2278
2279 pub fn upgrade(&self, cx: impl AsRef<AppContext>) -> Option<ModelHandle<T>> {
2280 let cx = cx.as_ref();
2281 if cx.models.contains_key(&self.model_id) {
2282 Some(ModelHandle::new(self.model_id, &cx.ref_counts))
2283 } else {
2284 None
2285 }
2286 }
2287}
2288
2289impl<T> Hash for WeakModelHandle<T> {
2290 fn hash<H: Hasher>(&self, state: &mut H) {
2291 self.model_id.hash(state)
2292 }
2293}
2294
2295impl<T> PartialEq for WeakModelHandle<T> {
2296 fn eq(&self, other: &Self) -> bool {
2297 self.model_id == other.model_id
2298 }
2299}
2300
2301impl<T> Eq for WeakModelHandle<T> {}
2302
2303impl<T> Clone for WeakModelHandle<T> {
2304 fn clone(&self) -> Self {
2305 Self {
2306 model_id: self.model_id,
2307 model_type: PhantomData,
2308 }
2309 }
2310}
2311
2312pub struct ViewHandle<T> {
2313 window_id: usize,
2314 view_id: usize,
2315 view_type: PhantomData<T>,
2316 ref_counts: Arc<Mutex<RefCounts>>,
2317}
2318
2319impl<T: View> ViewHandle<T> {
2320 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
2321 ref_counts.lock().inc_view(window_id, view_id);
2322 Self {
2323 window_id,
2324 view_id,
2325 view_type: PhantomData,
2326 ref_counts: ref_counts.clone(),
2327 }
2328 }
2329
2330 pub fn downgrade(&self) -> WeakViewHandle<T> {
2331 WeakViewHandle::new(self.window_id, self.view_id)
2332 }
2333
2334 pub fn window_id(&self) -> usize {
2335 self.window_id
2336 }
2337
2338 pub fn id(&self) -> usize {
2339 self.view_id
2340 }
2341
2342 pub fn read<'a, C: ReadView>(&self, cx: &'a C) -> &'a T {
2343 cx.read_view(self)
2344 }
2345
2346 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
2347 where
2348 C: ReadViewWith,
2349 F: FnOnce(&T, &AppContext) -> S,
2350 {
2351 cx.read_view_with(self, read)
2352 }
2353
2354 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
2355 where
2356 C: UpdateView,
2357 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
2358 {
2359 cx.update_view(self, update)
2360 }
2361
2362 pub fn is_focused(&self, cx: &AppContext) -> bool {
2363 cx.focused_view_id(self.window_id)
2364 .map_or(false, |focused_id| focused_id == self.view_id)
2365 }
2366
2367 pub fn condition(
2368 &self,
2369 cx: &TestAppContext,
2370 mut predicate: impl FnMut(&T, &AppContext) -> bool,
2371 ) -> impl Future<Output = ()> {
2372 let (tx, mut rx) = mpsc::channel(1024);
2373
2374 let mut cx = cx.cx.borrow_mut();
2375 self.update(&mut *cx, |_, cx| {
2376 cx.observe_view(self, {
2377 let mut tx = tx.clone();
2378 move |_, _, _| {
2379 tx.blocking_send(()).ok();
2380 }
2381 });
2382
2383 cx.subscribe(self, {
2384 let mut tx = tx.clone();
2385 move |_, _, _| {
2386 tx.blocking_send(()).ok();
2387 }
2388 })
2389 });
2390
2391 let cx = cx.weak_self.as_ref().unwrap().upgrade().unwrap();
2392 let handle = self.downgrade();
2393 let duration = if std::env::var("CI").is_ok() {
2394 Duration::from_secs(2)
2395 } else {
2396 Duration::from_millis(500)
2397 };
2398
2399 async move {
2400 timeout(duration, async move {
2401 loop {
2402 {
2403 let cx = cx.borrow();
2404 let cx = cx.as_ref();
2405 if predicate(
2406 handle
2407 .upgrade(cx)
2408 .expect("view dropped with pending condition")
2409 .read(cx),
2410 cx,
2411 ) {
2412 break;
2413 }
2414 }
2415
2416 rx.recv()
2417 .await
2418 .expect("view dropped with pending condition");
2419 }
2420 })
2421 .await
2422 .expect("condition timed out");
2423 }
2424 }
2425}
2426
2427impl<T> Clone for ViewHandle<T> {
2428 fn clone(&self) -> Self {
2429 self.ref_counts
2430 .lock()
2431 .inc_view(self.window_id, self.view_id);
2432 Self {
2433 window_id: self.window_id,
2434 view_id: self.view_id,
2435 view_type: PhantomData,
2436 ref_counts: self.ref_counts.clone(),
2437 }
2438 }
2439}
2440
2441impl<T> PartialEq for ViewHandle<T> {
2442 fn eq(&self, other: &Self) -> bool {
2443 self.window_id == other.window_id && self.view_id == other.view_id
2444 }
2445}
2446
2447impl<T> Eq for ViewHandle<T> {}
2448
2449impl<T> Debug for ViewHandle<T> {
2450 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2451 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
2452 .field("window_id", &self.window_id)
2453 .field("view_id", &self.view_id)
2454 .finish()
2455 }
2456}
2457
2458impl<T> Drop for ViewHandle<T> {
2459 fn drop(&mut self) {
2460 self.ref_counts
2461 .lock()
2462 .dec_view(self.window_id, self.view_id);
2463 }
2464}
2465
2466impl<T> Handle<T> for ViewHandle<T> {
2467 fn id(&self) -> usize {
2468 self.view_id
2469 }
2470
2471 fn location(&self) -> EntityLocation {
2472 EntityLocation::View(self.window_id, self.view_id)
2473 }
2474}
2475
2476pub struct AnyViewHandle {
2477 window_id: usize,
2478 view_id: usize,
2479 view_type: TypeId,
2480 ref_counts: Arc<Mutex<RefCounts>>,
2481}
2482
2483impl AnyViewHandle {
2484 pub fn id(&self) -> usize {
2485 self.view_id
2486 }
2487
2488 pub fn is<T: 'static>(&self) -> bool {
2489 TypeId::of::<T>() == self.view_type
2490 }
2491
2492 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
2493 if self.is::<T>() {
2494 let result = Some(ViewHandle {
2495 window_id: self.window_id,
2496 view_id: self.view_id,
2497 ref_counts: self.ref_counts.clone(),
2498 view_type: PhantomData,
2499 });
2500 unsafe {
2501 Arc::decrement_strong_count(&self.ref_counts);
2502 }
2503 std::mem::forget(self);
2504 result
2505 } else {
2506 None
2507 }
2508 }
2509}
2510
2511impl Clone for AnyViewHandle {
2512 fn clone(&self) -> Self {
2513 self.ref_counts
2514 .lock()
2515 .inc_view(self.window_id, self.view_id);
2516 Self {
2517 window_id: self.window_id,
2518 view_id: self.view_id,
2519 view_type: self.view_type,
2520 ref_counts: self.ref_counts.clone(),
2521 }
2522 }
2523}
2524
2525impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
2526 fn from(handle: &ViewHandle<T>) -> Self {
2527 handle
2528 .ref_counts
2529 .lock()
2530 .inc_view(handle.window_id, handle.view_id);
2531 AnyViewHandle {
2532 window_id: handle.window_id,
2533 view_id: handle.view_id,
2534 view_type: TypeId::of::<T>(),
2535 ref_counts: handle.ref_counts.clone(),
2536 }
2537 }
2538}
2539
2540impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
2541 fn from(handle: ViewHandle<T>) -> Self {
2542 let any_handle = AnyViewHandle {
2543 window_id: handle.window_id,
2544 view_id: handle.view_id,
2545 view_type: TypeId::of::<T>(),
2546 ref_counts: handle.ref_counts.clone(),
2547 };
2548 unsafe {
2549 Arc::decrement_strong_count(&handle.ref_counts);
2550 }
2551 std::mem::forget(handle);
2552 any_handle
2553 }
2554}
2555
2556impl Drop for AnyViewHandle {
2557 fn drop(&mut self) {
2558 self.ref_counts
2559 .lock()
2560 .dec_view(self.window_id, self.view_id);
2561 }
2562}
2563
2564pub struct AnyModelHandle {
2565 model_id: usize,
2566 ref_counts: Arc<Mutex<RefCounts>>,
2567}
2568
2569impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
2570 fn from(handle: ModelHandle<T>) -> Self {
2571 handle.ref_counts.lock().inc_model(handle.model_id);
2572 Self {
2573 model_id: handle.model_id,
2574 ref_counts: handle.ref_counts.clone(),
2575 }
2576 }
2577}
2578
2579impl Drop for AnyModelHandle {
2580 fn drop(&mut self) {
2581 self.ref_counts.lock().dec_model(self.model_id);
2582 }
2583}
2584pub struct WeakViewHandle<T> {
2585 window_id: usize,
2586 view_id: usize,
2587 view_type: PhantomData<T>,
2588}
2589
2590impl<T: View> WeakViewHandle<T> {
2591 fn new(window_id: usize, view_id: usize) -> Self {
2592 Self {
2593 window_id,
2594 view_id,
2595 view_type: PhantomData,
2596 }
2597 }
2598
2599 pub fn upgrade(&self, cx: impl AsRef<AppContext>) -> Option<ViewHandle<T>> {
2600 let cx = cx.as_ref();
2601 if cx.ref_counts.lock().is_entity_alive(self.view_id) {
2602 Some(ViewHandle::new(
2603 self.window_id,
2604 self.view_id,
2605 &cx.ref_counts,
2606 ))
2607 } else {
2608 None
2609 }
2610 }
2611}
2612
2613impl<T> Clone for WeakViewHandle<T> {
2614 fn clone(&self) -> Self {
2615 Self {
2616 window_id: self.window_id,
2617 view_id: self.view_id,
2618 view_type: PhantomData,
2619 }
2620 }
2621}
2622
2623pub struct ValueHandle<T> {
2624 value_type: PhantomData<T>,
2625 tag_type_id: TypeId,
2626 id: usize,
2627 ref_counts: Weak<Mutex<RefCounts>>,
2628}
2629
2630impl<T: 'static> ValueHandle<T> {
2631 fn new(tag_type_id: TypeId, id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
2632 ref_counts.lock().inc_value(tag_type_id, id);
2633 Self {
2634 value_type: PhantomData,
2635 tag_type_id,
2636 id,
2637 ref_counts: Arc::downgrade(ref_counts),
2638 }
2639 }
2640
2641 pub fn read<R>(&self, cx: &AppContext, f: impl FnOnce(&T) -> R) -> R {
2642 f(cx.values
2643 .read()
2644 .get(&(self.tag_type_id, self.id))
2645 .unwrap()
2646 .downcast_ref()
2647 .unwrap())
2648 }
2649
2650 pub fn update<R>(&self, cx: &AppContext, f: impl FnOnce(&mut T) -> R) -> R {
2651 f(cx.values
2652 .write()
2653 .get_mut(&(self.tag_type_id, self.id))
2654 .unwrap()
2655 .downcast_mut()
2656 .unwrap())
2657 }
2658}
2659
2660impl<T> Drop for ValueHandle<T> {
2661 fn drop(&mut self) {
2662 if let Some(ref_counts) = self.ref_counts.upgrade() {
2663 ref_counts.lock().dec_value(self.tag_type_id, self.id);
2664 }
2665 }
2666}
2667
2668#[derive(Default)]
2669struct RefCounts {
2670 entity_counts: HashMap<usize, usize>,
2671 value_counts: HashMap<(TypeId, usize), usize>,
2672 dropped_models: HashSet<usize>,
2673 dropped_views: HashSet<(usize, usize)>,
2674 dropped_values: HashSet<(TypeId, usize)>,
2675}
2676
2677impl RefCounts {
2678 fn inc_model(&mut self, model_id: usize) {
2679 match self.entity_counts.entry(model_id) {
2680 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
2681 Entry::Vacant(entry) => {
2682 entry.insert(1);
2683 self.dropped_models.remove(&model_id);
2684 }
2685 }
2686 }
2687
2688 fn inc_view(&mut self, window_id: usize, view_id: usize) {
2689 match self.entity_counts.entry(view_id) {
2690 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
2691 Entry::Vacant(entry) => {
2692 entry.insert(1);
2693 self.dropped_views.remove(&(window_id, view_id));
2694 }
2695 }
2696 }
2697
2698 fn inc_value(&mut self, tag_type_id: TypeId, id: usize) {
2699 *self.value_counts.entry((tag_type_id, id)).or_insert(0) += 1;
2700 }
2701
2702 fn dec_model(&mut self, model_id: usize) {
2703 let count = self.entity_counts.get_mut(&model_id).unwrap();
2704 *count -= 1;
2705 if *count == 0 {
2706 self.entity_counts.remove(&model_id);
2707 self.dropped_models.insert(model_id);
2708 }
2709 }
2710
2711 fn dec_view(&mut self, window_id: usize, view_id: usize) {
2712 let count = self.entity_counts.get_mut(&view_id).unwrap();
2713 *count -= 1;
2714 if *count == 0 {
2715 self.entity_counts.remove(&view_id);
2716 self.dropped_views.insert((window_id, view_id));
2717 }
2718 }
2719
2720 fn dec_value(&mut self, tag_type_id: TypeId, id: usize) {
2721 let key = (tag_type_id, id);
2722 let count = self.value_counts.get_mut(&key).unwrap();
2723 *count -= 1;
2724 if *count == 0 {
2725 self.value_counts.remove(&key);
2726 self.dropped_values.insert(key);
2727 }
2728 }
2729
2730 fn is_entity_alive(&self, entity_id: usize) -> bool {
2731 self.entity_counts.contains_key(&entity_id)
2732 }
2733
2734 fn take_dropped(
2735 &mut self,
2736 ) -> (
2737 HashSet<usize>,
2738 HashSet<(usize, usize)>,
2739 HashSet<(TypeId, usize)>,
2740 ) {
2741 let mut dropped_models = HashSet::new();
2742 let mut dropped_views = HashSet::new();
2743 let mut dropped_values = HashSet::new();
2744 std::mem::swap(&mut self.dropped_models, &mut dropped_models);
2745 std::mem::swap(&mut self.dropped_views, &mut dropped_views);
2746 std::mem::swap(&mut self.dropped_values, &mut dropped_values);
2747 (dropped_models, dropped_views, dropped_values)
2748 }
2749}
2750
2751enum Subscription {
2752 FromModel {
2753 model_id: usize,
2754 callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize)>,
2755 },
2756 FromView {
2757 window_id: usize,
2758 view_id: usize,
2759 callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize, usize)>,
2760 },
2761}
2762
2763enum ModelObservation {
2764 FromModel {
2765 model_id: usize,
2766 callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize)>,
2767 },
2768 FromView {
2769 window_id: usize,
2770 view_id: usize,
2771 callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize, usize)>,
2772 },
2773}
2774
2775struct ViewObservation {
2776 window_id: usize,
2777 view_id: usize,
2778 callback: Box<dyn FnMut(&mut dyn Any, usize, usize, &mut MutableAppContext, usize, usize)>,
2779}
2780
2781#[cfg(test)]
2782mod tests {
2783 use super::*;
2784 use crate::elements::*;
2785 use smol::future::poll_once;
2786
2787 #[crate::test(self)]
2788 fn test_model_handles(cx: &mut MutableAppContext) {
2789 struct Model {
2790 other: Option<ModelHandle<Model>>,
2791 events: Vec<String>,
2792 }
2793
2794 impl Entity for Model {
2795 type Event = usize;
2796 }
2797
2798 impl Model {
2799 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
2800 if let Some(other) = other.as_ref() {
2801 cx.observe(other, |me, _, _| {
2802 me.events.push("notified".into());
2803 });
2804 cx.subscribe(other, |me, event, _| {
2805 me.events.push(format!("observed event {}", event));
2806 });
2807 }
2808
2809 Self {
2810 other,
2811 events: Vec::new(),
2812 }
2813 }
2814 }
2815
2816 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
2817 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
2818 assert_eq!(cx.cx.models.len(), 2);
2819
2820 handle_1.update(cx, |model, cx| {
2821 model.events.push("updated".into());
2822 cx.emit(1);
2823 cx.notify();
2824 cx.emit(2);
2825 });
2826 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
2827 assert_eq!(
2828 handle_2.read(cx).events,
2829 vec![
2830 "observed event 1".to_string(),
2831 "notified".to_string(),
2832 "observed event 2".to_string(),
2833 ]
2834 );
2835
2836 handle_2.update(cx, |model, _| {
2837 drop(handle_1);
2838 model.other.take();
2839 });
2840
2841 assert_eq!(cx.cx.models.len(), 1);
2842 assert!(cx.subscriptions.is_empty());
2843 assert!(cx.model_observations.is_empty());
2844 }
2845
2846 #[crate::test(self)]
2847 fn test_subscribe_and_emit_from_model(cx: &mut MutableAppContext) {
2848 #[derive(Default)]
2849 struct Model {
2850 events: Vec<usize>,
2851 }
2852
2853 impl Entity for Model {
2854 type Event = usize;
2855 }
2856
2857 let handle_1 = cx.add_model(|_| Model::default());
2858 let handle_2 = cx.add_model(|_| Model::default());
2859 let handle_2b = handle_2.clone();
2860
2861 handle_1.update(cx, |_, c| {
2862 c.subscribe(&handle_2, move |model: &mut Model, event, c| {
2863 model.events.push(*event);
2864
2865 c.subscribe(&handle_2b, |model, event, _| {
2866 model.events.push(*event * 2);
2867 });
2868 });
2869 });
2870
2871 handle_2.update(cx, |_, c| c.emit(7));
2872 assert_eq!(handle_1.read(cx).events, vec![7]);
2873
2874 handle_2.update(cx, |_, c| c.emit(5));
2875 assert_eq!(handle_1.read(cx).events, vec![7, 10, 5]);
2876 }
2877
2878 #[crate::test(self)]
2879 fn test_observe_and_notify_from_model(cx: &mut MutableAppContext) {
2880 #[derive(Default)]
2881 struct Model {
2882 count: usize,
2883 events: Vec<usize>,
2884 }
2885
2886 impl Entity for Model {
2887 type Event = ();
2888 }
2889
2890 let handle_1 = cx.add_model(|_| Model::default());
2891 let handle_2 = cx.add_model(|_| Model::default());
2892 let handle_2b = handle_2.clone();
2893
2894 handle_1.update(cx, |_, c| {
2895 c.observe(&handle_2, move |model, observed, c| {
2896 model.events.push(observed.read(c).count);
2897 c.observe(&handle_2b, |model, observed, c| {
2898 model.events.push(observed.read(c).count * 2);
2899 });
2900 });
2901 });
2902
2903 handle_2.update(cx, |model, c| {
2904 model.count = 7;
2905 c.notify()
2906 });
2907 assert_eq!(handle_1.read(cx).events, vec![7]);
2908
2909 handle_2.update(cx, |model, c| {
2910 model.count = 5;
2911 c.notify()
2912 });
2913 assert_eq!(handle_1.read(cx).events, vec![7, 10, 5])
2914 }
2915
2916 #[crate::test(self)]
2917 fn test_view_handles(cx: &mut MutableAppContext) {
2918 struct View {
2919 other: Option<ViewHandle<View>>,
2920 events: Vec<String>,
2921 }
2922
2923 impl Entity for View {
2924 type Event = usize;
2925 }
2926
2927 impl super::View for View {
2928 fn render<'a>(&self, _: &AppContext) -> ElementBox {
2929 Empty::new().boxed()
2930 }
2931
2932 fn ui_name() -> &'static str {
2933 "View"
2934 }
2935 }
2936
2937 impl View {
2938 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
2939 if let Some(other) = other.as_ref() {
2940 cx.subscribe_to_view(other, |me, _, event, _| {
2941 me.events.push(format!("observed event {}", event));
2942 });
2943 }
2944 Self {
2945 other,
2946 events: Vec::new(),
2947 }
2948 }
2949 }
2950
2951 let (window_id, _) = cx.add_window(|cx| View::new(None, cx));
2952 let handle_1 = cx.add_view(window_id, |cx| View::new(None, cx));
2953 let handle_2 = cx.add_view(window_id, |cx| View::new(Some(handle_1.clone()), cx));
2954 assert_eq!(cx.cx.views.len(), 3);
2955
2956 handle_1.update(cx, |view, cx| {
2957 view.events.push("updated".into());
2958 cx.emit(1);
2959 cx.emit(2);
2960 });
2961 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
2962 assert_eq!(
2963 handle_2.read(cx).events,
2964 vec![
2965 "observed event 1".to_string(),
2966 "observed event 2".to_string(),
2967 ]
2968 );
2969
2970 handle_2.update(cx, |view, _| {
2971 drop(handle_1);
2972 view.other.take();
2973 });
2974
2975 assert_eq!(cx.cx.views.len(), 2);
2976 assert!(cx.subscriptions.is_empty());
2977 assert!(cx.model_observations.is_empty());
2978 }
2979
2980 #[crate::test(self)]
2981 fn test_entity_release_hooks(cx: &mut MutableAppContext) {
2982 struct Model {
2983 released: Arc<Mutex<bool>>,
2984 }
2985
2986 struct View {
2987 released: Arc<Mutex<bool>>,
2988 }
2989
2990 impl Entity for Model {
2991 type Event = ();
2992
2993 fn release(&mut self, _: &mut MutableAppContext) {
2994 *self.released.lock() = true;
2995 }
2996 }
2997
2998 impl Entity for View {
2999 type Event = ();
3000
3001 fn release(&mut self, _: &mut MutableAppContext) {
3002 *self.released.lock() = true;
3003 }
3004 }
3005
3006 impl super::View for View {
3007 fn ui_name() -> &'static str {
3008 "View"
3009 }
3010
3011 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3012 Empty::new().boxed()
3013 }
3014 }
3015
3016 let model_released = Arc::new(Mutex::new(false));
3017 let view_released = Arc::new(Mutex::new(false));
3018
3019 let model = cx.add_model(|_| Model {
3020 released: model_released.clone(),
3021 });
3022
3023 let (window_id, _) = cx.add_window(|_| View {
3024 released: view_released.clone(),
3025 });
3026
3027 assert!(!*model_released.lock());
3028 assert!(!*view_released.lock());
3029
3030 cx.update(move || {
3031 drop(model);
3032 });
3033 assert!(*model_released.lock());
3034
3035 drop(cx.remove_window(window_id));
3036 assert!(*view_released.lock());
3037 }
3038
3039 #[crate::test(self)]
3040 fn test_subscribe_and_emit_from_view(cx: &mut MutableAppContext) {
3041 #[derive(Default)]
3042 struct View {
3043 events: Vec<usize>,
3044 }
3045
3046 impl Entity for View {
3047 type Event = usize;
3048 }
3049
3050 impl super::View for View {
3051 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3052 Empty::new().boxed()
3053 }
3054
3055 fn ui_name() -> &'static str {
3056 "View"
3057 }
3058 }
3059
3060 struct Model;
3061
3062 impl Entity for Model {
3063 type Event = usize;
3064 }
3065
3066 let (window_id, handle_1) = cx.add_window(|_| View::default());
3067 let handle_2 = cx.add_view(window_id, |_| View::default());
3068 let handle_2b = handle_2.clone();
3069 let handle_3 = cx.add_model(|_| Model);
3070
3071 handle_1.update(cx, |_, c| {
3072 c.subscribe_to_view(&handle_2, move |me, _, event, c| {
3073 me.events.push(*event);
3074
3075 c.subscribe_to_view(&handle_2b, |me, _, event, _| {
3076 me.events.push(*event * 2);
3077 });
3078 });
3079
3080 c.subscribe_to_model(&handle_3, |me, _, event, _| {
3081 me.events.push(*event);
3082 })
3083 });
3084
3085 handle_2.update(cx, |_, c| c.emit(7));
3086 assert_eq!(handle_1.read(cx).events, vec![7]);
3087
3088 handle_2.update(cx, |_, c| c.emit(5));
3089 assert_eq!(handle_1.read(cx).events, vec![7, 10, 5]);
3090
3091 handle_3.update(cx, |_, c| c.emit(9));
3092 assert_eq!(handle_1.read(cx).events, vec![7, 10, 5, 9]);
3093 }
3094
3095 #[crate::test(self)]
3096 fn test_dropping_subscribers(cx: &mut MutableAppContext) {
3097 struct View;
3098
3099 impl Entity for View {
3100 type Event = ();
3101 }
3102
3103 impl super::View for View {
3104 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3105 Empty::new().boxed()
3106 }
3107
3108 fn ui_name() -> &'static str {
3109 "View"
3110 }
3111 }
3112
3113 struct Model;
3114
3115 impl Entity for Model {
3116 type Event = ();
3117 }
3118
3119 let (window_id, _) = cx.add_window(|_| View);
3120 let observing_view = cx.add_view(window_id, |_| View);
3121 let emitting_view = cx.add_view(window_id, |_| View);
3122 let observing_model = cx.add_model(|_| Model);
3123 let observed_model = cx.add_model(|_| Model);
3124
3125 observing_view.update(cx, |_, cx| {
3126 cx.subscribe_to_view(&emitting_view, |_, _, _, _| {});
3127 cx.subscribe_to_model(&observed_model, |_, _, _, _| {});
3128 });
3129 observing_model.update(cx, |_, cx| {
3130 cx.subscribe(&observed_model, |_, _, _| {});
3131 });
3132
3133 cx.update(|| {
3134 drop(observing_view);
3135 drop(observing_model);
3136 });
3137
3138 emitting_view.update(cx, |_, cx| cx.emit(()));
3139 observed_model.update(cx, |_, cx| cx.emit(()));
3140 }
3141
3142 #[crate::test(self)]
3143 fn test_observe_and_notify_from_view(cx: &mut MutableAppContext) {
3144 #[derive(Default)]
3145 struct View {
3146 events: Vec<usize>,
3147 }
3148
3149 impl Entity for View {
3150 type Event = usize;
3151 }
3152
3153 impl super::View for View {
3154 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3155 Empty::new().boxed()
3156 }
3157
3158 fn ui_name() -> &'static str {
3159 "View"
3160 }
3161 }
3162
3163 #[derive(Default)]
3164 struct Model {
3165 count: usize,
3166 }
3167
3168 impl Entity for Model {
3169 type Event = ();
3170 }
3171
3172 let (_, view) = cx.add_window(|_| View::default());
3173 let model = cx.add_model(|_| Model::default());
3174
3175 view.update(cx, |_, c| {
3176 c.observe_model(&model, |me, observed, c| {
3177 me.events.push(observed.read(c).count)
3178 });
3179 });
3180
3181 model.update(cx, |model, c| {
3182 model.count = 11;
3183 c.notify();
3184 });
3185 assert_eq!(view.read(cx).events, vec![11]);
3186 }
3187
3188 #[crate::test(self)]
3189 fn test_dropping_observers(cx: &mut MutableAppContext) {
3190 struct View;
3191
3192 impl Entity for View {
3193 type Event = ();
3194 }
3195
3196 impl super::View for View {
3197 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3198 Empty::new().boxed()
3199 }
3200
3201 fn ui_name() -> &'static str {
3202 "View"
3203 }
3204 }
3205
3206 struct Model;
3207
3208 impl Entity for Model {
3209 type Event = ();
3210 }
3211
3212 let (window_id, _) = cx.add_window(|_| View);
3213 let observing_view = cx.add_view(window_id, |_| View);
3214 let observing_model = cx.add_model(|_| Model);
3215 let observed_model = cx.add_model(|_| Model);
3216
3217 observing_view.update(cx, |_, cx| {
3218 cx.observe_model(&observed_model, |_, _, _| {});
3219 });
3220 observing_model.update(cx, |_, cx| {
3221 cx.observe(&observed_model, |_, _, _| {});
3222 });
3223
3224 cx.update(|| {
3225 drop(observing_view);
3226 drop(observing_model);
3227 });
3228
3229 observed_model.update(cx, |_, cx| cx.notify());
3230 }
3231
3232 #[crate::test(self)]
3233 fn test_focus(cx: &mut MutableAppContext) {
3234 struct View {
3235 name: String,
3236 events: Arc<Mutex<Vec<String>>>,
3237 }
3238
3239 impl Entity for View {
3240 type Event = ();
3241 }
3242
3243 impl super::View for View {
3244 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3245 Empty::new().boxed()
3246 }
3247
3248 fn ui_name() -> &'static str {
3249 "View"
3250 }
3251
3252 fn on_focus(&mut self, _: &mut ViewContext<Self>) {
3253 self.events.lock().push(format!("{} focused", &self.name));
3254 }
3255
3256 fn on_blur(&mut self, _: &mut ViewContext<Self>) {
3257 self.events.lock().push(format!("{} blurred", &self.name));
3258 }
3259 }
3260
3261 let events: Arc<Mutex<Vec<String>>> = Default::default();
3262 let (window_id, view_1) = cx.add_window(|_| View {
3263 events: events.clone(),
3264 name: "view 1".to_string(),
3265 });
3266 let view_2 = cx.add_view(window_id, |_| View {
3267 events: events.clone(),
3268 name: "view 2".to_string(),
3269 });
3270
3271 view_1.update(cx, |_, cx| cx.focus(&view_2));
3272 view_1.update(cx, |_, cx| cx.focus(&view_1));
3273 view_1.update(cx, |_, cx| cx.focus(&view_2));
3274 view_1.update(cx, |_, _| drop(view_2));
3275
3276 assert_eq!(
3277 *events.lock(),
3278 [
3279 "view 1 focused".to_string(),
3280 "view 1 blurred".to_string(),
3281 "view 2 focused".to_string(),
3282 "view 2 blurred".to_string(),
3283 "view 1 focused".to_string(),
3284 "view 1 blurred".to_string(),
3285 "view 2 focused".to_string(),
3286 "view 1 focused".to_string(),
3287 ],
3288 );
3289 }
3290
3291 #[crate::test(self)]
3292 fn test_dispatch_action(cx: &mut MutableAppContext) {
3293 struct ViewA {
3294 id: usize,
3295 }
3296
3297 impl Entity for ViewA {
3298 type Event = ();
3299 }
3300
3301 impl View for ViewA {
3302 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3303 Empty::new().boxed()
3304 }
3305
3306 fn ui_name() -> &'static str {
3307 "View"
3308 }
3309 }
3310
3311 struct ViewB {
3312 id: usize,
3313 }
3314
3315 impl Entity for ViewB {
3316 type Event = ();
3317 }
3318
3319 impl View for ViewB {
3320 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3321 Empty::new().boxed()
3322 }
3323
3324 fn ui_name() -> &'static str {
3325 "View"
3326 }
3327 }
3328
3329 struct ActionArg {
3330 foo: String,
3331 }
3332
3333 let actions = Rc::new(RefCell::new(Vec::new()));
3334
3335 let actions_clone = actions.clone();
3336 cx.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
3337 actions_clone.borrow_mut().push("global a".to_string());
3338 });
3339
3340 let actions_clone = actions.clone();
3341 cx.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
3342 actions_clone.borrow_mut().push("global b".to_string());
3343 });
3344
3345 let actions_clone = actions.clone();
3346 cx.add_action("action", move |view: &mut ViewA, arg: &ActionArg, cx| {
3347 assert_eq!(arg.foo, "bar");
3348 cx.propagate_action();
3349 actions_clone.borrow_mut().push(format!("{} a", view.id));
3350 });
3351
3352 let actions_clone = actions.clone();
3353 cx.add_action("action", move |view: &mut ViewA, _: &ActionArg, cx| {
3354 if view.id != 1 {
3355 cx.propagate_action();
3356 }
3357 actions_clone.borrow_mut().push(format!("{} b", view.id));
3358 });
3359
3360 let actions_clone = actions.clone();
3361 cx.add_action("action", move |view: &mut ViewB, _: &ActionArg, cx| {
3362 cx.propagate_action();
3363 actions_clone.borrow_mut().push(format!("{} c", view.id));
3364 });
3365
3366 let actions_clone = actions.clone();
3367 cx.add_action("action", move |view: &mut ViewB, _: &ActionArg, cx| {
3368 cx.propagate_action();
3369 actions_clone.borrow_mut().push(format!("{} d", view.id));
3370 });
3371
3372 let (window_id, view_1) = cx.add_window(|_| ViewA { id: 1 });
3373 let view_2 = cx.add_view(window_id, |_| ViewB { id: 2 });
3374 let view_3 = cx.add_view(window_id, |_| ViewA { id: 3 });
3375 let view_4 = cx.add_view(window_id, |_| ViewB { id: 4 });
3376
3377 cx.dispatch_action(
3378 window_id,
3379 vec![view_1.id(), view_2.id(), view_3.id(), view_4.id()],
3380 "action",
3381 ActionArg { foo: "bar".into() },
3382 );
3383
3384 assert_eq!(
3385 *actions.borrow(),
3386 vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "1 b"]
3387 );
3388
3389 // Remove view_1, which doesn't propagate the action
3390 actions.borrow_mut().clear();
3391 cx.dispatch_action(
3392 window_id,
3393 vec![view_2.id(), view_3.id(), view_4.id()],
3394 "action",
3395 ActionArg { foo: "bar".into() },
3396 );
3397
3398 assert_eq!(
3399 *actions.borrow(),
3400 vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "global b", "global a"]
3401 );
3402 }
3403
3404 #[crate::test(self)]
3405 fn test_dispatch_keystroke(cx: &mut MutableAppContext) {
3406 use std::cell::Cell;
3407
3408 #[derive(Clone)]
3409 struct ActionArg {
3410 key: String,
3411 }
3412
3413 struct View {
3414 id: usize,
3415 keymap_context: keymap::Context,
3416 }
3417
3418 impl Entity for View {
3419 type Event = ();
3420 }
3421
3422 impl super::View for View {
3423 fn render<'a>(&self, _: &AppContext) -> ElementBox {
3424 Empty::new().boxed()
3425 }
3426
3427 fn ui_name() -> &'static str {
3428 "View"
3429 }
3430
3431 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
3432 self.keymap_context.clone()
3433 }
3434 }
3435
3436 impl View {
3437 fn new(id: usize) -> Self {
3438 View {
3439 id,
3440 keymap_context: keymap::Context::default(),
3441 }
3442 }
3443 }
3444
3445 let mut view_1 = View::new(1);
3446 let mut view_2 = View::new(2);
3447 let mut view_3 = View::new(3);
3448 view_1.keymap_context.set.insert("a".into());
3449 view_2.keymap_context.set.insert("b".into());
3450 view_3.keymap_context.set.insert("c".into());
3451
3452 let (window_id, view_1) = cx.add_window(|_| view_1);
3453 let view_2 = cx.add_view(window_id, |_| view_2);
3454 let view_3 = cx.add_view(window_id, |_| view_3);
3455
3456 // This keymap's only binding dispatches an action on view 2 because that view will have
3457 // "a" and "b" in its context, but not "c".
3458 let binding = keymap::Binding::new("a", "action", Some("a && b && !c"))
3459 .with_arg(ActionArg { key: "a".into() });
3460 cx.add_bindings(vec![binding]);
3461
3462 let handled_action = Rc::new(Cell::new(false));
3463 let handled_action_clone = handled_action.clone();
3464 cx.add_action("action", move |view: &mut View, arg: &ActionArg, _| {
3465 handled_action_clone.set(true);
3466 assert_eq!(view.id, 2);
3467 assert_eq!(arg.key, "a");
3468 });
3469
3470 cx.dispatch_keystroke(
3471 window_id,
3472 vec![view_1.id(), view_2.id(), view_3.id()],
3473 &Keystroke::parse("a").unwrap(),
3474 )
3475 .unwrap();
3476
3477 assert!(handled_action.get());
3478 }
3479
3480 #[crate::test(self)]
3481 async fn test_model_condition(mut cx: TestAppContext) {
3482 struct Counter(usize);
3483
3484 impl super::Entity for Counter {
3485 type Event = ();
3486 }
3487
3488 impl Counter {
3489 fn inc(&mut self, cx: &mut ModelContext<Self>) {
3490 self.0 += 1;
3491 cx.notify();
3492 }
3493 }
3494
3495 let model = cx.add_model(|_| Counter(0));
3496
3497 let condition1 = model.condition(&cx, |model, _| model.0 == 2);
3498 let condition2 = model.condition(&cx, |model, _| model.0 == 3);
3499 smol::pin!(condition1, condition2);
3500
3501 model.update(&mut cx, |model, cx| model.inc(cx));
3502 assert_eq!(poll_once(&mut condition1).await, None);
3503 assert_eq!(poll_once(&mut condition2).await, None);
3504
3505 model.update(&mut cx, |model, cx| model.inc(cx));
3506 assert_eq!(poll_once(&mut condition1).await, Some(()));
3507 assert_eq!(poll_once(&mut condition2).await, None);
3508
3509 model.update(&mut cx, |model, cx| model.inc(cx));
3510 assert_eq!(poll_once(&mut condition2).await, Some(()));
3511
3512 model.update(&mut cx, |_, cx| cx.notify());
3513 }
3514
3515 #[crate::test(self)]
3516 #[should_panic]
3517 async fn test_model_condition_timeout(mut cx: TestAppContext) {
3518 struct Model;
3519
3520 impl super::Entity for Model {
3521 type Event = ();
3522 }
3523
3524 let model = cx.add_model(|_| Model);
3525 model.condition(&cx, |_, _| false).await;
3526 }
3527
3528 #[crate::test(self)]
3529 #[should_panic(expected = "model dropped with pending condition")]
3530 async fn test_model_condition_panic_on_drop(mut cx: TestAppContext) {
3531 struct Model;
3532
3533 impl super::Entity for Model {
3534 type Event = ();
3535 }
3536
3537 let model = cx.add_model(|_| Model);
3538 let condition = model.condition(&cx, |_, _| false);
3539 cx.update(|_| drop(model));
3540 condition.await;
3541 }
3542
3543 #[crate::test(self)]
3544 async fn test_view_condition(mut cx: TestAppContext) {
3545 struct Counter(usize);
3546
3547 impl super::Entity for Counter {
3548 type Event = ();
3549 }
3550
3551 impl super::View for Counter {
3552 fn ui_name() -> &'static str {
3553 "test view"
3554 }
3555
3556 fn render(&self, _: &AppContext) -> ElementBox {
3557 Empty::new().boxed()
3558 }
3559 }
3560
3561 impl Counter {
3562 fn inc(&mut self, cx: &mut ViewContext<Self>) {
3563 self.0 += 1;
3564 cx.notify();
3565 }
3566 }
3567
3568 let (_, view) = cx.add_window(|_| Counter(0));
3569
3570 let condition1 = view.condition(&cx, |view, _| view.0 == 2);
3571 let condition2 = view.condition(&cx, |view, _| view.0 == 3);
3572 smol::pin!(condition1, condition2);
3573
3574 view.update(&mut cx, |view, cx| view.inc(cx));
3575 assert_eq!(poll_once(&mut condition1).await, None);
3576 assert_eq!(poll_once(&mut condition2).await, None);
3577
3578 view.update(&mut cx, |view, cx| view.inc(cx));
3579 assert_eq!(poll_once(&mut condition1).await, Some(()));
3580 assert_eq!(poll_once(&mut condition2).await, None);
3581
3582 view.update(&mut cx, |view, cx| view.inc(cx));
3583 assert_eq!(poll_once(&mut condition2).await, Some(()));
3584 view.update(&mut cx, |_, cx| cx.notify());
3585 }
3586
3587 #[crate::test(self)]
3588 #[should_panic]
3589 async fn test_view_condition_timeout(mut cx: TestAppContext) {
3590 struct View;
3591
3592 impl super::Entity for View {
3593 type Event = ();
3594 }
3595
3596 impl super::View for View {
3597 fn ui_name() -> &'static str {
3598 "test view"
3599 }
3600
3601 fn render(&self, _: &AppContext) -> ElementBox {
3602 Empty::new().boxed()
3603 }
3604 }
3605
3606 let (_, view) = cx.add_window(|_| View);
3607 view.condition(&cx, |_, _| false).await;
3608 }
3609
3610 #[crate::test(self)]
3611 #[should_panic(expected = "view dropped with pending condition")]
3612 async fn test_view_condition_panic_on_drop(mut cx: TestAppContext) {
3613 struct View;
3614
3615 impl super::Entity for View {
3616 type Event = ();
3617 }
3618
3619 impl super::View for View {
3620 fn ui_name() -> &'static str {
3621 "test view"
3622 }
3623
3624 fn render(&self, _: &AppContext) -> ElementBox {
3625 Empty::new().boxed()
3626 }
3627 }
3628
3629 let window_id = cx.add_window(|_| View).0;
3630 let view = cx.add_view(window_id, |_| View);
3631
3632 let condition = view.condition(&cx, |_, _| false);
3633 cx.update(|_| drop(view));
3634 condition.await;
3635 }
3636}