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