1pub mod action;
2
3use crate::{
4 elements::ElementBox,
5 executor::{self, Task},
6 keymap::{self, Binding, Keystroke},
7 platform::{self, Platform, PromptLevel, WindowOptions},
8 presenter::Presenter,
9 util::post_inc,
10 AssetCache, AssetSource, ClipboardItem, FontCache, MouseRegionId, PathPromptOptions,
11 TextLayoutCache,
12};
13pub use action::*;
14use anyhow::{anyhow, Context, Result};
15use collections::btree_map;
16use keymap::MatchResult;
17use lazy_static::lazy_static;
18use parking_lot::Mutex;
19use platform::Event;
20use postage::oneshot;
21use smallvec::SmallVec;
22use smol::prelude::*;
23use std::{
24 any::{type_name, Any, TypeId},
25 cell::RefCell,
26 collections::{hash_map::Entry, BTreeMap, HashMap, HashSet, VecDeque},
27 fmt::{self, Debug},
28 hash::{Hash, Hasher},
29 marker::PhantomData,
30 mem,
31 ops::{Deref, DerefMut},
32 path::{Path, PathBuf},
33 pin::Pin,
34 rc::{self, Rc},
35 sync::{Arc, Weak},
36 time::Duration,
37};
38
39pub trait Entity: 'static {
40 type Event;
41
42 fn release(&mut self, _: &mut MutableAppContext) {}
43 fn app_will_quit(
44 &mut self,
45 _: &mut MutableAppContext,
46 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
47 None
48 }
49}
50
51pub trait View: Entity + Sized {
52 fn ui_name() -> &'static str;
53 fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox;
54 fn on_focus(&mut self, _: &mut ViewContext<Self>) {}
55 fn on_blur(&mut self, _: &mut ViewContext<Self>) {}
56 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
57 Self::default_keymap_context()
58 }
59 fn default_keymap_context() -> keymap::Context {
60 let mut cx = keymap::Context::default();
61 cx.set.insert(Self::ui_name().into());
62 cx
63 }
64 fn debug_json(&self, _: &AppContext) -> serde_json::Value {
65 serde_json::Value::Null
66 }
67}
68
69pub trait ReadModel {
70 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T;
71}
72
73pub trait ReadModelWith {
74 fn read_model_with<E: Entity, T>(
75 &self,
76 handle: &ModelHandle<E>,
77 read: &mut dyn FnMut(&E, &AppContext) -> T,
78 ) -> T;
79}
80
81pub trait UpdateModel {
82 fn update_model<T: Entity, O>(
83 &mut self,
84 handle: &ModelHandle<T>,
85 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
86 ) -> O;
87}
88
89pub trait UpgradeModelHandle {
90 fn upgrade_model_handle<T: Entity>(
91 &self,
92 handle: &WeakModelHandle<T>,
93 ) -> Option<ModelHandle<T>>;
94
95 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool;
96
97 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle>;
98}
99
100pub trait UpgradeViewHandle {
101 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>>;
102
103 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle>;
104}
105
106pub trait ReadView {
107 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T;
108}
109
110pub trait ReadViewWith {
111 fn read_view_with<V, T>(
112 &self,
113 handle: &ViewHandle<V>,
114 read: &mut dyn FnMut(&V, &AppContext) -> T,
115 ) -> T
116 where
117 V: View;
118}
119
120pub trait UpdateView {
121 fn update_view<T, S>(
122 &mut self,
123 handle: &ViewHandle<T>,
124 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
125 ) -> S
126 where
127 T: View;
128}
129
130pub struct Menu<'a> {
131 pub name: &'a str,
132 pub items: Vec<MenuItem<'a>>,
133}
134
135pub enum MenuItem<'a> {
136 Action {
137 name: &'a str,
138 action: Box<dyn Action>,
139 },
140 Separator,
141}
142
143#[derive(Clone)]
144pub struct App(Rc<RefCell<MutableAppContext>>);
145
146#[derive(Clone)]
147pub struct AsyncAppContext(Rc<RefCell<MutableAppContext>>);
148
149#[cfg(any(test, feature = "test-support"))]
150pub struct TestAppContext {
151 cx: Rc<RefCell<MutableAppContext>>,
152 foreground_platform: Rc<platform::test::ForegroundPlatform>,
153}
154
155impl App {
156 pub fn new(asset_source: impl AssetSource) -> Result<Self> {
157 let platform = platform::current::platform();
158 let foreground_platform = platform::current::foreground_platform();
159 let foreground = Rc::new(executor::Foreground::platform(platform.dispatcher())?);
160 let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
161 foreground,
162 Arc::new(executor::Background::new()),
163 platform.clone(),
164 foreground_platform.clone(),
165 Arc::new(FontCache::new(platform.fonts())),
166 Default::default(),
167 asset_source,
168 ))));
169
170 foreground_platform.on_quit(Box::new({
171 let cx = app.0.clone();
172 move || {
173 cx.borrow_mut().quit();
174 }
175 }));
176 foreground_platform.on_will_open_menu(Box::new({
177 let cx = app.0.clone();
178 move || {
179 let mut cx = cx.borrow_mut();
180 cx.keystroke_matcher.clear_pending();
181 }
182 }));
183 foreground_platform.on_validate_menu_command(Box::new({
184 let cx = app.0.clone();
185 move |action| {
186 let cx = cx.borrow_mut();
187 !cx.keystroke_matcher.has_pending_keystrokes() && cx.is_action_available(action)
188 }
189 }));
190 foreground_platform.on_menu_command(Box::new({
191 let cx = app.0.clone();
192 move |action| {
193 let mut cx = cx.borrow_mut();
194 if let Some(key_window_id) = cx.cx.platform.key_window_id() {
195 if let Some((presenter, _)) =
196 cx.presenters_and_platform_windows.get(&key_window_id)
197 {
198 let presenter = presenter.clone();
199 let path = presenter.borrow().dispatch_path(cx.as_ref());
200 cx.dispatch_action_any(key_window_id, &path, action);
201 } else {
202 cx.dispatch_global_action_any(action);
203 }
204 } else {
205 cx.dispatch_global_action_any(action);
206 }
207 }
208 }));
209
210 app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
211 Ok(app)
212 }
213
214 pub fn background(&self) -> Arc<executor::Background> {
215 self.0.borrow().background().clone()
216 }
217
218 pub fn on_become_active<F>(self, mut callback: F) -> Self
219 where
220 F: 'static + FnMut(&mut MutableAppContext),
221 {
222 let cx = self.0.clone();
223 self.0
224 .borrow_mut()
225 .foreground_platform
226 .on_become_active(Box::new(move || callback(&mut *cx.borrow_mut())));
227 self
228 }
229
230 pub fn on_resign_active<F>(self, mut callback: F) -> Self
231 where
232 F: 'static + FnMut(&mut MutableAppContext),
233 {
234 let cx = self.0.clone();
235 self.0
236 .borrow_mut()
237 .foreground_platform
238 .on_resign_active(Box::new(move || callback(&mut *cx.borrow_mut())));
239 self
240 }
241
242 pub fn on_quit<F>(&mut self, mut callback: F) -> &mut Self
243 where
244 F: 'static + FnMut(&mut MutableAppContext),
245 {
246 let cx = self.0.clone();
247 self.0
248 .borrow_mut()
249 .foreground_platform
250 .on_quit(Box::new(move || callback(&mut *cx.borrow_mut())));
251 self
252 }
253
254 pub fn on_event<F>(&mut self, mut callback: F) -> &mut Self
255 where
256 F: 'static + FnMut(Event, &mut MutableAppContext) -> bool,
257 {
258 let cx = self.0.clone();
259 self.0
260 .borrow_mut()
261 .foreground_platform
262 .on_event(Box::new(move |event| {
263 callback(event, &mut *cx.borrow_mut())
264 }));
265 self
266 }
267
268 pub fn on_open_urls<F>(&mut self, mut callback: F) -> &mut Self
269 where
270 F: 'static + FnMut(Vec<String>, &mut MutableAppContext),
271 {
272 let cx = self.0.clone();
273 self.0
274 .borrow_mut()
275 .foreground_platform
276 .on_open_urls(Box::new(move |paths| {
277 callback(paths, &mut *cx.borrow_mut())
278 }));
279 self
280 }
281
282 pub fn run<F>(self, on_finish_launching: F)
283 where
284 F: 'static + FnOnce(&mut MutableAppContext),
285 {
286 let platform = self.0.borrow().foreground_platform.clone();
287 platform.run(Box::new(move || {
288 let mut cx = self.0.borrow_mut();
289 let cx = &mut *cx;
290 crate::views::init(cx);
291 on_finish_launching(cx);
292 }))
293 }
294
295 pub fn platform(&self) -> Arc<dyn Platform> {
296 self.0.borrow().platform()
297 }
298
299 pub fn font_cache(&self) -> Arc<FontCache> {
300 self.0.borrow().cx.font_cache.clone()
301 }
302
303 fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
304 let mut state = self.0.borrow_mut();
305 let result = state.update(callback);
306 state.pending_notifications.clear();
307 result
308 }
309}
310
311#[cfg(any(test, feature = "test-support"))]
312impl TestAppContext {
313 pub fn new(
314 foreground_platform: Rc<platform::test::ForegroundPlatform>,
315 platform: Arc<dyn Platform>,
316 foreground: Rc<executor::Foreground>,
317 background: Arc<executor::Background>,
318 font_cache: Arc<FontCache>,
319 leak_detector: Arc<Mutex<LeakDetector>>,
320 first_entity_id: usize,
321 ) -> Self {
322 let mut cx = MutableAppContext::new(
323 foreground.clone(),
324 background,
325 platform,
326 foreground_platform.clone(),
327 font_cache,
328 RefCounts {
329 #[cfg(any(test, feature = "test-support"))]
330 leak_detector,
331 ..Default::default()
332 },
333 (),
334 );
335 cx.next_entity_id = first_entity_id;
336 let cx = TestAppContext {
337 cx: Rc::new(RefCell::new(cx)),
338 foreground_platform,
339 };
340 cx.cx.borrow_mut().weak_self = Some(Rc::downgrade(&cx.cx));
341 cx
342 }
343
344 pub fn dispatch_action<A: Action>(&self, window_id: usize, action: A) {
345 let mut cx = self.cx.borrow_mut();
346 let dispatch_path = cx
347 .presenters_and_platform_windows
348 .get(&window_id)
349 .unwrap()
350 .0
351 .borrow()
352 .dispatch_path(cx.as_ref());
353
354 cx.dispatch_action_any(window_id, &dispatch_path, &action);
355 }
356
357 pub fn dispatch_global_action<A: Action>(&self, action: A) {
358 self.cx.borrow_mut().dispatch_global_action(action);
359 }
360
361 pub fn dispatch_keystroke(
362 &mut self,
363 window_id: usize,
364 keystroke: Keystroke,
365 input: Option<String>,
366 is_held: bool,
367 ) {
368 self.cx.borrow_mut().update(|cx| {
369 let presenter = cx
370 .presenters_and_platform_windows
371 .get(&window_id)
372 .unwrap()
373 .0
374 .clone();
375 let dispatch_path = presenter.borrow().dispatch_path(cx.as_ref());
376
377 if !cx.dispatch_keystroke(window_id, dispatch_path, &keystroke) {
378 presenter.borrow_mut().dispatch_event(
379 Event::KeyDown {
380 keystroke,
381 input,
382 is_held,
383 },
384 cx,
385 );
386 }
387 });
388 }
389
390 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
391 where
392 T: Entity,
393 F: FnOnce(&mut ModelContext<T>) -> T,
394 {
395 self.cx.borrow_mut().add_model(build_model)
396 }
397
398 pub fn add_window<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>)
399 where
400 T: View,
401 F: FnOnce(&mut ViewContext<T>) -> T,
402 {
403 self.cx
404 .borrow_mut()
405 .add_window(Default::default(), build_root_view)
406 }
407
408 pub fn window_ids(&self) -> Vec<usize> {
409 self.cx.borrow().window_ids().collect()
410 }
411
412 pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
413 self.cx.borrow().root_view(window_id)
414 }
415
416 pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
417 where
418 T: View,
419 F: FnOnce(&mut ViewContext<T>) -> T,
420 {
421 self.cx.borrow_mut().add_view(window_id, build_view)
422 }
423
424 pub fn add_option_view<T, F>(
425 &mut self,
426 window_id: usize,
427 build_view: F,
428 ) -> Option<ViewHandle<T>>
429 where
430 T: View,
431 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
432 {
433 self.cx.borrow_mut().add_option_view(window_id, build_view)
434 }
435
436 pub fn read<T, F: FnOnce(&AppContext) -> T>(&self, callback: F) -> T {
437 callback(self.cx.borrow().as_ref())
438 }
439
440 pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
441 let mut state = self.cx.borrow_mut();
442 // Don't increment pending flushes in order for effects to be flushed before the callback
443 // completes, which is helpful in tests.
444 let result = callback(&mut *state);
445 // Flush effects after the callback just in case there are any. This can happen in edge
446 // cases such as the closure dropping handles.
447 state.flush_effects();
448 result
449 }
450
451 pub fn render<F, V, T>(&mut self, handle: &ViewHandle<V>, f: F) -> T
452 where
453 F: FnOnce(&mut V, &mut RenderContext<V>) -> T,
454 V: View,
455 {
456 handle.update(&mut *self.cx.borrow_mut(), |view, cx| {
457 let mut render_cx = RenderContext {
458 app: cx,
459 window_id: handle.window_id(),
460 view_id: handle.id(),
461 view_type: PhantomData,
462 titlebar_height: 0.,
463 hovered_region_ids: Default::default(),
464 clicked_region_id: None,
465 right_clicked_region_id: None,
466 refreshing: false,
467 };
468 f(view, &mut render_cx)
469 })
470 }
471
472 pub fn to_async(&self) -> AsyncAppContext {
473 AsyncAppContext(self.cx.clone())
474 }
475
476 pub fn font_cache(&self) -> Arc<FontCache> {
477 self.cx.borrow().cx.font_cache.clone()
478 }
479
480 pub fn foreground_platform(&self) -> Rc<platform::test::ForegroundPlatform> {
481 self.foreground_platform.clone()
482 }
483
484 pub fn platform(&self) -> Arc<dyn platform::Platform> {
485 self.cx.borrow().cx.platform.clone()
486 }
487
488 pub fn foreground(&self) -> Rc<executor::Foreground> {
489 self.cx.borrow().foreground().clone()
490 }
491
492 pub fn background(&self) -> Arc<executor::Background> {
493 self.cx.borrow().background().clone()
494 }
495
496 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
497 where
498 F: FnOnce(AsyncAppContext) -> Fut,
499 Fut: 'static + Future<Output = T>,
500 T: 'static,
501 {
502 self.cx.borrow_mut().spawn(f)
503 }
504
505 pub fn simulate_new_path_selection(&self, result: impl FnOnce(PathBuf) -> Option<PathBuf>) {
506 self.foreground_platform.simulate_new_path_selection(result);
507 }
508
509 pub fn did_prompt_for_new_path(&self) -> bool {
510 self.foreground_platform.as_ref().did_prompt_for_new_path()
511 }
512
513 pub fn simulate_prompt_answer(&self, window_id: usize, answer: usize) {
514 use postage::prelude::Sink as _;
515
516 let mut state = self.cx.borrow_mut();
517 let (_, window) = state
518 .presenters_and_platform_windows
519 .get_mut(&window_id)
520 .unwrap();
521 let test_window = window
522 .as_any_mut()
523 .downcast_mut::<platform::test::Window>()
524 .unwrap();
525 let mut done_tx = test_window
526 .pending_prompts
527 .borrow_mut()
528 .pop_front()
529 .expect("prompt was not called");
530 let _ = done_tx.try_send(answer);
531 }
532
533 pub fn has_pending_prompt(&self, window_id: usize) -> bool {
534 let mut state = self.cx.borrow_mut();
535 let (_, window) = state
536 .presenters_and_platform_windows
537 .get_mut(&window_id)
538 .unwrap();
539 let test_window = window
540 .as_any_mut()
541 .downcast_mut::<platform::test::Window>()
542 .unwrap();
543 let prompts = test_window.pending_prompts.borrow_mut();
544 !prompts.is_empty()
545 }
546
547 #[cfg(any(test, feature = "test-support"))]
548 pub fn leak_detector(&self) -> Arc<Mutex<LeakDetector>> {
549 self.cx.borrow().leak_detector()
550 }
551
552 #[cfg(any(test, feature = "test-support"))]
553 pub fn assert_dropped(&self, handle: impl WeakHandle) {
554 self.cx
555 .borrow()
556 .leak_detector()
557 .lock()
558 .assert_dropped(handle.id())
559 }
560}
561
562impl AsyncAppContext {
563 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
564 where
565 F: FnOnce(AsyncAppContext) -> Fut,
566 Fut: 'static + Future<Output = T>,
567 T: 'static,
568 {
569 self.0.borrow().foreground.spawn(f(self.clone()))
570 }
571
572 pub fn read<T, F: FnOnce(&AppContext) -> T>(&mut self, callback: F) -> T {
573 callback(self.0.borrow().as_ref())
574 }
575
576 pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
577 self.0.borrow_mut().update(callback)
578 }
579
580 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
581 where
582 T: Entity,
583 F: FnOnce(&mut ModelContext<T>) -> T,
584 {
585 self.update(|cx| cx.add_model(build_model))
586 }
587
588 pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
589 where
590 T: View,
591 F: FnOnce(&mut ViewContext<T>) -> T,
592 {
593 self.update(|cx| cx.add_view(window_id, build_view))
594 }
595
596 pub fn add_window<T, F>(
597 &mut self,
598 window_options: WindowOptions,
599 build_root_view: F,
600 ) -> (usize, ViewHandle<T>)
601 where
602 T: View,
603 F: FnOnce(&mut ViewContext<T>) -> T,
604 {
605 self.update(|cx| cx.add_window(window_options, build_root_view))
606 }
607
608 pub fn platform(&self) -> Arc<dyn Platform> {
609 self.0.borrow().platform()
610 }
611
612 pub fn foreground(&self) -> Rc<executor::Foreground> {
613 self.0.borrow().foreground.clone()
614 }
615
616 pub fn background(&self) -> Arc<executor::Background> {
617 self.0.borrow().cx.background.clone()
618 }
619}
620
621impl UpdateModel for AsyncAppContext {
622 fn update_model<E: Entity, O>(
623 &mut self,
624 handle: &ModelHandle<E>,
625 update: &mut dyn FnMut(&mut E, &mut ModelContext<E>) -> O,
626 ) -> O {
627 self.0.borrow_mut().update_model(handle, update)
628 }
629}
630
631impl UpgradeModelHandle for AsyncAppContext {
632 fn upgrade_model_handle<T: Entity>(
633 &self,
634 handle: &WeakModelHandle<T>,
635 ) -> Option<ModelHandle<T>> {
636 self.0.borrow().upgrade_model_handle(handle)
637 }
638
639 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
640 self.0.borrow().model_handle_is_upgradable(handle)
641 }
642
643 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
644 self.0.borrow().upgrade_any_model_handle(handle)
645 }
646}
647
648impl UpgradeViewHandle for AsyncAppContext {
649 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
650 self.0.borrow_mut().upgrade_view_handle(handle)
651 }
652
653 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
654 self.0.borrow_mut().upgrade_any_view_handle(handle)
655 }
656}
657
658impl ReadModelWith for AsyncAppContext {
659 fn read_model_with<E: Entity, T>(
660 &self,
661 handle: &ModelHandle<E>,
662 read: &mut dyn FnMut(&E, &AppContext) -> T,
663 ) -> T {
664 let cx = self.0.borrow();
665 let cx = cx.as_ref();
666 read(handle.read(cx), cx)
667 }
668}
669
670impl UpdateView for AsyncAppContext {
671 fn update_view<T, S>(
672 &mut self,
673 handle: &ViewHandle<T>,
674 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
675 ) -> S
676 where
677 T: View,
678 {
679 self.0.borrow_mut().update_view(handle, update)
680 }
681}
682
683impl ReadViewWith for AsyncAppContext {
684 fn read_view_with<V, T>(
685 &self,
686 handle: &ViewHandle<V>,
687 read: &mut dyn FnMut(&V, &AppContext) -> T,
688 ) -> T
689 where
690 V: View,
691 {
692 let cx = self.0.borrow();
693 let cx = cx.as_ref();
694 read(handle.read(cx), cx)
695 }
696}
697
698#[cfg(any(test, feature = "test-support"))]
699impl UpdateModel for TestAppContext {
700 fn update_model<T: Entity, O>(
701 &mut self,
702 handle: &ModelHandle<T>,
703 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
704 ) -> O {
705 self.cx.borrow_mut().update_model(handle, update)
706 }
707}
708
709#[cfg(any(test, feature = "test-support"))]
710impl ReadModelWith for TestAppContext {
711 fn read_model_with<E: Entity, T>(
712 &self,
713 handle: &ModelHandle<E>,
714 read: &mut dyn FnMut(&E, &AppContext) -> T,
715 ) -> T {
716 let cx = self.cx.borrow();
717 let cx = cx.as_ref();
718 read(handle.read(cx), cx)
719 }
720}
721
722#[cfg(any(test, feature = "test-support"))]
723impl UpdateView for TestAppContext {
724 fn update_view<T, S>(
725 &mut self,
726 handle: &ViewHandle<T>,
727 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
728 ) -> S
729 where
730 T: View,
731 {
732 self.cx.borrow_mut().update_view(handle, update)
733 }
734}
735
736#[cfg(any(test, feature = "test-support"))]
737impl ReadViewWith for TestAppContext {
738 fn read_view_with<V, T>(
739 &self,
740 handle: &ViewHandle<V>,
741 read: &mut dyn FnMut(&V, &AppContext) -> T,
742 ) -> T
743 where
744 V: View,
745 {
746 let cx = self.cx.borrow();
747 let cx = cx.as_ref();
748 read(handle.read(cx), cx)
749 }
750}
751
752type ActionCallback =
753 dyn FnMut(&mut dyn AnyView, &dyn Action, &mut MutableAppContext, usize, usize);
754type GlobalActionCallback = dyn FnMut(&dyn Action, &mut MutableAppContext);
755
756type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext) -> bool>;
757type GlobalSubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
758type ObservationCallback = Box<dyn FnMut(&mut MutableAppContext) -> bool>;
759type FocusObservationCallback = Box<dyn FnMut(&mut MutableAppContext) -> bool>;
760type GlobalObservationCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
761type ReleaseObservationCallback = Box<dyn FnOnce(&dyn Any, &mut MutableAppContext)>;
762type ActionObservationCallback = Box<dyn FnMut(TypeId, &mut MutableAppContext)>;
763type DeserializeActionCallback = fn(json: &str) -> anyhow::Result<Box<dyn Action>>;
764
765pub struct MutableAppContext {
766 weak_self: Option<rc::Weak<RefCell<Self>>>,
767 foreground_platform: Rc<dyn platform::ForegroundPlatform>,
768 assets: Arc<AssetCache>,
769 cx: AppContext,
770 action_deserializers: HashMap<&'static str, (TypeId, DeserializeActionCallback)>,
771 capture_actions: HashMap<TypeId, HashMap<TypeId, Vec<Box<ActionCallback>>>>,
772 actions: HashMap<TypeId, HashMap<TypeId, Vec<Box<ActionCallback>>>>,
773 global_actions: HashMap<TypeId, Box<GlobalActionCallback>>,
774 keystroke_matcher: keymap::Matcher,
775 next_entity_id: usize,
776 next_window_id: usize,
777 next_subscription_id: usize,
778 frame_count: usize,
779 subscriptions: Arc<Mutex<HashMap<usize, BTreeMap<usize, Option<SubscriptionCallback>>>>>,
780 global_subscriptions:
781 Arc<Mutex<HashMap<TypeId, BTreeMap<usize, Option<GlobalSubscriptionCallback>>>>>,
782 observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, Option<ObservationCallback>>>>>,
783 focus_observations:
784 Arc<Mutex<HashMap<usize, BTreeMap<usize, Option<FocusObservationCallback>>>>>,
785 global_observations:
786 Arc<Mutex<HashMap<TypeId, BTreeMap<usize, Option<GlobalObservationCallback>>>>>,
787 release_observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>,
788 action_dispatch_observations: Arc<Mutex<BTreeMap<usize, ActionObservationCallback>>>,
789 presenters_and_platform_windows:
790 HashMap<usize, (Rc<RefCell<Presenter>>, Box<dyn platform::Window>)>,
791 foreground: Rc<executor::Foreground>,
792 pending_effects: VecDeque<Effect>,
793 pending_focus_index: Option<usize>,
794 pending_notifications: HashSet<usize>,
795 pending_global_notifications: HashSet<TypeId>,
796 pending_flushes: usize,
797 flushing_effects: bool,
798 halt_action_dispatch: bool,
799}
800
801impl MutableAppContext {
802 fn new(
803 foreground: Rc<executor::Foreground>,
804 background: Arc<executor::Background>,
805 platform: Arc<dyn platform::Platform>,
806 foreground_platform: Rc<dyn platform::ForegroundPlatform>,
807 font_cache: Arc<FontCache>,
808 ref_counts: RefCounts,
809 asset_source: impl AssetSource,
810 ) -> Self {
811 Self {
812 weak_self: None,
813 foreground_platform,
814 assets: Arc::new(AssetCache::new(asset_source)),
815 cx: AppContext {
816 models: Default::default(),
817 views: Default::default(),
818 windows: Default::default(),
819 globals: Default::default(),
820 element_states: Default::default(),
821 ref_counts: Arc::new(Mutex::new(ref_counts)),
822 background,
823 font_cache,
824 platform,
825 },
826 action_deserializers: HashMap::new(),
827 capture_actions: HashMap::new(),
828 actions: HashMap::new(),
829 global_actions: HashMap::new(),
830 keystroke_matcher: keymap::Matcher::default(),
831 next_entity_id: 0,
832 next_window_id: 0,
833 next_subscription_id: 0,
834 frame_count: 0,
835 subscriptions: Default::default(),
836 global_subscriptions: Default::default(),
837 observations: Default::default(),
838 focus_observations: Default::default(),
839 release_observations: Default::default(),
840 global_observations: Default::default(),
841 action_dispatch_observations: Default::default(),
842 presenters_and_platform_windows: HashMap::new(),
843 foreground,
844 pending_effects: VecDeque::new(),
845 pending_focus_index: None,
846 pending_notifications: HashSet::new(),
847 pending_global_notifications: HashSet::new(),
848 pending_flushes: 0,
849 flushing_effects: false,
850 halt_action_dispatch: false,
851 }
852 }
853
854 pub fn upgrade(&self) -> App {
855 App(self.weak_self.as_ref().unwrap().upgrade().unwrap())
856 }
857
858 pub fn quit(&mut self) {
859 let mut futures = Vec::new();
860 for model_id in self.cx.models.keys().copied().collect::<Vec<_>>() {
861 let mut model = self.cx.models.remove(&model_id).unwrap();
862 futures.extend(model.app_will_quit(self));
863 self.cx.models.insert(model_id, model);
864 }
865
866 for view_id in self.cx.views.keys().copied().collect::<Vec<_>>() {
867 let mut view = self.cx.views.remove(&view_id).unwrap();
868 futures.extend(view.app_will_quit(self));
869 self.cx.views.insert(view_id, view);
870 }
871
872 self.remove_all_windows();
873
874 let futures = futures::future::join_all(futures);
875 if self
876 .background
877 .block_with_timeout(Duration::from_millis(100), futures)
878 .is_err()
879 {
880 log::error!("timed out waiting on app_will_quit");
881 }
882 }
883
884 pub fn remove_all_windows(&mut self) {
885 for (window_id, _) in self.cx.windows.drain() {
886 self.presenters_and_platform_windows.remove(&window_id);
887 }
888 self.flush_effects();
889 }
890
891 pub fn platform(&self) -> Arc<dyn platform::Platform> {
892 self.cx.platform.clone()
893 }
894
895 pub fn font_cache(&self) -> &Arc<FontCache> {
896 &self.cx.font_cache
897 }
898
899 pub fn foreground(&self) -> &Rc<executor::Foreground> {
900 &self.foreground
901 }
902
903 pub fn background(&self) -> &Arc<executor::Background> {
904 &self.cx.background
905 }
906
907 pub fn debug_elements(&self, window_id: usize) -> Option<crate::json::Value> {
908 self.presenters_and_platform_windows
909 .get(&window_id)
910 .and_then(|(presenter, _)| presenter.borrow().debug_elements(self))
911 }
912
913 pub fn deserialize_action(
914 &self,
915 name: &str,
916 argument: Option<&str>,
917 ) -> Result<Box<dyn Action>> {
918 let callback = self
919 .action_deserializers
920 .get(name)
921 .ok_or_else(|| anyhow!("unknown action {}", name))?
922 .1;
923 callback(argument.unwrap_or("{}"))
924 .with_context(|| format!("invalid data for action {}", name))
925 }
926
927 pub fn add_action<A, V, F>(&mut self, handler: F)
928 where
929 A: Action,
930 V: View,
931 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>),
932 {
933 self.add_action_internal(handler, false)
934 }
935
936 pub fn capture_action<A, V, F>(&mut self, handler: F)
937 where
938 A: Action,
939 V: View,
940 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>),
941 {
942 self.add_action_internal(handler, true)
943 }
944
945 fn add_action_internal<A, V, F>(&mut self, mut handler: F, capture: bool)
946 where
947 A: Action,
948 V: View,
949 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>),
950 {
951 let handler = Box::new(
952 move |view: &mut dyn AnyView,
953 action: &dyn Action,
954 cx: &mut MutableAppContext,
955 window_id: usize,
956 view_id: usize| {
957 let action = action.as_any().downcast_ref().unwrap();
958 let mut cx = ViewContext::new(cx, window_id, view_id);
959 handler(
960 view.as_any_mut()
961 .downcast_mut()
962 .expect("downcast is type safe"),
963 action,
964 &mut cx,
965 );
966 },
967 );
968
969 self.action_deserializers
970 .entry(A::qualified_name())
971 .or_insert((TypeId::of::<A>(), A::from_json_str));
972
973 let actions = if capture {
974 &mut self.capture_actions
975 } else {
976 &mut self.actions
977 };
978
979 actions
980 .entry(TypeId::of::<V>())
981 .or_default()
982 .entry(TypeId::of::<A>())
983 .or_default()
984 .push(handler);
985 }
986
987 pub fn add_async_action<A, V, F>(&mut self, mut handler: F)
988 where
989 A: Action,
990 V: View,
991 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>) -> Option<Task<Result<()>>>,
992 {
993 self.add_action(move |view, action, cx| {
994 handler(view, action, cx).map(|task| task.detach_and_log_err(cx));
995 })
996 }
997
998 pub fn add_global_action<A, F>(&mut self, mut handler: F)
999 where
1000 A: Action,
1001 F: 'static + FnMut(&A, &mut MutableAppContext),
1002 {
1003 let handler = Box::new(move |action: &dyn Action, cx: &mut MutableAppContext| {
1004 let action = action.as_any().downcast_ref().unwrap();
1005 handler(action, cx);
1006 });
1007
1008 self.action_deserializers
1009 .entry(A::qualified_name())
1010 .or_insert((TypeId::of::<A>(), A::from_json_str));
1011
1012 if self
1013 .global_actions
1014 .insert(TypeId::of::<A>(), handler)
1015 .is_some()
1016 {
1017 panic!(
1018 "registered multiple global handlers for {}",
1019 type_name::<A>()
1020 );
1021 }
1022 }
1023
1024 pub fn window_ids(&self) -> impl Iterator<Item = usize> + '_ {
1025 self.cx.windows.keys().cloned()
1026 }
1027
1028 pub fn activate_window(&self, window_id: usize) {
1029 if let Some((_, window)) = self.presenters_and_platform_windows.get(&window_id) {
1030 window.activate()
1031 }
1032 }
1033
1034 pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
1035 self.cx
1036 .windows
1037 .get(&window_id)
1038 .and_then(|window| window.root_view.clone().downcast::<T>())
1039 }
1040
1041 pub fn window_is_active(&self, window_id: usize) -> bool {
1042 self.cx
1043 .windows
1044 .get(&window_id)
1045 .map_or(false, |window| window.is_active)
1046 }
1047
1048 pub fn render_view(&mut self, params: RenderParams) -> Result<ElementBox> {
1049 let window_id = params.window_id;
1050 let view_id = params.view_id;
1051 let mut view = self
1052 .cx
1053 .views
1054 .remove(&(params.window_id, params.view_id))
1055 .ok_or(anyhow!("view not found"))?;
1056 let element = view.render(params, self);
1057 self.cx.views.insert((window_id, view_id), view);
1058 Ok(element)
1059 }
1060
1061 pub fn render_views(
1062 &mut self,
1063 window_id: usize,
1064 titlebar_height: f32,
1065 ) -> HashMap<usize, ElementBox> {
1066 self.start_frame();
1067 let view_ids = self
1068 .views
1069 .keys()
1070 .filter_map(|(win_id, view_id)| {
1071 if *win_id == window_id {
1072 Some(*view_id)
1073 } else {
1074 None
1075 }
1076 })
1077 .collect::<Vec<_>>();
1078 view_ids
1079 .into_iter()
1080 .map(|view_id| {
1081 (
1082 view_id,
1083 self.render_view(RenderParams {
1084 window_id,
1085 view_id,
1086 titlebar_height,
1087 hovered_region_ids: Default::default(),
1088 clicked_region_id: None,
1089 right_clicked_region_id: None,
1090 refreshing: false,
1091 })
1092 .unwrap(),
1093 )
1094 })
1095 .collect()
1096 }
1097
1098 pub(crate) fn start_frame(&mut self) {
1099 self.frame_count += 1;
1100 }
1101
1102 pub fn update<T, F: FnOnce(&mut Self) -> T>(&mut self, callback: F) -> T {
1103 self.pending_flushes += 1;
1104 let result = callback(self);
1105 self.flush_effects();
1106 result
1107 }
1108
1109 pub fn set_menus(&mut self, menus: Vec<Menu>) {
1110 self.foreground_platform
1111 .set_menus(menus, &self.keystroke_matcher);
1112 }
1113
1114 fn prompt(
1115 &self,
1116 window_id: usize,
1117 level: PromptLevel,
1118 msg: &str,
1119 answers: &[&str],
1120 ) -> oneshot::Receiver<usize> {
1121 let (_, window) = &self.presenters_and_platform_windows[&window_id];
1122 window.prompt(level, msg, answers)
1123 }
1124
1125 pub fn prompt_for_paths(
1126 &self,
1127 options: PathPromptOptions,
1128 ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
1129 self.foreground_platform.prompt_for_paths(options)
1130 }
1131
1132 pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
1133 self.foreground_platform.prompt_for_new_path(directory)
1134 }
1135
1136 pub fn emit_global<E: Any>(&mut self, payload: E) {
1137 self.pending_effects.push_back(Effect::GlobalEvent {
1138 payload: Box::new(payload),
1139 });
1140 }
1141
1142 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1143 where
1144 E: Entity,
1145 E::Event: 'static,
1146 H: Handle<E>,
1147 F: 'static + FnMut(H, &E::Event, &mut Self),
1148 {
1149 self.subscribe_internal(handle, move |handle, event, cx| {
1150 callback(handle, event, cx);
1151 true
1152 })
1153 }
1154
1155 pub fn subscribe_global<E, F>(&mut self, mut callback: F) -> Subscription
1156 where
1157 E: Any,
1158 F: 'static + FnMut(&E, &mut Self),
1159 {
1160 let subscription_id = post_inc(&mut self.next_subscription_id);
1161 let type_id = TypeId::of::<E>();
1162 self.pending_effects.push_back(Effect::GlobalSubscription {
1163 type_id,
1164 subscription_id,
1165 callback: Box::new(move |payload, cx| {
1166 let payload = payload.downcast_ref().expect("downcast is type safe");
1167 callback(payload, cx)
1168 }),
1169 });
1170 Subscription::GlobalSubscription {
1171 id: subscription_id,
1172 type_id,
1173 subscriptions: Some(Arc::downgrade(&self.global_subscriptions)),
1174 }
1175 }
1176
1177 pub fn observe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1178 where
1179 E: Entity,
1180 E::Event: 'static,
1181 H: Handle<E>,
1182 F: 'static + FnMut(H, &mut Self),
1183 {
1184 self.observe_internal(handle, move |handle, cx| {
1185 callback(handle, cx);
1186 true
1187 })
1188 }
1189
1190 pub fn subscribe_internal<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1191 where
1192 E: Entity,
1193 E::Event: 'static,
1194 H: Handle<E>,
1195 F: 'static + FnMut(H, &E::Event, &mut Self) -> bool,
1196 {
1197 let subscription_id = post_inc(&mut self.next_subscription_id);
1198 let emitter = handle.downgrade();
1199 self.pending_effects.push_back(Effect::Subscription {
1200 entity_id: handle.id(),
1201 subscription_id,
1202 callback: Box::new(move |payload, cx| {
1203 if let Some(emitter) = H::upgrade_from(&emitter, cx.as_ref()) {
1204 let payload = payload.downcast_ref().expect("downcast is type safe");
1205 callback(emitter, payload, cx)
1206 } else {
1207 false
1208 }
1209 }),
1210 });
1211 Subscription::Subscription {
1212 id: subscription_id,
1213 entity_id: handle.id(),
1214 subscriptions: Some(Arc::downgrade(&self.subscriptions)),
1215 }
1216 }
1217
1218 fn observe_internal<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1219 where
1220 E: Entity,
1221 E::Event: 'static,
1222 H: Handle<E>,
1223 F: 'static + FnMut(H, &mut Self) -> bool,
1224 {
1225 let subscription_id = post_inc(&mut self.next_subscription_id);
1226 let observed = handle.downgrade();
1227 let entity_id = handle.id();
1228 self.pending_effects.push_back(Effect::Observation {
1229 entity_id,
1230 subscription_id,
1231 callback: Box::new(move |cx| {
1232 if let Some(observed) = H::upgrade_from(&observed, cx) {
1233 callback(observed, cx)
1234 } else {
1235 false
1236 }
1237 }),
1238 });
1239 Subscription::Observation {
1240 id: subscription_id,
1241 entity_id,
1242 observations: Some(Arc::downgrade(&self.observations)),
1243 }
1244 }
1245
1246 fn observe_focus<F, V>(&mut self, handle: &ViewHandle<V>, mut callback: F) -> Subscription
1247 where
1248 F: 'static + FnMut(ViewHandle<V>, &mut MutableAppContext) -> bool,
1249 V: View,
1250 {
1251 let subscription_id = post_inc(&mut self.next_subscription_id);
1252 let observed = handle.downgrade();
1253 let view_id = handle.id();
1254 self.pending_effects.push_back(Effect::FocusObservation {
1255 view_id,
1256 subscription_id,
1257 callback: Box::new(move |cx| {
1258 if let Some(observed) = observed.upgrade(cx) {
1259 callback(observed, cx)
1260 } else {
1261 false
1262 }
1263 }),
1264 });
1265 Subscription::FocusObservation {
1266 id: subscription_id,
1267 view_id,
1268 observations: Some(Arc::downgrade(&self.focus_observations)),
1269 }
1270 }
1271
1272 pub fn observe_global<G, F>(&mut self, mut observe: F) -> Subscription
1273 where
1274 G: Any,
1275 F: 'static + FnMut(&G, &mut MutableAppContext),
1276 {
1277 let type_id = TypeId::of::<G>();
1278 let id = post_inc(&mut self.next_subscription_id);
1279
1280 self.global_observations
1281 .lock()
1282 .entry(type_id)
1283 .or_default()
1284 .insert(
1285 id,
1286 Some(
1287 Box::new(move |global: &dyn Any, cx: &mut MutableAppContext| {
1288 observe(global.downcast_ref().unwrap(), cx)
1289 }) as GlobalObservationCallback,
1290 ),
1291 );
1292
1293 Subscription::GlobalObservation {
1294 id,
1295 type_id,
1296 observations: Some(Arc::downgrade(&self.global_observations)),
1297 }
1298 }
1299
1300 pub fn observe_release<E, H, F>(&mut self, handle: &H, callback: F) -> Subscription
1301 where
1302 E: Entity,
1303 E::Event: 'static,
1304 H: Handle<E>,
1305 F: 'static + FnOnce(&E, &mut Self),
1306 {
1307 let id = post_inc(&mut self.next_subscription_id);
1308 self.release_observations
1309 .lock()
1310 .entry(handle.id())
1311 .or_default()
1312 .insert(
1313 id,
1314 Box::new(move |released, cx| {
1315 let released = released.downcast_ref().unwrap();
1316 callback(released, cx)
1317 }),
1318 );
1319 Subscription::ReleaseObservation {
1320 id,
1321 entity_id: handle.id(),
1322 observations: Some(Arc::downgrade(&self.release_observations)),
1323 }
1324 }
1325
1326 pub fn observe_actions<F>(&mut self, callback: F) -> Subscription
1327 where
1328 F: 'static + FnMut(TypeId, &mut MutableAppContext),
1329 {
1330 let id = post_inc(&mut self.next_subscription_id);
1331 self.action_dispatch_observations
1332 .lock()
1333 .insert(id, Box::new(callback));
1334 Subscription::ActionObservation {
1335 id,
1336 observations: Some(Arc::downgrade(&self.action_dispatch_observations)),
1337 }
1338 }
1339
1340 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut MutableAppContext)) {
1341 self.pending_effects.push_back(Effect::Deferred {
1342 callback: Box::new(callback),
1343 after_window_update: false,
1344 })
1345 }
1346
1347 pub fn after_window_update(&mut self, callback: impl 'static + FnOnce(&mut MutableAppContext)) {
1348 self.pending_effects.push_back(Effect::Deferred {
1349 callback: Box::new(callback),
1350 after_window_update: true,
1351 })
1352 }
1353
1354 pub(crate) fn notify_model(&mut self, model_id: usize) {
1355 if self.pending_notifications.insert(model_id) {
1356 self.pending_effects
1357 .push_back(Effect::ModelNotification { model_id });
1358 }
1359 }
1360
1361 pub(crate) fn notify_view(&mut self, window_id: usize, view_id: usize) {
1362 if self.pending_notifications.insert(view_id) {
1363 self.pending_effects
1364 .push_back(Effect::ViewNotification { window_id, view_id });
1365 }
1366 }
1367
1368 pub(crate) fn notify_global(&mut self, type_id: TypeId) {
1369 if self.pending_global_notifications.insert(type_id) {
1370 self.pending_effects
1371 .push_back(Effect::GlobalNotification { type_id });
1372 }
1373 }
1374
1375 pub fn all_action_names<'a>(&'a self) -> impl Iterator<Item = &'static str> + 'a {
1376 self.action_deserializers.keys().copied()
1377 }
1378
1379 pub fn available_actions(
1380 &self,
1381 window_id: usize,
1382 view_id: usize,
1383 ) -> impl Iterator<Item = (&'static str, Box<dyn Action>, SmallVec<[&Binding; 1]>)> {
1384 let mut action_types: HashSet<_> = self.global_actions.keys().copied().collect();
1385
1386 let presenter = self
1387 .presenters_and_platform_windows
1388 .get(&window_id)
1389 .unwrap()
1390 .0
1391 .clone();
1392 let mut dispatch_path = Vec::new();
1393 presenter
1394 .borrow()
1395 .compute_dispatch_path_from(view_id, &mut dispatch_path);
1396 for view_id in dispatch_path {
1397 if let Some(view) = self.views.get(&(window_id, view_id)) {
1398 let view_type = view.as_any().type_id();
1399 if let Some(actions) = self.actions.get(&view_type) {
1400 action_types.extend(actions.keys().copied());
1401 }
1402 }
1403 }
1404
1405 self.action_deserializers
1406 .iter()
1407 .filter_map(move |(name, (type_id, deserialize))| {
1408 if action_types.contains(type_id) {
1409 Some((
1410 *name,
1411 deserialize("{}").ok()?,
1412 self.keystroke_matcher
1413 .bindings_for_action_type(*type_id)
1414 .collect(),
1415 ))
1416 } else {
1417 None
1418 }
1419 })
1420 }
1421
1422 pub fn is_action_available(&self, action: &dyn Action) -> bool {
1423 let action_type = action.as_any().type_id();
1424 if let Some(window_id) = self.cx.platform.key_window_id() {
1425 if let Some((presenter, _)) = self.presenters_and_platform_windows.get(&window_id) {
1426 let dispatch_path = presenter.borrow().dispatch_path(&self.cx);
1427 for view_id in dispatch_path {
1428 if let Some(view) = self.views.get(&(window_id, view_id)) {
1429 let view_type = view.as_any().type_id();
1430 if let Some(actions) = self.actions.get(&view_type) {
1431 if actions.contains_key(&action_type) {
1432 return true;
1433 }
1434 }
1435 }
1436 }
1437 }
1438 }
1439 self.global_actions.contains_key(&action_type)
1440 }
1441
1442 /// Return keystrokes that would dispatch the given action closest to the focused view, if there are any.
1443 pub(crate) fn keystrokes_for_action(
1444 &self,
1445 window_id: usize,
1446 dispatch_path: &[usize],
1447 action: &dyn Action,
1448 ) -> Option<SmallVec<[Keystroke; 2]>> {
1449 for view_id in dispatch_path.iter().rev() {
1450 let view = self
1451 .cx
1452 .views
1453 .get(&(window_id, *view_id))
1454 .expect("view in responder chain does not exist");
1455 let cx = view.keymap_context(self.as_ref());
1456 let keystrokes = self.keystroke_matcher.keystrokes_for_action(action, &cx);
1457 if keystrokes.is_some() {
1458 return keystrokes;
1459 }
1460 }
1461
1462 None
1463 }
1464
1465 pub fn dispatch_action_at(&mut self, window_id: usize, view_id: usize, action: &dyn Action) {
1466 let presenter = self
1467 .presenters_and_platform_windows
1468 .get(&window_id)
1469 .unwrap()
1470 .0
1471 .clone();
1472 let mut dispatch_path = Vec::new();
1473 presenter
1474 .borrow()
1475 .compute_dispatch_path_from(view_id, &mut dispatch_path);
1476 self.dispatch_action_any(window_id, &dispatch_path, action);
1477 }
1478
1479 pub fn dispatch_action<A: Action>(
1480 &mut self,
1481 window_id: usize,
1482 dispatch_path: Vec<usize>,
1483 action: &A,
1484 ) {
1485 self.dispatch_action_any(window_id, &dispatch_path, action);
1486 }
1487
1488 pub(crate) fn dispatch_action_any(
1489 &mut self,
1490 window_id: usize,
1491 path: &[usize],
1492 action: &dyn Action,
1493 ) -> bool {
1494 self.update(|this| {
1495 this.halt_action_dispatch = false;
1496 for (capture_phase, view_id) in path
1497 .iter()
1498 .map(|view_id| (true, *view_id))
1499 .chain(path.iter().rev().map(|view_id| (false, *view_id)))
1500 {
1501 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
1502 let type_id = view.as_any().type_id();
1503
1504 if let Some((name, mut handlers)) = this
1505 .actions_mut(capture_phase)
1506 .get_mut(&type_id)
1507 .and_then(|h| h.remove_entry(&action.id()))
1508 {
1509 for handler in handlers.iter_mut().rev() {
1510 this.halt_action_dispatch = true;
1511 handler(view.as_mut(), action, this, window_id, view_id);
1512 if this.halt_action_dispatch {
1513 break;
1514 }
1515 }
1516 this.actions_mut(capture_phase)
1517 .get_mut(&type_id)
1518 .unwrap()
1519 .insert(name, handlers);
1520 }
1521
1522 this.cx.views.insert((window_id, view_id), view);
1523
1524 if this.halt_action_dispatch {
1525 break;
1526 }
1527 }
1528 }
1529
1530 if !this.halt_action_dispatch {
1531 this.halt_action_dispatch = this.dispatch_global_action_any(action);
1532 }
1533
1534 this.pending_effects
1535 .push_back(Effect::ActionDispatchNotification {
1536 action_id: action.id(),
1537 });
1538 this.halt_action_dispatch
1539 })
1540 }
1541
1542 fn actions_mut(
1543 &mut self,
1544 capture_phase: bool,
1545 ) -> &mut HashMap<TypeId, HashMap<TypeId, Vec<Box<ActionCallback>>>> {
1546 if capture_phase {
1547 &mut self.capture_actions
1548 } else {
1549 &mut self.actions
1550 }
1551 }
1552
1553 pub fn dispatch_global_action<A: Action>(&mut self, action: A) {
1554 self.dispatch_global_action_any(&action);
1555 }
1556
1557 fn dispatch_global_action_any(&mut self, action: &dyn Action) -> bool {
1558 self.update(|this| {
1559 if let Some((name, mut handler)) = this.global_actions.remove_entry(&action.id()) {
1560 handler(action, this);
1561 this.global_actions.insert(name, handler);
1562 true
1563 } else {
1564 false
1565 }
1566 })
1567 }
1568
1569 pub fn add_bindings<T: IntoIterator<Item = keymap::Binding>>(&mut self, bindings: T) {
1570 self.keystroke_matcher.add_bindings(bindings);
1571 }
1572
1573 pub fn clear_bindings(&mut self) {
1574 self.keystroke_matcher.clear_bindings();
1575 }
1576
1577 pub fn dispatch_keystroke(
1578 &mut self,
1579 window_id: usize,
1580 dispatch_path: Vec<usize>,
1581 keystroke: &Keystroke,
1582 ) -> bool {
1583 let mut context_chain = Vec::new();
1584 for view_id in &dispatch_path {
1585 let view = self
1586 .cx
1587 .views
1588 .get(&(window_id, *view_id))
1589 .expect("view in responder chain does not exist");
1590 context_chain.push(view.keymap_context(self.as_ref()));
1591 }
1592
1593 let mut pending = false;
1594 for (i, cx) in context_chain.iter().enumerate().rev() {
1595 match self
1596 .keystroke_matcher
1597 .push_keystroke(keystroke.clone(), dispatch_path[i], cx)
1598 {
1599 MatchResult::None => {}
1600 MatchResult::Pending => pending = true,
1601 MatchResult::Action(action) => {
1602 if self.dispatch_action_any(window_id, &dispatch_path[0..=i], action.as_ref()) {
1603 self.keystroke_matcher.clear_pending();
1604 return true;
1605 }
1606 }
1607 }
1608 }
1609
1610 pending
1611 }
1612
1613 pub fn default_global<T: 'static + Default>(&mut self) -> &T {
1614 let type_id = TypeId::of::<T>();
1615 self.update(|this| {
1616 if !this.globals.contains_key(&type_id) {
1617 this.notify_global(type_id);
1618 }
1619
1620 this.cx
1621 .globals
1622 .entry(type_id)
1623 .or_insert_with(|| Box::new(T::default()));
1624 });
1625 self.globals.get(&type_id).unwrap().downcast_ref().unwrap()
1626 }
1627
1628 pub fn set_global<T: 'static>(&mut self, state: T) {
1629 self.update(|this| {
1630 let type_id = TypeId::of::<T>();
1631 this.cx.globals.insert(type_id, Box::new(state));
1632 this.notify_global(type_id);
1633 });
1634 }
1635
1636 pub fn update_default_global<T, F, U>(&mut self, update: F) -> U
1637 where
1638 T: 'static + Default,
1639 F: FnOnce(&mut T, &mut MutableAppContext) -> U,
1640 {
1641 self.update(|this| {
1642 let type_id = TypeId::of::<T>();
1643 let mut state = this
1644 .cx
1645 .globals
1646 .remove(&type_id)
1647 .unwrap_or_else(|| Box::new(T::default()));
1648 let result = update(state.downcast_mut().unwrap(), this);
1649 this.cx.globals.insert(type_id, state);
1650 this.notify_global(type_id);
1651 result
1652 })
1653 }
1654
1655 pub fn update_global<T, F, U>(&mut self, update: F) -> U
1656 where
1657 T: 'static,
1658 F: FnOnce(&mut T, &mut MutableAppContext) -> U,
1659 {
1660 self.update(|this| {
1661 let type_id = TypeId::of::<T>();
1662 let mut state = this
1663 .cx
1664 .globals
1665 .remove(&type_id)
1666 .expect("no global has been added for this type");
1667 let result = update(state.downcast_mut().unwrap(), this);
1668 this.cx.globals.insert(type_id, state);
1669 this.notify_global(type_id);
1670 result
1671 })
1672 }
1673
1674 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
1675 where
1676 T: Entity,
1677 F: FnOnce(&mut ModelContext<T>) -> T,
1678 {
1679 self.update(|this| {
1680 let model_id = post_inc(&mut this.next_entity_id);
1681 let handle = ModelHandle::new(model_id, &this.cx.ref_counts);
1682 let mut cx = ModelContext::new(this, model_id);
1683 let model = build_model(&mut cx);
1684 this.cx.models.insert(model_id, Box::new(model));
1685 handle
1686 })
1687 }
1688
1689 pub fn add_window<T, F>(
1690 &mut self,
1691 window_options: WindowOptions,
1692 build_root_view: F,
1693 ) -> (usize, ViewHandle<T>)
1694 where
1695 T: View,
1696 F: FnOnce(&mut ViewContext<T>) -> T,
1697 {
1698 self.update(|this| {
1699 let window_id = post_inc(&mut this.next_window_id);
1700 let root_view = this.add_view(window_id, build_root_view);
1701
1702 this.cx.windows.insert(
1703 window_id,
1704 Window {
1705 root_view: root_view.clone().into(),
1706 focused_view_id: Some(root_view.id()),
1707 is_active: true,
1708 invalidation: None,
1709 },
1710 );
1711 root_view.update(this, |view, cx| {
1712 view.on_focus(cx);
1713 });
1714 this.open_platform_window(window_id, window_options);
1715
1716 (window_id, root_view)
1717 })
1718 }
1719
1720 pub fn replace_root_view<T, F>(&mut self, window_id: usize, build_root_view: F) -> ViewHandle<T>
1721 where
1722 T: View,
1723 F: FnOnce(&mut ViewContext<T>) -> T,
1724 {
1725 self.update(|this| {
1726 let root_view = this.add_view(window_id, build_root_view);
1727 let window = this.cx.windows.get_mut(&window_id).unwrap();
1728 window.root_view = root_view.clone().into();
1729 window.focused_view_id = Some(root_view.id());
1730 root_view
1731 })
1732 }
1733
1734 pub fn remove_window(&mut self, window_id: usize) {
1735 self.cx.windows.remove(&window_id);
1736 self.presenters_and_platform_windows.remove(&window_id);
1737 self.flush_effects();
1738 }
1739
1740 fn open_platform_window(&mut self, window_id: usize, window_options: WindowOptions) {
1741 let mut window =
1742 self.cx
1743 .platform
1744 .open_window(window_id, window_options, self.foreground.clone());
1745 let presenter = Rc::new(RefCell::new(
1746 self.build_presenter(window_id, window.titlebar_height()),
1747 ));
1748
1749 {
1750 let mut app = self.upgrade();
1751 let presenter = Rc::downgrade(&presenter);
1752 window.on_event(Box::new(move |event| {
1753 app.update(|cx| {
1754 if let Some(presenter) = presenter.upgrade() {
1755 if let Event::KeyDown { keystroke, .. } = &event {
1756 if cx.dispatch_keystroke(
1757 window_id,
1758 presenter.borrow().dispatch_path(cx.as_ref()),
1759 keystroke,
1760 ) {
1761 return;
1762 }
1763 }
1764
1765 presenter.borrow_mut().dispatch_event(event, cx);
1766 }
1767 })
1768 }));
1769 }
1770
1771 {
1772 let mut app = self.upgrade();
1773 window.on_active_status_change(Box::new(move |is_active| {
1774 app.update(|cx| cx.window_changed_active_status(window_id, is_active))
1775 }));
1776 }
1777
1778 {
1779 let mut app = self.upgrade();
1780 window.on_resize(Box::new(move || {
1781 app.update(|cx| cx.window_was_resized(window_id))
1782 }));
1783 }
1784
1785 {
1786 let mut app = self.upgrade();
1787 window.on_close(Box::new(move || {
1788 app.update(|cx| cx.remove_window(window_id));
1789 }));
1790 }
1791
1792 let scene =
1793 presenter
1794 .borrow_mut()
1795 .build_scene(window.size(), window.scale_factor(), false, self);
1796 window.present_scene(scene);
1797 self.presenters_and_platform_windows
1798 .insert(window_id, (presenter.clone(), window));
1799 }
1800
1801 pub fn build_presenter(&mut self, window_id: usize, titlebar_height: f32) -> Presenter {
1802 Presenter::new(
1803 window_id,
1804 titlebar_height,
1805 self.cx.font_cache.clone(),
1806 TextLayoutCache::new(self.cx.platform.fonts()),
1807 self.assets.clone(),
1808 self,
1809 )
1810 }
1811
1812 pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
1813 where
1814 T: View,
1815 F: FnOnce(&mut ViewContext<T>) -> T,
1816 {
1817 self.add_option_view(window_id, |cx| Some(build_view(cx)))
1818 .unwrap()
1819 }
1820
1821 pub fn add_option_view<T, F>(
1822 &mut self,
1823 window_id: usize,
1824 build_view: F,
1825 ) -> Option<ViewHandle<T>>
1826 where
1827 T: View,
1828 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
1829 {
1830 self.update(|this| {
1831 let view_id = post_inc(&mut this.next_entity_id);
1832 let mut cx = ViewContext::new(this, window_id, view_id);
1833 let handle = if let Some(view) = build_view(&mut cx) {
1834 this.cx.views.insert((window_id, view_id), Box::new(view));
1835 if let Some(window) = this.cx.windows.get_mut(&window_id) {
1836 window
1837 .invalidation
1838 .get_or_insert_with(Default::default)
1839 .updated
1840 .insert(view_id);
1841 }
1842 Some(ViewHandle::new(window_id, view_id, &this.cx.ref_counts))
1843 } else {
1844 None
1845 };
1846 handle
1847 })
1848 }
1849
1850 fn remove_dropped_entities(&mut self) {
1851 loop {
1852 let (dropped_models, dropped_views, dropped_element_states) =
1853 self.cx.ref_counts.lock().take_dropped();
1854 if dropped_models.is_empty()
1855 && dropped_views.is_empty()
1856 && dropped_element_states.is_empty()
1857 {
1858 break;
1859 }
1860
1861 for model_id in dropped_models {
1862 self.subscriptions.lock().remove(&model_id);
1863 self.observations.lock().remove(&model_id);
1864 let mut model = self.cx.models.remove(&model_id).unwrap();
1865 model.release(self);
1866 self.pending_effects
1867 .push_back(Effect::ModelRelease { model_id, model });
1868 }
1869
1870 for (window_id, view_id) in dropped_views {
1871 self.subscriptions.lock().remove(&view_id);
1872 self.observations.lock().remove(&view_id);
1873 let mut view = self.cx.views.remove(&(window_id, view_id)).unwrap();
1874 view.release(self);
1875 let change_focus_to = self.cx.windows.get_mut(&window_id).and_then(|window| {
1876 window
1877 .invalidation
1878 .get_or_insert_with(Default::default)
1879 .removed
1880 .push(view_id);
1881 if window.focused_view_id == Some(view_id) {
1882 Some(window.root_view.id())
1883 } else {
1884 None
1885 }
1886 });
1887
1888 if let Some(view_id) = change_focus_to {
1889 self.handle_focus_effect(window_id, Some(view_id));
1890 }
1891
1892 self.pending_effects
1893 .push_back(Effect::ViewRelease { view_id, view });
1894 }
1895
1896 for key in dropped_element_states {
1897 self.cx.element_states.remove(&key);
1898 }
1899 }
1900 }
1901
1902 fn flush_effects(&mut self) {
1903 self.pending_flushes = self.pending_flushes.saturating_sub(1);
1904 let mut after_window_update_callbacks = Vec::new();
1905
1906 if !self.flushing_effects && self.pending_flushes == 0 {
1907 self.flushing_effects = true;
1908
1909 let mut refreshing = false;
1910 loop {
1911 if let Some(effect) = self.pending_effects.pop_front() {
1912 if let Some(pending_focus_index) = self.pending_focus_index.as_mut() {
1913 *pending_focus_index = pending_focus_index.saturating_sub(1);
1914 }
1915 match effect {
1916 Effect::Subscription {
1917 entity_id,
1918 subscription_id,
1919 callback,
1920 } => self.handle_subscription_effect(entity_id, subscription_id, callback),
1921 Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload),
1922 Effect::GlobalSubscription {
1923 type_id,
1924 subscription_id,
1925 callback,
1926 } => self.handle_global_subscription_effect(
1927 type_id,
1928 subscription_id,
1929 callback,
1930 ),
1931 Effect::GlobalEvent { payload } => self.emit_global_event(payload),
1932 Effect::Observation {
1933 entity_id,
1934 subscription_id,
1935 callback,
1936 } => self.handle_observation_effect(entity_id, subscription_id, callback),
1937 Effect::ModelNotification { model_id } => {
1938 self.handle_model_notification_effect(model_id)
1939 }
1940 Effect::ViewNotification { window_id, view_id } => {
1941 self.handle_view_notification_effect(window_id, view_id)
1942 }
1943 Effect::GlobalNotification { type_id } => {
1944 self.handle_global_notification_effect(type_id)
1945 }
1946 Effect::Deferred {
1947 callback,
1948 after_window_update,
1949 } => {
1950 if after_window_update {
1951 after_window_update_callbacks.push(callback);
1952 } else {
1953 callback(self)
1954 }
1955 }
1956 Effect::ModelRelease { model_id, model } => {
1957 self.handle_entity_release_effect(model_id, model.as_any())
1958 }
1959 Effect::ViewRelease { view_id, view } => {
1960 self.handle_entity_release_effect(view_id, view.as_any())
1961 }
1962 Effect::Focus { window_id, view_id } => {
1963 self.handle_focus_effect(window_id, view_id);
1964 }
1965 Effect::FocusObservation {
1966 view_id,
1967 subscription_id,
1968 callback,
1969 } => {
1970 self.handle_focus_observation_effect(view_id, subscription_id, callback)
1971 }
1972 Effect::ResizeWindow { window_id } => {
1973 if let Some(window) = self.cx.windows.get_mut(&window_id) {
1974 window
1975 .invalidation
1976 .get_or_insert(WindowInvalidation::default());
1977 }
1978 }
1979 Effect::ActivateWindow {
1980 window_id,
1981 is_active,
1982 } => self.handle_activation_effect(window_id, is_active),
1983 Effect::RefreshWindows => {
1984 refreshing = true;
1985 }
1986 Effect::ActionDispatchNotification { action_id } => {
1987 self.handle_action_dispatch_notification_effect(action_id)
1988 }
1989 }
1990 self.pending_notifications.clear();
1991 self.remove_dropped_entities();
1992 } else {
1993 self.remove_dropped_entities();
1994 if refreshing {
1995 self.perform_window_refresh();
1996 } else {
1997 self.update_windows();
1998 }
1999
2000 if self.pending_effects.is_empty() {
2001 for callback in after_window_update_callbacks.drain(..) {
2002 callback(self);
2003 }
2004
2005 if self.pending_effects.is_empty() {
2006 self.flushing_effects = false;
2007 self.pending_notifications.clear();
2008 self.pending_global_notifications.clear();
2009 break;
2010 }
2011 }
2012
2013 refreshing = false;
2014 }
2015 }
2016 }
2017 }
2018
2019 fn update_windows(&mut self) {
2020 let mut invalidations = HashMap::new();
2021 for (window_id, window) in &mut self.cx.windows {
2022 if let Some(invalidation) = window.invalidation.take() {
2023 invalidations.insert(*window_id, invalidation);
2024 }
2025 }
2026
2027 for (window_id, mut invalidation) in invalidations {
2028 if let Some((presenter, mut window)) =
2029 self.presenters_and_platform_windows.remove(&window_id)
2030 {
2031 {
2032 let mut presenter = presenter.borrow_mut();
2033 presenter.invalidate(&mut invalidation, self);
2034 let scene =
2035 presenter.build_scene(window.size(), window.scale_factor(), false, self);
2036 window.present_scene(scene);
2037 }
2038 self.presenters_and_platform_windows
2039 .insert(window_id, (presenter, window));
2040 }
2041 }
2042 }
2043
2044 fn window_was_resized(&mut self, window_id: usize) {
2045 self.pending_effects
2046 .push_back(Effect::ResizeWindow { window_id });
2047 }
2048
2049 fn window_changed_active_status(&mut self, window_id: usize, is_active: bool) {
2050 self.pending_effects.push_back(Effect::ActivateWindow {
2051 window_id,
2052 is_active,
2053 });
2054 }
2055
2056 pub fn refresh_windows(&mut self) {
2057 self.pending_effects.push_back(Effect::RefreshWindows);
2058 }
2059
2060 fn perform_window_refresh(&mut self) {
2061 let mut presenters = mem::take(&mut self.presenters_and_platform_windows);
2062 for (window_id, (presenter, window)) in &mut presenters {
2063 let mut invalidation = self
2064 .cx
2065 .windows
2066 .get_mut(&window_id)
2067 .unwrap()
2068 .invalidation
2069 .take();
2070 let mut presenter = presenter.borrow_mut();
2071 presenter.refresh(
2072 invalidation.as_mut().unwrap_or(&mut Default::default()),
2073 self,
2074 );
2075 let scene = presenter.build_scene(window.size(), window.scale_factor(), true, self);
2076 window.present_scene(scene);
2077 }
2078 self.presenters_and_platform_windows = presenters;
2079 }
2080
2081 fn handle_subscription_effect(
2082 &mut self,
2083 entity_id: usize,
2084 subscription_id: usize,
2085 callback: SubscriptionCallback,
2086 ) {
2087 match self
2088 .subscriptions
2089 .lock()
2090 .entry(entity_id)
2091 .or_default()
2092 .entry(subscription_id)
2093 {
2094 btree_map::Entry::Vacant(entry) => {
2095 entry.insert(Some(callback));
2096 }
2097 // Subscription was dropped before effect was processed
2098 btree_map::Entry::Occupied(entry) => {
2099 debug_assert!(entry.get().is_none());
2100 entry.remove();
2101 }
2102 }
2103 }
2104
2105 fn emit_event(&mut self, entity_id: usize, payload: Box<dyn Any>) {
2106 let callbacks = self.subscriptions.lock().remove(&entity_id);
2107 if let Some(callbacks) = callbacks {
2108 for (id, callback) in callbacks {
2109 if let Some(mut callback) = callback {
2110 let alive = callback(payload.as_ref(), self);
2111 if alive {
2112 match self
2113 .subscriptions
2114 .lock()
2115 .entry(entity_id)
2116 .or_default()
2117 .entry(id)
2118 {
2119 btree_map::Entry::Vacant(entry) => {
2120 entry.insert(Some(callback));
2121 }
2122 btree_map::Entry::Occupied(entry) => {
2123 entry.remove();
2124 }
2125 }
2126 }
2127 }
2128 }
2129 }
2130 }
2131
2132 fn handle_global_subscription_effect(
2133 &mut self,
2134 type_id: TypeId,
2135 subscription_id: usize,
2136 callback: GlobalSubscriptionCallback,
2137 ) {
2138 match self
2139 .global_subscriptions
2140 .lock()
2141 .entry(type_id)
2142 .or_default()
2143 .entry(subscription_id)
2144 {
2145 btree_map::Entry::Vacant(entry) => {
2146 entry.insert(Some(callback));
2147 }
2148 // Subscription was dropped before effect was processed
2149 btree_map::Entry::Occupied(entry) => {
2150 debug_assert!(entry.get().is_none());
2151 entry.remove();
2152 }
2153 }
2154 }
2155
2156 fn emit_global_event(&mut self, payload: Box<dyn Any>) {
2157 let type_id = (&*payload).type_id();
2158 let callbacks = self.global_subscriptions.lock().remove(&type_id);
2159 if let Some(callbacks) = callbacks {
2160 for (id, callback) in callbacks {
2161 if let Some(mut callback) = callback {
2162 callback(payload.as_ref(), self);
2163 match self
2164 .global_subscriptions
2165 .lock()
2166 .entry(type_id)
2167 .or_default()
2168 .entry(id)
2169 {
2170 btree_map::Entry::Vacant(entry) => {
2171 entry.insert(Some(callback));
2172 }
2173 btree_map::Entry::Occupied(entry) => {
2174 entry.remove();
2175 }
2176 }
2177 }
2178 }
2179 }
2180 }
2181
2182 fn handle_observation_effect(
2183 &mut self,
2184 entity_id: usize,
2185 subscription_id: usize,
2186 callback: ObservationCallback,
2187 ) {
2188 match self
2189 .observations
2190 .lock()
2191 .entry(entity_id)
2192 .or_default()
2193 .entry(subscription_id)
2194 {
2195 btree_map::Entry::Vacant(entry) => {
2196 entry.insert(Some(callback));
2197 }
2198 // Observation was dropped before effect was processed
2199 btree_map::Entry::Occupied(entry) => {
2200 debug_assert!(entry.get().is_none());
2201 entry.remove();
2202 }
2203 }
2204 }
2205
2206 fn handle_focus_observation_effect(
2207 &mut self,
2208 view_id: usize,
2209 subscription_id: usize,
2210 callback: FocusObservationCallback,
2211 ) {
2212 match self
2213 .focus_observations
2214 .lock()
2215 .entry(view_id)
2216 .or_default()
2217 .entry(subscription_id)
2218 {
2219 btree_map::Entry::Vacant(entry) => {
2220 entry.insert(Some(callback));
2221 }
2222 // Observation was dropped before effect was processed
2223 btree_map::Entry::Occupied(entry) => {
2224 debug_assert!(entry.get().is_none());
2225 entry.remove();
2226 }
2227 }
2228 }
2229
2230 fn handle_model_notification_effect(&mut self, observed_id: usize) {
2231 let callbacks = self.observations.lock().remove(&observed_id);
2232 if let Some(callbacks) = callbacks {
2233 if self.cx.models.contains_key(&observed_id) {
2234 for (id, callback) in callbacks {
2235 if let Some(mut callback) = callback {
2236 let alive = callback(self);
2237 if alive {
2238 match self
2239 .observations
2240 .lock()
2241 .entry(observed_id)
2242 .or_default()
2243 .entry(id)
2244 {
2245 btree_map::Entry::Vacant(entry) => {
2246 entry.insert(Some(callback));
2247 }
2248 btree_map::Entry::Occupied(entry) => {
2249 entry.remove();
2250 }
2251 }
2252 }
2253 }
2254 }
2255 }
2256 }
2257 }
2258
2259 fn handle_view_notification_effect(
2260 &mut self,
2261 observed_window_id: usize,
2262 observed_view_id: usize,
2263 ) {
2264 if let Some(window) = self.cx.windows.get_mut(&observed_window_id) {
2265 window
2266 .invalidation
2267 .get_or_insert_with(Default::default)
2268 .updated
2269 .insert(observed_view_id);
2270 }
2271
2272 let callbacks = self.observations.lock().remove(&observed_view_id);
2273 if let Some(callbacks) = callbacks {
2274 if self
2275 .cx
2276 .views
2277 .contains_key(&(observed_window_id, observed_view_id))
2278 {
2279 for (id, callback) in callbacks {
2280 if let Some(mut callback) = callback {
2281 let alive = callback(self);
2282 if alive {
2283 match self
2284 .observations
2285 .lock()
2286 .entry(observed_view_id)
2287 .or_default()
2288 .entry(id)
2289 {
2290 btree_map::Entry::Vacant(entry) => {
2291 entry.insert(Some(callback));
2292 }
2293 btree_map::Entry::Occupied(entry) => {
2294 entry.remove();
2295 }
2296 }
2297 }
2298 }
2299 }
2300 }
2301 }
2302 }
2303
2304 fn handle_global_notification_effect(&mut self, observed_type_id: TypeId) {
2305 let callbacks = self.global_observations.lock().remove(&observed_type_id);
2306 if let Some(callbacks) = callbacks {
2307 if let Some(global) = self.cx.globals.remove(&observed_type_id) {
2308 for (id, callback) in callbacks {
2309 if let Some(mut callback) = callback {
2310 callback(global.as_ref(), self);
2311 match self
2312 .global_observations
2313 .lock()
2314 .entry(observed_type_id)
2315 .or_default()
2316 .entry(id)
2317 {
2318 collections::btree_map::Entry::Vacant(entry) => {
2319 entry.insert(Some(callback));
2320 }
2321 collections::btree_map::Entry::Occupied(entry) => {
2322 entry.remove();
2323 }
2324 }
2325 }
2326 }
2327 self.cx.globals.insert(observed_type_id, global);
2328 }
2329 }
2330 }
2331
2332 fn handle_entity_release_effect(&mut self, entity_id: usize, entity: &dyn Any) {
2333 let callbacks = self.release_observations.lock().remove(&entity_id);
2334 if let Some(callbacks) = callbacks {
2335 for (_, callback) in callbacks {
2336 callback(entity, self);
2337 }
2338 }
2339 }
2340
2341 fn handle_activation_effect(&mut self, window_id: usize, active: bool) {
2342 if self
2343 .cx
2344 .windows
2345 .get(&window_id)
2346 .map(|w| w.is_active)
2347 .map_or(false, |cur_active| cur_active == active)
2348 {
2349 return;
2350 }
2351
2352 self.update(|this| {
2353 let window = this.cx.windows.get_mut(&window_id)?;
2354 window.is_active = active;
2355 let view_id = window.focused_view_id?;
2356 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
2357 if active {
2358 view.on_focus(this, window_id, view_id);
2359 } else {
2360 view.on_blur(this, window_id, view_id);
2361 }
2362 this.cx.views.insert((window_id, view_id), view);
2363 }
2364
2365 Some(())
2366 });
2367 }
2368
2369 fn handle_focus_effect(&mut self, window_id: usize, focused_id: Option<usize>) {
2370 self.pending_focus_index.take();
2371
2372 if self
2373 .cx
2374 .windows
2375 .get(&window_id)
2376 .map(|w| w.focused_view_id)
2377 .map_or(false, |cur_focused| cur_focused == focused_id)
2378 {
2379 return;
2380 }
2381
2382 self.update(|this| {
2383 let blurred_id = this.cx.windows.get_mut(&window_id).and_then(|window| {
2384 let blurred_id = window.focused_view_id;
2385 window.focused_view_id = focused_id;
2386 blurred_id
2387 });
2388
2389 if let Some(blurred_id) = blurred_id {
2390 if let Some(mut blurred_view) = this.cx.views.remove(&(window_id, blurred_id)) {
2391 blurred_view.on_blur(this, window_id, blurred_id);
2392 this.cx.views.insert((window_id, blurred_id), blurred_view);
2393 }
2394 }
2395
2396 if let Some(focused_id) = focused_id {
2397 if let Some(mut focused_view) = this.cx.views.remove(&(window_id, focused_id)) {
2398 focused_view.on_focus(this, window_id, focused_id);
2399 this.cx.views.insert((window_id, focused_id), focused_view);
2400
2401 let callbacks = this.focus_observations.lock().remove(&focused_id);
2402 if let Some(callbacks) = callbacks {
2403 for (id, callback) in callbacks {
2404 if let Some(mut callback) = callback {
2405 let alive = callback(this);
2406 if alive {
2407 match this
2408 .focus_observations
2409 .lock()
2410 .entry(focused_id)
2411 .or_default()
2412 .entry(id)
2413 {
2414 btree_map::Entry::Vacant(entry) => {
2415 entry.insert(Some(callback));
2416 }
2417 btree_map::Entry::Occupied(entry) => {
2418 entry.remove();
2419 }
2420 }
2421 }
2422 }
2423 }
2424 }
2425 }
2426 }
2427 })
2428 }
2429
2430 fn handle_action_dispatch_notification_effect(&mut self, action_id: TypeId) {
2431 let mut callbacks = mem::take(&mut *self.action_dispatch_observations.lock());
2432 for (_, callback) in &mut callbacks {
2433 callback(action_id, self);
2434 }
2435 self.action_dispatch_observations.lock().extend(callbacks);
2436 }
2437
2438 pub fn focus(&mut self, window_id: usize, view_id: Option<usize>) {
2439 if let Some(pending_focus_index) = self.pending_focus_index {
2440 self.pending_effects.remove(pending_focus_index);
2441 }
2442 self.pending_focus_index = Some(self.pending_effects.len());
2443 self.pending_effects
2444 .push_back(Effect::Focus { window_id, view_id });
2445 }
2446
2447 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
2448 where
2449 F: FnOnce(AsyncAppContext) -> Fut,
2450 Fut: 'static + Future<Output = T>,
2451 T: 'static,
2452 {
2453 let future = f(self.to_async());
2454 let cx = self.to_async();
2455 self.foreground.spawn(async move {
2456 let result = future.await;
2457 cx.0.borrow_mut().flush_effects();
2458 result
2459 })
2460 }
2461
2462 pub fn to_async(&self) -> AsyncAppContext {
2463 AsyncAppContext(self.weak_self.as_ref().unwrap().upgrade().unwrap())
2464 }
2465
2466 pub fn write_to_clipboard(&self, item: ClipboardItem) {
2467 self.cx.platform.write_to_clipboard(item);
2468 }
2469
2470 pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {
2471 self.cx.platform.read_from_clipboard()
2472 }
2473
2474 #[cfg(any(test, feature = "test-support"))]
2475 pub fn leak_detector(&self) -> Arc<Mutex<LeakDetector>> {
2476 self.cx.ref_counts.lock().leak_detector.clone()
2477 }
2478}
2479
2480impl ReadModel for MutableAppContext {
2481 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2482 if let Some(model) = self.cx.models.get(&handle.model_id) {
2483 model
2484 .as_any()
2485 .downcast_ref()
2486 .expect("downcast is type safe")
2487 } else {
2488 panic!("circular model reference");
2489 }
2490 }
2491}
2492
2493impl UpdateModel for MutableAppContext {
2494 fn update_model<T: Entity, V>(
2495 &mut self,
2496 handle: &ModelHandle<T>,
2497 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
2498 ) -> V {
2499 if let Some(mut model) = self.cx.models.remove(&handle.model_id) {
2500 self.update(|this| {
2501 let mut cx = ModelContext::new(this, handle.model_id);
2502 let result = update(
2503 model
2504 .as_any_mut()
2505 .downcast_mut()
2506 .expect("downcast is type safe"),
2507 &mut cx,
2508 );
2509 this.cx.models.insert(handle.model_id, model);
2510 result
2511 })
2512 } else {
2513 panic!("circular model update");
2514 }
2515 }
2516}
2517
2518impl UpgradeModelHandle for MutableAppContext {
2519 fn upgrade_model_handle<T: Entity>(
2520 &self,
2521 handle: &WeakModelHandle<T>,
2522 ) -> Option<ModelHandle<T>> {
2523 self.cx.upgrade_model_handle(handle)
2524 }
2525
2526 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
2527 self.cx.model_handle_is_upgradable(handle)
2528 }
2529
2530 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
2531 self.cx.upgrade_any_model_handle(handle)
2532 }
2533}
2534
2535impl UpgradeViewHandle for MutableAppContext {
2536 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
2537 self.cx.upgrade_view_handle(handle)
2538 }
2539
2540 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
2541 self.cx.upgrade_any_view_handle(handle)
2542 }
2543}
2544
2545impl ReadView for MutableAppContext {
2546 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2547 if let Some(view) = self.cx.views.get(&(handle.window_id, handle.view_id)) {
2548 view.as_any().downcast_ref().expect("downcast is type safe")
2549 } else {
2550 panic!("circular view reference");
2551 }
2552 }
2553}
2554
2555impl UpdateView for MutableAppContext {
2556 fn update_view<T, S>(
2557 &mut self,
2558 handle: &ViewHandle<T>,
2559 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
2560 ) -> S
2561 where
2562 T: View,
2563 {
2564 self.update(|this| {
2565 let mut view = this
2566 .cx
2567 .views
2568 .remove(&(handle.window_id, handle.view_id))
2569 .expect("circular view update");
2570
2571 let mut cx = ViewContext::new(this, handle.window_id, handle.view_id);
2572 let result = update(
2573 view.as_any_mut()
2574 .downcast_mut()
2575 .expect("downcast is type safe"),
2576 &mut cx,
2577 );
2578 this.cx
2579 .views
2580 .insert((handle.window_id, handle.view_id), view);
2581 result
2582 })
2583 }
2584}
2585
2586impl AsRef<AppContext> for MutableAppContext {
2587 fn as_ref(&self) -> &AppContext {
2588 &self.cx
2589 }
2590}
2591
2592impl Deref for MutableAppContext {
2593 type Target = AppContext;
2594
2595 fn deref(&self) -> &Self::Target {
2596 &self.cx
2597 }
2598}
2599
2600pub struct AppContext {
2601 models: HashMap<usize, Box<dyn AnyModel>>,
2602 views: HashMap<(usize, usize), Box<dyn AnyView>>,
2603 windows: HashMap<usize, Window>,
2604 globals: HashMap<TypeId, Box<dyn Any>>,
2605 element_states: HashMap<ElementStateId, Box<dyn Any>>,
2606 background: Arc<executor::Background>,
2607 ref_counts: Arc<Mutex<RefCounts>>,
2608 font_cache: Arc<FontCache>,
2609 platform: Arc<dyn Platform>,
2610}
2611
2612impl AppContext {
2613 pub(crate) fn root_view(&self, window_id: usize) -> Option<AnyViewHandle> {
2614 self.windows
2615 .get(&window_id)
2616 .map(|window| window.root_view.clone())
2617 }
2618
2619 pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
2620 self.windows
2621 .get(&window_id)
2622 .map(|window| window.root_view.id())
2623 }
2624
2625 pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
2626 self.windows
2627 .get(&window_id)
2628 .and_then(|window| window.focused_view_id)
2629 }
2630
2631 pub fn background(&self) -> &Arc<executor::Background> {
2632 &self.background
2633 }
2634
2635 pub fn font_cache(&self) -> &Arc<FontCache> {
2636 &self.font_cache
2637 }
2638
2639 pub fn platform(&self) -> &Arc<dyn Platform> {
2640 &self.platform
2641 }
2642
2643 pub fn has_global<T: 'static>(&self) -> bool {
2644 self.globals.contains_key(&TypeId::of::<T>())
2645 }
2646
2647 pub fn global<T: 'static>(&self) -> &T {
2648 if let Some(global) = self.globals.get(&TypeId::of::<T>()) {
2649 global.downcast_ref().unwrap()
2650 } else {
2651 panic!("no global has been added for {}", type_name::<T>());
2652 }
2653 }
2654}
2655
2656impl ReadModel for AppContext {
2657 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2658 if let Some(model) = self.models.get(&handle.model_id) {
2659 model
2660 .as_any()
2661 .downcast_ref()
2662 .expect("downcast should be type safe")
2663 } else {
2664 panic!("circular model reference");
2665 }
2666 }
2667}
2668
2669impl UpgradeModelHandle for AppContext {
2670 fn upgrade_model_handle<T: Entity>(
2671 &self,
2672 handle: &WeakModelHandle<T>,
2673 ) -> Option<ModelHandle<T>> {
2674 if self.models.contains_key(&handle.model_id) {
2675 Some(ModelHandle::new(handle.model_id, &self.ref_counts))
2676 } else {
2677 None
2678 }
2679 }
2680
2681 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
2682 self.models.contains_key(&handle.model_id)
2683 }
2684
2685 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
2686 if self.models.contains_key(&handle.model_id) {
2687 Some(AnyModelHandle::new(
2688 handle.model_id,
2689 handle.model_type,
2690 self.ref_counts.clone(),
2691 ))
2692 } else {
2693 None
2694 }
2695 }
2696}
2697
2698impl UpgradeViewHandle for AppContext {
2699 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
2700 if self.ref_counts.lock().is_entity_alive(handle.view_id) {
2701 Some(ViewHandle::new(
2702 handle.window_id,
2703 handle.view_id,
2704 &self.ref_counts,
2705 ))
2706 } else {
2707 None
2708 }
2709 }
2710
2711 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
2712 if self.ref_counts.lock().is_entity_alive(handle.view_id) {
2713 Some(AnyViewHandle::new(
2714 handle.window_id,
2715 handle.view_id,
2716 handle.view_type,
2717 self.ref_counts.clone(),
2718 ))
2719 } else {
2720 None
2721 }
2722 }
2723}
2724
2725impl ReadView for AppContext {
2726 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2727 if let Some(view) = self.views.get(&(handle.window_id, handle.view_id)) {
2728 view.as_any()
2729 .downcast_ref()
2730 .expect("downcast should be type safe")
2731 } else {
2732 panic!("circular view reference");
2733 }
2734 }
2735}
2736
2737struct Window {
2738 root_view: AnyViewHandle,
2739 focused_view_id: Option<usize>,
2740 is_active: bool,
2741 invalidation: Option<WindowInvalidation>,
2742}
2743
2744#[derive(Default, Clone)]
2745pub struct WindowInvalidation {
2746 pub updated: HashSet<usize>,
2747 pub removed: Vec<usize>,
2748}
2749
2750pub enum Effect {
2751 Subscription {
2752 entity_id: usize,
2753 subscription_id: usize,
2754 callback: SubscriptionCallback,
2755 },
2756 Event {
2757 entity_id: usize,
2758 payload: Box<dyn Any>,
2759 },
2760 GlobalSubscription {
2761 type_id: TypeId,
2762 subscription_id: usize,
2763 callback: GlobalSubscriptionCallback,
2764 },
2765 GlobalEvent {
2766 payload: Box<dyn Any>,
2767 },
2768 Observation {
2769 entity_id: usize,
2770 subscription_id: usize,
2771 callback: ObservationCallback,
2772 },
2773 ModelNotification {
2774 model_id: usize,
2775 },
2776 ViewNotification {
2777 window_id: usize,
2778 view_id: usize,
2779 },
2780 Deferred {
2781 callback: Box<dyn FnOnce(&mut MutableAppContext)>,
2782 after_window_update: bool,
2783 },
2784 GlobalNotification {
2785 type_id: TypeId,
2786 },
2787 ModelRelease {
2788 model_id: usize,
2789 model: Box<dyn AnyModel>,
2790 },
2791 ViewRelease {
2792 view_id: usize,
2793 view: Box<dyn AnyView>,
2794 },
2795 Focus {
2796 window_id: usize,
2797 view_id: Option<usize>,
2798 },
2799 FocusObservation {
2800 view_id: usize,
2801 subscription_id: usize,
2802 callback: FocusObservationCallback,
2803 },
2804 ResizeWindow {
2805 window_id: usize,
2806 },
2807 ActivateWindow {
2808 window_id: usize,
2809 is_active: bool,
2810 },
2811 RefreshWindows,
2812 ActionDispatchNotification {
2813 action_id: TypeId,
2814 },
2815}
2816
2817impl Debug for Effect {
2818 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2819 match self {
2820 Effect::Subscription {
2821 entity_id,
2822 subscription_id,
2823 ..
2824 } => f
2825 .debug_struct("Effect::Subscribe")
2826 .field("entity_id", entity_id)
2827 .field("subscription_id", subscription_id)
2828 .finish(),
2829 Effect::Event { entity_id, .. } => f
2830 .debug_struct("Effect::Event")
2831 .field("entity_id", entity_id)
2832 .finish(),
2833 Effect::GlobalSubscription {
2834 type_id,
2835 subscription_id,
2836 ..
2837 } => f
2838 .debug_struct("Effect::Subscribe")
2839 .field("type_id", type_id)
2840 .field("subscription_id", subscription_id)
2841 .finish(),
2842 Effect::GlobalEvent { payload, .. } => f
2843 .debug_struct("Effect::GlobalEvent")
2844 .field("type_id", &(&*payload).type_id())
2845 .finish(),
2846 Effect::Observation {
2847 entity_id,
2848 subscription_id,
2849 ..
2850 } => f
2851 .debug_struct("Effect::Observation")
2852 .field("entity_id", entity_id)
2853 .field("subscription_id", subscription_id)
2854 .finish(),
2855 Effect::ModelNotification { model_id } => f
2856 .debug_struct("Effect::ModelNotification")
2857 .field("model_id", model_id)
2858 .finish(),
2859 Effect::ViewNotification { window_id, view_id } => f
2860 .debug_struct("Effect::ViewNotification")
2861 .field("window_id", window_id)
2862 .field("view_id", view_id)
2863 .finish(),
2864 Effect::GlobalNotification { type_id } => f
2865 .debug_struct("Effect::GlobalNotification")
2866 .field("type_id", type_id)
2867 .finish(),
2868 Effect::Deferred { .. } => f.debug_struct("Effect::Deferred").finish(),
2869 Effect::ModelRelease { model_id, .. } => f
2870 .debug_struct("Effect::ModelRelease")
2871 .field("model_id", model_id)
2872 .finish(),
2873 Effect::ViewRelease { view_id, .. } => f
2874 .debug_struct("Effect::ViewRelease")
2875 .field("view_id", view_id)
2876 .finish(),
2877 Effect::Focus { window_id, view_id } => f
2878 .debug_struct("Effect::Focus")
2879 .field("window_id", window_id)
2880 .field("view_id", view_id)
2881 .finish(),
2882 Effect::FocusObservation {
2883 view_id,
2884 subscription_id,
2885 ..
2886 } => f
2887 .debug_struct("Effect::FocusObservation")
2888 .field("view_id", view_id)
2889 .field("subscription_id", subscription_id)
2890 .finish(),
2891 Effect::ActionDispatchNotification { action_id, .. } => f
2892 .debug_struct("Effect::ActionDispatchNotification")
2893 .field("action_id", action_id)
2894 .finish(),
2895 Effect::ResizeWindow { window_id } => f
2896 .debug_struct("Effect::RefreshWindow")
2897 .field("window_id", window_id)
2898 .finish(),
2899 Effect::ActivateWindow {
2900 window_id,
2901 is_active,
2902 } => f
2903 .debug_struct("Effect::ActivateWindow")
2904 .field("window_id", window_id)
2905 .field("is_active", is_active)
2906 .finish(),
2907 Effect::RefreshWindows => f.debug_struct("Effect::FullViewRefresh").finish(),
2908 }
2909 }
2910}
2911
2912pub trait AnyModel {
2913 fn as_any(&self) -> &dyn Any;
2914 fn as_any_mut(&mut self) -> &mut dyn Any;
2915 fn release(&mut self, cx: &mut MutableAppContext);
2916 fn app_will_quit(
2917 &mut self,
2918 cx: &mut MutableAppContext,
2919 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
2920}
2921
2922impl<T> AnyModel for T
2923where
2924 T: Entity,
2925{
2926 fn as_any(&self) -> &dyn Any {
2927 self
2928 }
2929
2930 fn as_any_mut(&mut self) -> &mut dyn Any {
2931 self
2932 }
2933
2934 fn release(&mut self, cx: &mut MutableAppContext) {
2935 self.release(cx);
2936 }
2937
2938 fn app_will_quit(
2939 &mut self,
2940 cx: &mut MutableAppContext,
2941 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
2942 self.app_will_quit(cx)
2943 }
2944}
2945
2946pub trait AnyView {
2947 fn as_any(&self) -> &dyn Any;
2948 fn as_any_mut(&mut self) -> &mut dyn Any;
2949 fn release(&mut self, cx: &mut MutableAppContext);
2950 fn app_will_quit(
2951 &mut self,
2952 cx: &mut MutableAppContext,
2953 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
2954 fn ui_name(&self) -> &'static str;
2955 fn render<'a>(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox;
2956 fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize);
2957 fn on_blur(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize);
2958 fn keymap_context(&self, cx: &AppContext) -> keymap::Context;
2959 fn debug_json(&self, cx: &AppContext) -> serde_json::Value;
2960}
2961
2962impl<T> AnyView for T
2963where
2964 T: View,
2965{
2966 fn as_any(&self) -> &dyn Any {
2967 self
2968 }
2969
2970 fn as_any_mut(&mut self) -> &mut dyn Any {
2971 self
2972 }
2973
2974 fn release(&mut self, cx: &mut MutableAppContext) {
2975 self.release(cx);
2976 }
2977
2978 fn app_will_quit(
2979 &mut self,
2980 cx: &mut MutableAppContext,
2981 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
2982 self.app_will_quit(cx)
2983 }
2984
2985 fn ui_name(&self) -> &'static str {
2986 T::ui_name()
2987 }
2988
2989 fn render<'a>(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox {
2990 View::render(self, &mut RenderContext::new(params, cx))
2991 }
2992
2993 fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) {
2994 let mut cx = ViewContext::new(cx, window_id, view_id);
2995 View::on_focus(self, &mut cx);
2996 }
2997
2998 fn on_blur(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) {
2999 let mut cx = ViewContext::new(cx, window_id, view_id);
3000 View::on_blur(self, &mut cx);
3001 }
3002
3003 fn keymap_context(&self, cx: &AppContext) -> keymap::Context {
3004 View::keymap_context(self, cx)
3005 }
3006
3007 fn debug_json(&self, cx: &AppContext) -> serde_json::Value {
3008 View::debug_json(self, cx)
3009 }
3010}
3011
3012pub struct ModelContext<'a, T: ?Sized> {
3013 app: &'a mut MutableAppContext,
3014 model_id: usize,
3015 model_type: PhantomData<T>,
3016 halt_stream: bool,
3017}
3018
3019impl<'a, T: Entity> ModelContext<'a, T> {
3020 fn new(app: &'a mut MutableAppContext, model_id: usize) -> Self {
3021 Self {
3022 app,
3023 model_id,
3024 model_type: PhantomData,
3025 halt_stream: false,
3026 }
3027 }
3028
3029 pub fn background(&self) -> &Arc<executor::Background> {
3030 &self.app.cx.background
3031 }
3032
3033 pub fn halt_stream(&mut self) {
3034 self.halt_stream = true;
3035 }
3036
3037 pub fn model_id(&self) -> usize {
3038 self.model_id
3039 }
3040
3041 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
3042 where
3043 S: Entity,
3044 F: FnOnce(&mut ModelContext<S>) -> S,
3045 {
3046 self.app.add_model(build_model)
3047 }
3048
3049 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ModelContext<T>)) {
3050 let handle = self.handle();
3051 self.app.defer(move |cx| {
3052 handle.update(cx, |model, cx| {
3053 callback(model, cx);
3054 })
3055 })
3056 }
3057
3058 pub fn emit(&mut self, payload: T::Event) {
3059 self.app.pending_effects.push_back(Effect::Event {
3060 entity_id: self.model_id,
3061 payload: Box::new(payload),
3062 });
3063 }
3064
3065 pub fn notify(&mut self) {
3066 self.app.notify_model(self.model_id);
3067 }
3068
3069 pub fn subscribe<S: Entity, F>(
3070 &mut self,
3071 handle: &ModelHandle<S>,
3072 mut callback: F,
3073 ) -> Subscription
3074 where
3075 S::Event: 'static,
3076 F: 'static + FnMut(&mut T, ModelHandle<S>, &S::Event, &mut ModelContext<T>),
3077 {
3078 let subscriber = self.weak_handle();
3079 self.app
3080 .subscribe_internal(handle, move |emitter, event, cx| {
3081 if let Some(subscriber) = subscriber.upgrade(cx) {
3082 subscriber.update(cx, |subscriber, cx| {
3083 callback(subscriber, emitter, event, cx);
3084 });
3085 true
3086 } else {
3087 false
3088 }
3089 })
3090 }
3091
3092 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F) -> Subscription
3093 where
3094 S: Entity,
3095 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ModelContext<T>),
3096 {
3097 let observer = self.weak_handle();
3098 self.app.observe_internal(handle, move |observed, cx| {
3099 if let Some(observer) = observer.upgrade(cx) {
3100 observer.update(cx, |observer, cx| {
3101 callback(observer, observed, cx);
3102 });
3103 true
3104 } else {
3105 false
3106 }
3107 })
3108 }
3109
3110 pub fn observe_release<S, F>(
3111 &mut self,
3112 handle: &ModelHandle<S>,
3113 mut callback: F,
3114 ) -> Subscription
3115 where
3116 S: Entity,
3117 F: 'static + FnMut(&mut T, &S, &mut ModelContext<T>),
3118 {
3119 let observer = self.weak_handle();
3120 self.app.observe_release(handle, move |released, cx| {
3121 if let Some(observer) = observer.upgrade(cx) {
3122 observer.update(cx, |observer, cx| {
3123 callback(observer, released, cx);
3124 });
3125 }
3126 })
3127 }
3128
3129 pub fn handle(&self) -> ModelHandle<T> {
3130 ModelHandle::new(self.model_id, &self.app.cx.ref_counts)
3131 }
3132
3133 pub fn weak_handle(&self) -> WeakModelHandle<T> {
3134 WeakModelHandle::new(self.model_id)
3135 }
3136
3137 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
3138 where
3139 F: FnOnce(ModelHandle<T>, AsyncAppContext) -> Fut,
3140 Fut: 'static + Future<Output = S>,
3141 S: 'static,
3142 {
3143 let handle = self.handle();
3144 self.app.spawn(|cx| f(handle, cx))
3145 }
3146
3147 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
3148 where
3149 F: FnOnce(WeakModelHandle<T>, AsyncAppContext) -> Fut,
3150 Fut: 'static + Future<Output = S>,
3151 S: 'static,
3152 {
3153 let handle = self.weak_handle();
3154 self.app.spawn(|cx| f(handle, cx))
3155 }
3156}
3157
3158impl<M> AsRef<AppContext> for ModelContext<'_, M> {
3159 fn as_ref(&self) -> &AppContext {
3160 &self.app.cx
3161 }
3162}
3163
3164impl<M> AsMut<MutableAppContext> for ModelContext<'_, M> {
3165 fn as_mut(&mut self) -> &mut MutableAppContext {
3166 self.app
3167 }
3168}
3169
3170impl<M> ReadModel for ModelContext<'_, M> {
3171 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
3172 self.app.read_model(handle)
3173 }
3174}
3175
3176impl<M> UpdateModel for ModelContext<'_, M> {
3177 fn update_model<T: Entity, V>(
3178 &mut self,
3179 handle: &ModelHandle<T>,
3180 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
3181 ) -> V {
3182 self.app.update_model(handle, update)
3183 }
3184}
3185
3186impl<M> UpgradeModelHandle for ModelContext<'_, M> {
3187 fn upgrade_model_handle<T: Entity>(
3188 &self,
3189 handle: &WeakModelHandle<T>,
3190 ) -> Option<ModelHandle<T>> {
3191 self.cx.upgrade_model_handle(handle)
3192 }
3193
3194 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
3195 self.cx.model_handle_is_upgradable(handle)
3196 }
3197
3198 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
3199 self.cx.upgrade_any_model_handle(handle)
3200 }
3201}
3202
3203impl<M> Deref for ModelContext<'_, M> {
3204 type Target = MutableAppContext;
3205
3206 fn deref(&self) -> &Self::Target {
3207 &self.app
3208 }
3209}
3210
3211impl<M> DerefMut for ModelContext<'_, M> {
3212 fn deref_mut(&mut self) -> &mut Self::Target {
3213 &mut self.app
3214 }
3215}
3216
3217pub struct ViewContext<'a, T: ?Sized> {
3218 app: &'a mut MutableAppContext,
3219 window_id: usize,
3220 view_id: usize,
3221 view_type: PhantomData<T>,
3222}
3223
3224impl<'a, T: View> ViewContext<'a, T> {
3225 fn new(app: &'a mut MutableAppContext, window_id: usize, view_id: usize) -> Self {
3226 Self {
3227 app,
3228 window_id,
3229 view_id,
3230 view_type: PhantomData,
3231 }
3232 }
3233
3234 pub fn handle(&self) -> ViewHandle<T> {
3235 ViewHandle::new(self.window_id, self.view_id, &self.app.cx.ref_counts)
3236 }
3237
3238 pub fn weak_handle(&self) -> WeakViewHandle<T> {
3239 WeakViewHandle::new(self.window_id, self.view_id)
3240 }
3241
3242 pub fn window_id(&self) -> usize {
3243 self.window_id
3244 }
3245
3246 pub fn view_id(&self) -> usize {
3247 self.view_id
3248 }
3249
3250 pub fn foreground(&self) -> &Rc<executor::Foreground> {
3251 self.app.foreground()
3252 }
3253
3254 pub fn background_executor(&self) -> &Arc<executor::Background> {
3255 &self.app.cx.background
3256 }
3257
3258 pub fn platform(&self) -> Arc<dyn Platform> {
3259 self.app.platform()
3260 }
3261
3262 pub fn prompt(
3263 &self,
3264 level: PromptLevel,
3265 msg: &str,
3266 answers: &[&str],
3267 ) -> oneshot::Receiver<usize> {
3268 self.app.prompt(self.window_id, level, msg, answers)
3269 }
3270
3271 pub fn prompt_for_paths(
3272 &self,
3273 options: PathPromptOptions,
3274 ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
3275 self.app.prompt_for_paths(options)
3276 }
3277
3278 pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
3279 self.app.prompt_for_new_path(directory)
3280 }
3281
3282 pub fn debug_elements(&self) -> crate::json::Value {
3283 self.app.debug_elements(self.window_id).unwrap()
3284 }
3285
3286 pub fn focus<S>(&mut self, handle: S)
3287 where
3288 S: Into<AnyViewHandle>,
3289 {
3290 let handle = handle.into();
3291 self.app.focus(handle.window_id, Some(handle.view_id));
3292 }
3293
3294 pub fn focus_self(&mut self) {
3295 self.app.focus(self.window_id, Some(self.view_id));
3296 }
3297
3298 pub fn is_self_focused(&self) -> bool {
3299 self.app.focused_view_id(self.window_id) == Some(self.view_id)
3300 }
3301
3302 pub fn blur(&mut self) {
3303 self.app.focus(self.window_id, None);
3304 }
3305
3306 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
3307 where
3308 S: Entity,
3309 F: FnOnce(&mut ModelContext<S>) -> S,
3310 {
3311 self.app.add_model(build_model)
3312 }
3313
3314 pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
3315 where
3316 S: View,
3317 F: FnOnce(&mut ViewContext<S>) -> S,
3318 {
3319 self.app.add_view(self.window_id, build_view)
3320 }
3321
3322 pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
3323 where
3324 S: View,
3325 F: FnOnce(&mut ViewContext<S>) -> Option<S>,
3326 {
3327 self.app.add_option_view(self.window_id, build_view)
3328 }
3329
3330 pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
3331 where
3332 V: View,
3333 F: FnOnce(&mut ViewContext<V>) -> V,
3334 {
3335 let window_id = self.window_id;
3336 self.update(|this| {
3337 let root_view = this.add_view(window_id, build_root_view);
3338 let window = this.cx.windows.get_mut(&window_id).unwrap();
3339 window.root_view = root_view.clone().into();
3340 window.focused_view_id = Some(root_view.id());
3341 root_view
3342 })
3343 }
3344
3345 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
3346 where
3347 E: Entity,
3348 E::Event: 'static,
3349 H: Handle<E>,
3350 F: 'static + FnMut(&mut T, H, &E::Event, &mut ViewContext<T>),
3351 {
3352 let subscriber = self.weak_handle();
3353 self.app
3354 .subscribe_internal(handle, move |emitter, event, cx| {
3355 if let Some(subscriber) = subscriber.upgrade(cx) {
3356 subscriber.update(cx, |subscriber, cx| {
3357 callback(subscriber, emitter, event, cx);
3358 });
3359 true
3360 } else {
3361 false
3362 }
3363 })
3364 }
3365
3366 pub fn observe<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
3367 where
3368 E: Entity,
3369 H: Handle<E>,
3370 F: 'static + FnMut(&mut T, H, &mut ViewContext<T>),
3371 {
3372 let observer = self.weak_handle();
3373 self.app.observe_internal(handle, move |observed, cx| {
3374 if let Some(observer) = observer.upgrade(cx) {
3375 observer.update(cx, |observer, cx| {
3376 callback(observer, observed, cx);
3377 });
3378 true
3379 } else {
3380 false
3381 }
3382 })
3383 }
3384
3385 pub fn observe_focus<F, V>(&mut self, handle: &ViewHandle<V>, mut callback: F) -> Subscription
3386 where
3387 F: 'static + FnMut(&mut T, ViewHandle<V>, &mut ViewContext<T>),
3388 V: View,
3389 {
3390 let observer = self.weak_handle();
3391 self.app.observe_focus(handle, move |observed, cx| {
3392 if let Some(observer) = observer.upgrade(cx) {
3393 observer.update(cx, |observer, cx| {
3394 callback(observer, observed, cx);
3395 });
3396 true
3397 } else {
3398 false
3399 }
3400 })
3401 }
3402
3403 pub fn observe_release<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
3404 where
3405 E: Entity,
3406 H: Handle<E>,
3407 F: 'static + FnMut(&mut T, &E, &mut ViewContext<T>),
3408 {
3409 let observer = self.weak_handle();
3410 self.app.observe_release(handle, move |released, cx| {
3411 if let Some(observer) = observer.upgrade(cx) {
3412 observer.update(cx, |observer, cx| {
3413 callback(observer, released, cx);
3414 });
3415 }
3416 })
3417 }
3418
3419 pub fn observe_actions<F>(&mut self, mut callback: F) -> Subscription
3420 where
3421 F: 'static + FnMut(&mut T, TypeId, &mut ViewContext<T>),
3422 {
3423 let observer = self.weak_handle();
3424 self.app.observe_actions(move |action_id, cx| {
3425 if let Some(observer) = observer.upgrade(cx) {
3426 observer.update(cx, |observer, cx| {
3427 callback(observer, action_id, cx);
3428 });
3429 }
3430 })
3431 }
3432
3433 pub fn emit(&mut self, payload: T::Event) {
3434 self.app.pending_effects.push_back(Effect::Event {
3435 entity_id: self.view_id,
3436 payload: Box::new(payload),
3437 });
3438 }
3439
3440 pub fn notify(&mut self) {
3441 self.app.notify_view(self.window_id, self.view_id);
3442 }
3443
3444 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>)) {
3445 let handle = self.handle();
3446 self.app.defer(move |cx| {
3447 handle.update(cx, |view, cx| {
3448 callback(view, cx);
3449 })
3450 })
3451 }
3452
3453 pub fn after_window_update(
3454 &mut self,
3455 callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>),
3456 ) {
3457 let handle = self.handle();
3458 self.app.after_window_update(move |cx| {
3459 handle.update(cx, |view, cx| {
3460 callback(view, cx);
3461 })
3462 })
3463 }
3464
3465 pub fn propagate_action(&mut self) {
3466 self.app.halt_action_dispatch = false;
3467 }
3468
3469 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
3470 where
3471 F: FnOnce(ViewHandle<T>, AsyncAppContext) -> Fut,
3472 Fut: 'static + Future<Output = S>,
3473 S: 'static,
3474 {
3475 let handle = self.handle();
3476 self.app.spawn(|cx| f(handle, cx))
3477 }
3478
3479 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
3480 where
3481 F: FnOnce(WeakViewHandle<T>, AsyncAppContext) -> Fut,
3482 Fut: 'static + Future<Output = S>,
3483 S: 'static,
3484 {
3485 let handle = self.weak_handle();
3486 self.app.spawn(|cx| f(handle, cx))
3487 }
3488}
3489
3490pub struct RenderParams {
3491 pub window_id: usize,
3492 pub view_id: usize,
3493 pub titlebar_height: f32,
3494 pub hovered_region_ids: HashSet<MouseRegionId>,
3495 pub clicked_region_id: Option<MouseRegionId>,
3496 pub right_clicked_region_id: Option<MouseRegionId>,
3497 pub refreshing: bool,
3498}
3499
3500pub struct RenderContext<'a, T: View> {
3501 pub(crate) window_id: usize,
3502 pub(crate) view_id: usize,
3503 pub(crate) view_type: PhantomData<T>,
3504 pub(crate) hovered_region_ids: HashSet<MouseRegionId>,
3505 pub(crate) clicked_region_id: Option<MouseRegionId>,
3506 pub(crate) right_clicked_region_id: Option<MouseRegionId>,
3507 pub app: &'a mut MutableAppContext,
3508 pub titlebar_height: f32,
3509 pub refreshing: bool,
3510}
3511
3512#[derive(Clone, Copy, Default)]
3513pub struct MouseState {
3514 pub hovered: bool,
3515 pub clicked: bool,
3516 pub right_clicked: bool,
3517}
3518
3519impl<'a, V: View> RenderContext<'a, V> {
3520 fn new(params: RenderParams, app: &'a mut MutableAppContext) -> Self {
3521 Self {
3522 app,
3523 window_id: params.window_id,
3524 view_id: params.view_id,
3525 view_type: PhantomData,
3526 titlebar_height: params.titlebar_height,
3527 hovered_region_ids: params.hovered_region_ids.clone(),
3528 clicked_region_id: params.clicked_region_id,
3529 right_clicked_region_id: params.right_clicked_region_id,
3530 refreshing: params.refreshing,
3531 }
3532 }
3533
3534 pub fn handle(&self) -> WeakViewHandle<V> {
3535 WeakViewHandle::new(self.window_id, self.view_id)
3536 }
3537
3538 pub fn view_id(&self) -> usize {
3539 self.view_id
3540 }
3541
3542 pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
3543 let region_id = MouseRegionId {
3544 view_id: self.view_id,
3545 discriminant: (TypeId::of::<Tag>(), region_id),
3546 };
3547 MouseState {
3548 hovered: self.hovered_region_ids.contains(®ion_id),
3549 clicked: self.clicked_region_id == Some(region_id),
3550 right_clicked: self.right_clicked_region_id == Some(region_id),
3551 }
3552 }
3553
3554 pub fn element_state<Tag: 'static, T: 'static + Default>(
3555 &mut self,
3556 element_id: usize,
3557 ) -> ElementStateHandle<T> {
3558 let id = ElementStateId {
3559 view_id: self.view_id(),
3560 element_id,
3561 tag: TypeId::of::<Tag>(),
3562 };
3563 self.cx
3564 .element_states
3565 .entry(id)
3566 .or_insert_with(|| Box::new(T::default()));
3567 ElementStateHandle::new(id, self.frame_count, &self.cx.ref_counts)
3568 }
3569}
3570
3571impl AsRef<AppContext> for &AppContext {
3572 fn as_ref(&self) -> &AppContext {
3573 self
3574 }
3575}
3576
3577impl<V: View> Deref for RenderContext<'_, V> {
3578 type Target = MutableAppContext;
3579
3580 fn deref(&self) -> &Self::Target {
3581 self.app
3582 }
3583}
3584
3585impl<V: View> DerefMut for RenderContext<'_, V> {
3586 fn deref_mut(&mut self) -> &mut Self::Target {
3587 self.app
3588 }
3589}
3590
3591impl<V: View> ReadModel for RenderContext<'_, V> {
3592 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
3593 self.app.read_model(handle)
3594 }
3595}
3596
3597impl<V: View> UpdateModel for RenderContext<'_, V> {
3598 fn update_model<T: Entity, O>(
3599 &mut self,
3600 handle: &ModelHandle<T>,
3601 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
3602 ) -> O {
3603 self.app.update_model(handle, update)
3604 }
3605}
3606
3607impl<V: View> ReadView for RenderContext<'_, V> {
3608 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
3609 self.app.read_view(handle)
3610 }
3611}
3612
3613impl<M> AsRef<AppContext> for ViewContext<'_, M> {
3614 fn as_ref(&self) -> &AppContext {
3615 &self.app.cx
3616 }
3617}
3618
3619impl<M> Deref for ViewContext<'_, M> {
3620 type Target = MutableAppContext;
3621
3622 fn deref(&self) -> &Self::Target {
3623 &self.app
3624 }
3625}
3626
3627impl<M> DerefMut for ViewContext<'_, M> {
3628 fn deref_mut(&mut self) -> &mut Self::Target {
3629 &mut self.app
3630 }
3631}
3632
3633impl<M> AsMut<MutableAppContext> for ViewContext<'_, M> {
3634 fn as_mut(&mut self) -> &mut MutableAppContext {
3635 self.app
3636 }
3637}
3638
3639impl<V> ReadModel for ViewContext<'_, V> {
3640 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
3641 self.app.read_model(handle)
3642 }
3643}
3644
3645impl<V> UpgradeModelHandle for ViewContext<'_, V> {
3646 fn upgrade_model_handle<T: Entity>(
3647 &self,
3648 handle: &WeakModelHandle<T>,
3649 ) -> Option<ModelHandle<T>> {
3650 self.cx.upgrade_model_handle(handle)
3651 }
3652
3653 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
3654 self.cx.model_handle_is_upgradable(handle)
3655 }
3656
3657 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
3658 self.cx.upgrade_any_model_handle(handle)
3659 }
3660}
3661
3662impl<V> UpgradeViewHandle for ViewContext<'_, V> {
3663 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
3664 self.cx.upgrade_view_handle(handle)
3665 }
3666
3667 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
3668 self.cx.upgrade_any_view_handle(handle)
3669 }
3670}
3671
3672impl<V: View> UpgradeViewHandle for RenderContext<'_, V> {
3673 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
3674 self.cx.upgrade_view_handle(handle)
3675 }
3676
3677 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
3678 self.cx.upgrade_any_view_handle(handle)
3679 }
3680}
3681
3682impl<V: View> UpdateModel for ViewContext<'_, V> {
3683 fn update_model<T: Entity, O>(
3684 &mut self,
3685 handle: &ModelHandle<T>,
3686 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
3687 ) -> O {
3688 self.app.update_model(handle, update)
3689 }
3690}
3691
3692impl<V: View> ReadView for ViewContext<'_, V> {
3693 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
3694 self.app.read_view(handle)
3695 }
3696}
3697
3698impl<V: View> UpdateView for ViewContext<'_, V> {
3699 fn update_view<T, S>(
3700 &mut self,
3701 handle: &ViewHandle<T>,
3702 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
3703 ) -> S
3704 where
3705 T: View,
3706 {
3707 self.app.update_view(handle, update)
3708 }
3709}
3710
3711pub trait Handle<T> {
3712 type Weak: 'static;
3713 fn id(&self) -> usize;
3714 fn location(&self) -> EntityLocation;
3715 fn downgrade(&self) -> Self::Weak;
3716 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
3717 where
3718 Self: Sized;
3719}
3720
3721pub trait WeakHandle {
3722 fn id(&self) -> usize;
3723}
3724
3725#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
3726pub enum EntityLocation {
3727 Model(usize),
3728 View(usize, usize),
3729}
3730
3731pub struct ModelHandle<T: Entity> {
3732 model_id: usize,
3733 model_type: PhantomData<T>,
3734 ref_counts: Arc<Mutex<RefCounts>>,
3735
3736 #[cfg(any(test, feature = "test-support"))]
3737 handle_id: usize,
3738}
3739
3740impl<T: Entity> ModelHandle<T> {
3741 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
3742 ref_counts.lock().inc_model(model_id);
3743
3744 #[cfg(any(test, feature = "test-support"))]
3745 let handle_id = ref_counts
3746 .lock()
3747 .leak_detector
3748 .lock()
3749 .handle_created(Some(type_name::<T>()), model_id);
3750
3751 Self {
3752 model_id,
3753 model_type: PhantomData,
3754 ref_counts: ref_counts.clone(),
3755
3756 #[cfg(any(test, feature = "test-support"))]
3757 handle_id,
3758 }
3759 }
3760
3761 pub fn downgrade(&self) -> WeakModelHandle<T> {
3762 WeakModelHandle::new(self.model_id)
3763 }
3764
3765 pub fn id(&self) -> usize {
3766 self.model_id
3767 }
3768
3769 pub fn read<'a, C: ReadModel>(&self, cx: &'a C) -> &'a T {
3770 cx.read_model(self)
3771 }
3772
3773 pub fn read_with<'a, C, F, S>(&self, cx: &C, read: F) -> S
3774 where
3775 C: ReadModelWith,
3776 F: FnOnce(&T, &AppContext) -> S,
3777 {
3778 let mut read = Some(read);
3779 cx.read_model_with(self, &mut |model, cx| {
3780 let read = read.take().unwrap();
3781 read(model, cx)
3782 })
3783 }
3784
3785 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
3786 where
3787 C: UpdateModel,
3788 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
3789 {
3790 let mut update = Some(update);
3791 cx.update_model(self, &mut |model, cx| {
3792 let update = update.take().unwrap();
3793 update(model, cx)
3794 })
3795 }
3796
3797 #[cfg(any(test, feature = "test-support"))]
3798 pub fn next_notification(&self, cx: &TestAppContext) -> impl Future<Output = ()> {
3799 let (tx, mut rx) = futures::channel::mpsc::unbounded();
3800 let mut cx = cx.cx.borrow_mut();
3801 let subscription = cx.observe(self, move |_, _| {
3802 tx.unbounded_send(()).ok();
3803 });
3804
3805 let duration = if std::env::var("CI").is_ok() {
3806 Duration::from_secs(5)
3807 } else {
3808 Duration::from_secs(1)
3809 };
3810
3811 async move {
3812 let notification = crate::util::timeout(duration, rx.next())
3813 .await
3814 .expect("next notification timed out");
3815 drop(subscription);
3816 notification.expect("model dropped while test was waiting for its next notification")
3817 }
3818 }
3819
3820 #[cfg(any(test, feature = "test-support"))]
3821 pub fn next_event(&self, cx: &TestAppContext) -> impl Future<Output = T::Event>
3822 where
3823 T::Event: Clone,
3824 {
3825 let (tx, mut rx) = futures::channel::mpsc::unbounded();
3826 let mut cx = cx.cx.borrow_mut();
3827 let subscription = cx.subscribe(self, move |_, event, _| {
3828 tx.unbounded_send(event.clone()).ok();
3829 });
3830
3831 let duration = if std::env::var("CI").is_ok() {
3832 Duration::from_secs(5)
3833 } else {
3834 Duration::from_secs(1)
3835 };
3836
3837 cx.foreground.start_waiting();
3838 async move {
3839 let event = crate::util::timeout(duration, rx.next())
3840 .await
3841 .expect("next event timed out");
3842 drop(subscription);
3843 event.expect("model dropped while test was waiting for its next event")
3844 }
3845 }
3846
3847 #[cfg(any(test, feature = "test-support"))]
3848 pub fn condition(
3849 &self,
3850 cx: &TestAppContext,
3851 mut predicate: impl FnMut(&T, &AppContext) -> bool,
3852 ) -> impl Future<Output = ()> {
3853 let (tx, mut rx) = futures::channel::mpsc::unbounded();
3854
3855 let mut cx = cx.cx.borrow_mut();
3856 let subscriptions = (
3857 cx.observe(self, {
3858 let tx = tx.clone();
3859 move |_, _| {
3860 tx.unbounded_send(()).ok();
3861 }
3862 }),
3863 cx.subscribe(self, {
3864 let tx = tx.clone();
3865 move |_, _, _| {
3866 tx.unbounded_send(()).ok();
3867 }
3868 }),
3869 );
3870
3871 let cx = cx.weak_self.as_ref().unwrap().upgrade().unwrap();
3872 let handle = self.downgrade();
3873 let duration = if std::env::var("CI").is_ok() {
3874 Duration::from_secs(5)
3875 } else {
3876 Duration::from_secs(1)
3877 };
3878
3879 async move {
3880 crate::util::timeout(duration, async move {
3881 loop {
3882 {
3883 let cx = cx.borrow();
3884 let cx = cx.as_ref();
3885 if predicate(
3886 handle
3887 .upgrade(cx)
3888 .expect("model dropped with pending condition")
3889 .read(cx),
3890 cx,
3891 ) {
3892 break;
3893 }
3894 }
3895
3896 cx.borrow().foreground().start_waiting();
3897 rx.next()
3898 .await
3899 .expect("model dropped with pending condition");
3900 cx.borrow().foreground().finish_waiting();
3901 }
3902 })
3903 .await
3904 .expect("condition timed out");
3905 drop(subscriptions);
3906 }
3907 }
3908}
3909
3910impl<T: Entity> Clone for ModelHandle<T> {
3911 fn clone(&self) -> Self {
3912 Self::new(self.model_id, &self.ref_counts)
3913 }
3914}
3915
3916impl<T: Entity> PartialEq for ModelHandle<T> {
3917 fn eq(&self, other: &Self) -> bool {
3918 self.model_id == other.model_id
3919 }
3920}
3921
3922impl<T: Entity> Eq for ModelHandle<T> {}
3923
3924impl<T: Entity> PartialEq<WeakModelHandle<T>> for ModelHandle<T> {
3925 fn eq(&self, other: &WeakModelHandle<T>) -> bool {
3926 self.model_id == other.model_id
3927 }
3928}
3929
3930impl<T: Entity> Hash for ModelHandle<T> {
3931 fn hash<H: Hasher>(&self, state: &mut H) {
3932 self.model_id.hash(state);
3933 }
3934}
3935
3936impl<T: Entity> std::borrow::Borrow<usize> for ModelHandle<T> {
3937 fn borrow(&self) -> &usize {
3938 &self.model_id
3939 }
3940}
3941
3942impl<T: Entity> Debug for ModelHandle<T> {
3943 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3944 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
3945 .field(&self.model_id)
3946 .finish()
3947 }
3948}
3949
3950unsafe impl<T: Entity> Send for ModelHandle<T> {}
3951unsafe impl<T: Entity> Sync for ModelHandle<T> {}
3952
3953impl<T: Entity> Drop for ModelHandle<T> {
3954 fn drop(&mut self) {
3955 let mut ref_counts = self.ref_counts.lock();
3956 ref_counts.dec_model(self.model_id);
3957
3958 #[cfg(any(test, feature = "test-support"))]
3959 ref_counts
3960 .leak_detector
3961 .lock()
3962 .handle_dropped(self.model_id, self.handle_id);
3963 }
3964}
3965
3966impl<T: Entity> Handle<T> for ModelHandle<T> {
3967 type Weak = WeakModelHandle<T>;
3968
3969 fn id(&self) -> usize {
3970 self.model_id
3971 }
3972
3973 fn location(&self) -> EntityLocation {
3974 EntityLocation::Model(self.model_id)
3975 }
3976
3977 fn downgrade(&self) -> Self::Weak {
3978 self.downgrade()
3979 }
3980
3981 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
3982 where
3983 Self: Sized,
3984 {
3985 weak.upgrade(cx)
3986 }
3987}
3988
3989pub struct WeakModelHandle<T> {
3990 model_id: usize,
3991 model_type: PhantomData<T>,
3992}
3993
3994impl<T> WeakHandle for WeakModelHandle<T> {
3995 fn id(&self) -> usize {
3996 self.model_id
3997 }
3998}
3999
4000unsafe impl<T> Send for WeakModelHandle<T> {}
4001unsafe impl<T> Sync for WeakModelHandle<T> {}
4002
4003impl<T: Entity> WeakModelHandle<T> {
4004 fn new(model_id: usize) -> Self {
4005 Self {
4006 model_id,
4007 model_type: PhantomData,
4008 }
4009 }
4010
4011 pub fn id(&self) -> usize {
4012 self.model_id
4013 }
4014
4015 pub fn is_upgradable(&self, cx: &impl UpgradeModelHandle) -> bool {
4016 cx.model_handle_is_upgradable(self)
4017 }
4018
4019 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<ModelHandle<T>> {
4020 cx.upgrade_model_handle(self)
4021 }
4022}
4023
4024impl<T> Hash for WeakModelHandle<T> {
4025 fn hash<H: Hasher>(&self, state: &mut H) {
4026 self.model_id.hash(state)
4027 }
4028}
4029
4030impl<T> PartialEq for WeakModelHandle<T> {
4031 fn eq(&self, other: &Self) -> bool {
4032 self.model_id == other.model_id
4033 }
4034}
4035
4036impl<T> Eq for WeakModelHandle<T> {}
4037
4038impl<T> Clone for WeakModelHandle<T> {
4039 fn clone(&self) -> Self {
4040 Self {
4041 model_id: self.model_id,
4042 model_type: PhantomData,
4043 }
4044 }
4045}
4046
4047impl<T> Copy for WeakModelHandle<T> {}
4048
4049pub struct ViewHandle<T> {
4050 window_id: usize,
4051 view_id: usize,
4052 view_type: PhantomData<T>,
4053 ref_counts: Arc<Mutex<RefCounts>>,
4054 #[cfg(any(test, feature = "test-support"))]
4055 handle_id: usize,
4056}
4057
4058impl<T: View> ViewHandle<T> {
4059 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4060 ref_counts.lock().inc_view(window_id, view_id);
4061 #[cfg(any(test, feature = "test-support"))]
4062 let handle_id = ref_counts
4063 .lock()
4064 .leak_detector
4065 .lock()
4066 .handle_created(Some(type_name::<T>()), view_id);
4067
4068 Self {
4069 window_id,
4070 view_id,
4071 view_type: PhantomData,
4072 ref_counts: ref_counts.clone(),
4073
4074 #[cfg(any(test, feature = "test-support"))]
4075 handle_id,
4076 }
4077 }
4078
4079 pub fn downgrade(&self) -> WeakViewHandle<T> {
4080 WeakViewHandle::new(self.window_id, self.view_id)
4081 }
4082
4083 pub fn window_id(&self) -> usize {
4084 self.window_id
4085 }
4086
4087 pub fn id(&self) -> usize {
4088 self.view_id
4089 }
4090
4091 pub fn read<'a, C: ReadView>(&self, cx: &'a C) -> &'a T {
4092 cx.read_view(self)
4093 }
4094
4095 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
4096 where
4097 C: ReadViewWith,
4098 F: FnOnce(&T, &AppContext) -> S,
4099 {
4100 let mut read = Some(read);
4101 cx.read_view_with(self, &mut |view, cx| {
4102 let read = read.take().unwrap();
4103 read(view, cx)
4104 })
4105 }
4106
4107 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
4108 where
4109 C: UpdateView,
4110 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
4111 {
4112 let mut update = Some(update);
4113 cx.update_view(self, &mut |view, cx| {
4114 let update = update.take().unwrap();
4115 update(view, cx)
4116 })
4117 }
4118
4119 pub fn defer<C, F>(&self, cx: &mut C, update: F)
4120 where
4121 C: AsMut<MutableAppContext>,
4122 F: 'static + FnOnce(&mut T, &mut ViewContext<T>),
4123 {
4124 let this = self.clone();
4125 cx.as_mut().defer(move |cx| {
4126 this.update(cx, |view, cx| update(view, cx));
4127 });
4128 }
4129
4130 pub fn is_focused(&self, cx: &AppContext) -> bool {
4131 cx.focused_view_id(self.window_id)
4132 .map_or(false, |focused_id| focused_id == self.view_id)
4133 }
4134
4135 #[cfg(any(test, feature = "test-support"))]
4136 pub fn next_notification(&self, cx: &TestAppContext) -> impl Future<Output = ()> {
4137 use postage::prelude::{Sink as _, Stream as _};
4138
4139 let (mut tx, mut rx) = postage::mpsc::channel(1);
4140 let mut cx = cx.cx.borrow_mut();
4141 let subscription = cx.observe(self, move |_, _| {
4142 tx.try_send(()).ok();
4143 });
4144
4145 let duration = if std::env::var("CI").is_ok() {
4146 Duration::from_secs(5)
4147 } else {
4148 Duration::from_secs(1)
4149 };
4150
4151 async move {
4152 let notification = crate::util::timeout(duration, rx.recv())
4153 .await
4154 .expect("next notification timed out");
4155 drop(subscription);
4156 notification.expect("model dropped while test was waiting for its next notification")
4157 }
4158 }
4159
4160 #[cfg(any(test, feature = "test-support"))]
4161 pub fn condition(
4162 &self,
4163 cx: &TestAppContext,
4164 mut predicate: impl FnMut(&T, &AppContext) -> bool,
4165 ) -> impl Future<Output = ()> {
4166 use postage::prelude::{Sink as _, Stream as _};
4167
4168 let (tx, mut rx) = postage::mpsc::channel(1024);
4169
4170 let mut cx = cx.cx.borrow_mut();
4171 let subscriptions = self.update(&mut *cx, |_, cx| {
4172 (
4173 cx.observe(self, {
4174 let mut tx = tx.clone();
4175 move |_, _, _| {
4176 tx.blocking_send(()).ok();
4177 }
4178 }),
4179 cx.subscribe(self, {
4180 let mut tx = tx.clone();
4181 move |_, _, _, _| {
4182 tx.blocking_send(()).ok();
4183 }
4184 }),
4185 )
4186 });
4187
4188 let cx = cx.weak_self.as_ref().unwrap().upgrade().unwrap();
4189 let handle = self.downgrade();
4190 let duration = if std::env::var("CI").is_ok() {
4191 Duration::from_secs(2)
4192 } else {
4193 Duration::from_millis(500)
4194 };
4195
4196 async move {
4197 crate::util::timeout(duration, async move {
4198 loop {
4199 {
4200 let cx = cx.borrow();
4201 let cx = cx.as_ref();
4202 if predicate(
4203 handle
4204 .upgrade(cx)
4205 .expect("view dropped with pending condition")
4206 .read(cx),
4207 cx,
4208 ) {
4209 break;
4210 }
4211 }
4212
4213 cx.borrow().foreground().start_waiting();
4214 rx.recv()
4215 .await
4216 .expect("view dropped with pending condition");
4217 cx.borrow().foreground().finish_waiting();
4218 }
4219 })
4220 .await
4221 .expect("condition timed out");
4222 drop(subscriptions);
4223 }
4224 }
4225}
4226
4227impl<T: View> Clone for ViewHandle<T> {
4228 fn clone(&self) -> Self {
4229 ViewHandle::new(self.window_id, self.view_id, &self.ref_counts)
4230 }
4231}
4232
4233impl<T> PartialEq for ViewHandle<T> {
4234 fn eq(&self, other: &Self) -> bool {
4235 self.window_id == other.window_id && self.view_id == other.view_id
4236 }
4237}
4238
4239impl<T> PartialEq<WeakViewHandle<T>> for ViewHandle<T> {
4240 fn eq(&self, other: &WeakViewHandle<T>) -> bool {
4241 self.window_id == other.window_id && self.view_id == other.view_id
4242 }
4243}
4244
4245impl<T> PartialEq<ViewHandle<T>> for WeakViewHandle<T> {
4246 fn eq(&self, other: &ViewHandle<T>) -> bool {
4247 self.window_id == other.window_id && self.view_id == other.view_id
4248 }
4249}
4250
4251impl<T> Eq for ViewHandle<T> {}
4252
4253impl<T> Hash for ViewHandle<T> {
4254 fn hash<H: Hasher>(&self, state: &mut H) {
4255 self.window_id.hash(state);
4256 self.view_id.hash(state);
4257 }
4258}
4259
4260impl<T> Debug for ViewHandle<T> {
4261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4262 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
4263 .field("window_id", &self.window_id)
4264 .field("view_id", &self.view_id)
4265 .finish()
4266 }
4267}
4268
4269impl<T> Drop for ViewHandle<T> {
4270 fn drop(&mut self) {
4271 self.ref_counts
4272 .lock()
4273 .dec_view(self.window_id, self.view_id);
4274 #[cfg(any(test, feature = "test-support"))]
4275 self.ref_counts
4276 .lock()
4277 .leak_detector
4278 .lock()
4279 .handle_dropped(self.view_id, self.handle_id);
4280 }
4281}
4282
4283impl<T: View> Handle<T> for ViewHandle<T> {
4284 type Weak = WeakViewHandle<T>;
4285
4286 fn id(&self) -> usize {
4287 self.view_id
4288 }
4289
4290 fn location(&self) -> EntityLocation {
4291 EntityLocation::View(self.window_id, self.view_id)
4292 }
4293
4294 fn downgrade(&self) -> Self::Weak {
4295 self.downgrade()
4296 }
4297
4298 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4299 where
4300 Self: Sized,
4301 {
4302 weak.upgrade(cx)
4303 }
4304}
4305
4306pub struct AnyViewHandle {
4307 window_id: usize,
4308 view_id: usize,
4309 view_type: TypeId,
4310 ref_counts: Arc<Mutex<RefCounts>>,
4311
4312 #[cfg(any(test, feature = "test-support"))]
4313 handle_id: usize,
4314}
4315
4316impl AnyViewHandle {
4317 fn new(
4318 window_id: usize,
4319 view_id: usize,
4320 view_type: TypeId,
4321 ref_counts: Arc<Mutex<RefCounts>>,
4322 ) -> Self {
4323 ref_counts.lock().inc_view(window_id, view_id);
4324
4325 #[cfg(any(test, feature = "test-support"))]
4326 let handle_id = ref_counts
4327 .lock()
4328 .leak_detector
4329 .lock()
4330 .handle_created(None, view_id);
4331
4332 Self {
4333 window_id,
4334 view_id,
4335 view_type,
4336 ref_counts,
4337 #[cfg(any(test, feature = "test-support"))]
4338 handle_id,
4339 }
4340 }
4341
4342 pub fn id(&self) -> usize {
4343 self.view_id
4344 }
4345
4346 pub fn is<T: 'static>(&self) -> bool {
4347 TypeId::of::<T>() == self.view_type
4348 }
4349
4350 pub fn is_focused(&self, cx: &AppContext) -> bool {
4351 cx.focused_view_id(self.window_id)
4352 .map_or(false, |focused_id| focused_id == self.view_id)
4353 }
4354
4355 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
4356 if self.is::<T>() {
4357 let result = Some(ViewHandle {
4358 window_id: self.window_id,
4359 view_id: self.view_id,
4360 ref_counts: self.ref_counts.clone(),
4361 view_type: PhantomData,
4362 #[cfg(any(test, feature = "test-support"))]
4363 handle_id: self.handle_id,
4364 });
4365 unsafe {
4366 Arc::decrement_strong_count(&self.ref_counts);
4367 }
4368 std::mem::forget(self);
4369 result
4370 } else {
4371 None
4372 }
4373 }
4374
4375 pub fn downgrade(&self) -> AnyWeakViewHandle {
4376 AnyWeakViewHandle {
4377 window_id: self.window_id,
4378 view_id: self.view_id,
4379 view_type: self.view_type,
4380 }
4381 }
4382
4383 pub fn view_type(&self) -> TypeId {
4384 self.view_type
4385 }
4386
4387 pub fn debug_json(&self, cx: &AppContext) -> serde_json::Value {
4388 cx.views
4389 .get(&(self.window_id, self.view_id))
4390 .map_or_else(|| serde_json::Value::Null, |view| view.debug_json(cx))
4391 }
4392}
4393
4394impl Clone for AnyViewHandle {
4395 fn clone(&self) -> Self {
4396 Self::new(
4397 self.window_id,
4398 self.view_id,
4399 self.view_type,
4400 self.ref_counts.clone(),
4401 )
4402 }
4403}
4404
4405impl From<&AnyViewHandle> for AnyViewHandle {
4406 fn from(handle: &AnyViewHandle) -> Self {
4407 handle.clone()
4408 }
4409}
4410
4411impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
4412 fn from(handle: &ViewHandle<T>) -> Self {
4413 Self::new(
4414 handle.window_id,
4415 handle.view_id,
4416 TypeId::of::<T>(),
4417 handle.ref_counts.clone(),
4418 )
4419 }
4420}
4421
4422impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
4423 fn from(handle: ViewHandle<T>) -> Self {
4424 let any_handle = AnyViewHandle {
4425 window_id: handle.window_id,
4426 view_id: handle.view_id,
4427 view_type: TypeId::of::<T>(),
4428 ref_counts: handle.ref_counts.clone(),
4429 #[cfg(any(test, feature = "test-support"))]
4430 handle_id: handle.handle_id,
4431 };
4432 unsafe {
4433 Arc::decrement_strong_count(&handle.ref_counts);
4434 }
4435 std::mem::forget(handle);
4436 any_handle
4437 }
4438}
4439
4440impl Drop for AnyViewHandle {
4441 fn drop(&mut self) {
4442 self.ref_counts
4443 .lock()
4444 .dec_view(self.window_id, self.view_id);
4445 #[cfg(any(test, feature = "test-support"))]
4446 self.ref_counts
4447 .lock()
4448 .leak_detector
4449 .lock()
4450 .handle_dropped(self.view_id, self.handle_id);
4451 }
4452}
4453
4454pub struct AnyModelHandle {
4455 model_id: usize,
4456 model_type: TypeId,
4457 ref_counts: Arc<Mutex<RefCounts>>,
4458
4459 #[cfg(any(test, feature = "test-support"))]
4460 handle_id: usize,
4461}
4462
4463impl AnyModelHandle {
4464 fn new(model_id: usize, model_type: TypeId, ref_counts: Arc<Mutex<RefCounts>>) -> Self {
4465 ref_counts.lock().inc_model(model_id);
4466
4467 #[cfg(any(test, feature = "test-support"))]
4468 let handle_id = ref_counts
4469 .lock()
4470 .leak_detector
4471 .lock()
4472 .handle_created(None, model_id);
4473
4474 Self {
4475 model_id,
4476 model_type,
4477 ref_counts,
4478
4479 #[cfg(any(test, feature = "test-support"))]
4480 handle_id,
4481 }
4482 }
4483
4484 pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> {
4485 if self.is::<T>() {
4486 let result = Some(ModelHandle {
4487 model_id: self.model_id,
4488 model_type: PhantomData,
4489 ref_counts: self.ref_counts.clone(),
4490
4491 #[cfg(any(test, feature = "test-support"))]
4492 handle_id: self.handle_id,
4493 });
4494 unsafe {
4495 Arc::decrement_strong_count(&self.ref_counts);
4496 }
4497 std::mem::forget(self);
4498 result
4499 } else {
4500 None
4501 }
4502 }
4503
4504 pub fn downgrade(&self) -> AnyWeakModelHandle {
4505 AnyWeakModelHandle {
4506 model_id: self.model_id,
4507 model_type: self.model_type,
4508 }
4509 }
4510
4511 pub fn is<T: Entity>(&self) -> bool {
4512 self.model_type == TypeId::of::<T>()
4513 }
4514
4515 pub fn model_type(&self) -> TypeId {
4516 self.model_type
4517 }
4518}
4519
4520impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
4521 fn from(handle: ModelHandle<T>) -> Self {
4522 Self::new(
4523 handle.model_id,
4524 TypeId::of::<T>(),
4525 handle.ref_counts.clone(),
4526 )
4527 }
4528}
4529
4530impl Clone for AnyModelHandle {
4531 fn clone(&self) -> Self {
4532 Self::new(self.model_id, self.model_type, self.ref_counts.clone())
4533 }
4534}
4535
4536impl Drop for AnyModelHandle {
4537 fn drop(&mut self) {
4538 let mut ref_counts = self.ref_counts.lock();
4539 ref_counts.dec_model(self.model_id);
4540
4541 #[cfg(any(test, feature = "test-support"))]
4542 ref_counts
4543 .leak_detector
4544 .lock()
4545 .handle_dropped(self.model_id, self.handle_id);
4546 }
4547}
4548
4549pub struct AnyWeakModelHandle {
4550 model_id: usize,
4551 model_type: TypeId,
4552}
4553
4554impl AnyWeakModelHandle {
4555 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<AnyModelHandle> {
4556 cx.upgrade_any_model_handle(self)
4557 }
4558}
4559
4560impl<T: Entity> From<WeakModelHandle<T>> for AnyWeakModelHandle {
4561 fn from(handle: WeakModelHandle<T>) -> Self {
4562 AnyWeakModelHandle {
4563 model_id: handle.model_id,
4564 model_type: TypeId::of::<T>(),
4565 }
4566 }
4567}
4568
4569pub struct WeakViewHandle<T> {
4570 window_id: usize,
4571 view_id: usize,
4572 view_type: PhantomData<T>,
4573}
4574
4575impl<T> WeakHandle for WeakViewHandle<T> {
4576 fn id(&self) -> usize {
4577 self.view_id
4578 }
4579}
4580
4581impl<T: View> WeakViewHandle<T> {
4582 fn new(window_id: usize, view_id: usize) -> Self {
4583 Self {
4584 window_id,
4585 view_id,
4586 view_type: PhantomData,
4587 }
4588 }
4589
4590 pub fn id(&self) -> usize {
4591 self.view_id
4592 }
4593
4594 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<ViewHandle<T>> {
4595 cx.upgrade_view_handle(self)
4596 }
4597}
4598
4599impl<T> Clone for WeakViewHandle<T> {
4600 fn clone(&self) -> Self {
4601 Self {
4602 window_id: self.window_id,
4603 view_id: self.view_id,
4604 view_type: PhantomData,
4605 }
4606 }
4607}
4608
4609impl<T> PartialEq for WeakViewHandle<T> {
4610 fn eq(&self, other: &Self) -> bool {
4611 self.window_id == other.window_id && self.view_id == other.view_id
4612 }
4613}
4614
4615impl<T> Eq for WeakViewHandle<T> {}
4616
4617impl<T> Hash for WeakViewHandle<T> {
4618 fn hash<H: Hasher>(&self, state: &mut H) {
4619 self.window_id.hash(state);
4620 self.view_id.hash(state);
4621 }
4622}
4623
4624pub struct AnyWeakViewHandle {
4625 window_id: usize,
4626 view_id: usize,
4627 view_type: TypeId,
4628}
4629
4630impl AnyWeakViewHandle {
4631 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<AnyViewHandle> {
4632 cx.upgrade_any_view_handle(self)
4633 }
4634}
4635
4636impl<T: View> From<WeakViewHandle<T>> for AnyWeakViewHandle {
4637 fn from(handle: WeakViewHandle<T>) -> Self {
4638 AnyWeakViewHandle {
4639 window_id: handle.window_id,
4640 view_id: handle.view_id,
4641 view_type: TypeId::of::<T>(),
4642 }
4643 }
4644}
4645
4646#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4647pub struct ElementStateId {
4648 view_id: usize,
4649 element_id: usize,
4650 tag: TypeId,
4651}
4652
4653pub struct ElementStateHandle<T> {
4654 value_type: PhantomData<T>,
4655 id: ElementStateId,
4656 ref_counts: Weak<Mutex<RefCounts>>,
4657}
4658
4659impl<T: 'static> ElementStateHandle<T> {
4660 fn new(id: ElementStateId, frame_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4661 ref_counts.lock().inc_element_state(id, frame_id);
4662 Self {
4663 value_type: PhantomData,
4664 id,
4665 ref_counts: Arc::downgrade(ref_counts),
4666 }
4667 }
4668
4669 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
4670 cx.element_states
4671 .get(&self.id)
4672 .unwrap()
4673 .downcast_ref()
4674 .unwrap()
4675 }
4676
4677 pub fn update<C, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R
4678 where
4679 C: DerefMut<Target = MutableAppContext>,
4680 {
4681 let mut element_state = cx.deref_mut().cx.element_states.remove(&self.id).unwrap();
4682 let result = f(element_state.downcast_mut().unwrap(), cx);
4683 cx.deref_mut()
4684 .cx
4685 .element_states
4686 .insert(self.id, element_state);
4687 result
4688 }
4689}
4690
4691impl<T> Drop for ElementStateHandle<T> {
4692 fn drop(&mut self) {
4693 if let Some(ref_counts) = self.ref_counts.upgrade() {
4694 ref_counts.lock().dec_element_state(self.id);
4695 }
4696 }
4697}
4698
4699#[must_use]
4700pub enum Subscription {
4701 Subscription {
4702 id: usize,
4703 entity_id: usize,
4704 subscriptions:
4705 Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, Option<SubscriptionCallback>>>>>>,
4706 },
4707 GlobalSubscription {
4708 id: usize,
4709 type_id: TypeId,
4710 subscriptions: Option<
4711 Weak<Mutex<HashMap<TypeId, BTreeMap<usize, Option<GlobalSubscriptionCallback>>>>>,
4712 >,
4713 },
4714 Observation {
4715 id: usize,
4716 entity_id: usize,
4717 observations:
4718 Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, Option<ObservationCallback>>>>>>,
4719 },
4720 GlobalObservation {
4721 id: usize,
4722 type_id: TypeId,
4723 observations: Option<
4724 Weak<Mutex<HashMap<TypeId, BTreeMap<usize, Option<GlobalObservationCallback>>>>>,
4725 >,
4726 },
4727 FocusObservation {
4728 id: usize,
4729 view_id: usize,
4730 observations:
4731 Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, Option<FocusObservationCallback>>>>>>,
4732 },
4733 ReleaseObservation {
4734 id: usize,
4735 entity_id: usize,
4736 observations:
4737 Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>>,
4738 },
4739 ActionObservation {
4740 id: usize,
4741 observations: Option<Weak<Mutex<BTreeMap<usize, ActionObservationCallback>>>>,
4742 },
4743}
4744
4745impl Subscription {
4746 pub fn detach(&mut self) {
4747 match self {
4748 Subscription::Subscription { subscriptions, .. } => {
4749 subscriptions.take();
4750 }
4751 Subscription::GlobalSubscription { subscriptions, .. } => {
4752 subscriptions.take();
4753 }
4754 Subscription::Observation { observations, .. } => {
4755 observations.take();
4756 }
4757 Subscription::GlobalObservation { observations, .. } => {
4758 observations.take();
4759 }
4760 Subscription::ReleaseObservation { observations, .. } => {
4761 observations.take();
4762 }
4763 Subscription::FocusObservation { observations, .. } => {
4764 observations.take();
4765 }
4766 Subscription::ActionObservation { observations, .. } => {
4767 observations.take();
4768 }
4769 }
4770 }
4771}
4772
4773impl Drop for Subscription {
4774 fn drop(&mut self) {
4775 match self {
4776 Subscription::Subscription {
4777 id,
4778 entity_id,
4779 subscriptions,
4780 } => {
4781 if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
4782 match subscriptions
4783 .lock()
4784 .entry(*entity_id)
4785 .or_default()
4786 .entry(*id)
4787 {
4788 btree_map::Entry::Vacant(entry) => {
4789 entry.insert(None);
4790 }
4791 btree_map::Entry::Occupied(entry) => {
4792 entry.remove();
4793 }
4794 }
4795 }
4796 }
4797 Subscription::GlobalSubscription {
4798 id,
4799 type_id,
4800 subscriptions,
4801 } => {
4802 if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
4803 match subscriptions.lock().entry(*type_id).or_default().entry(*id) {
4804 btree_map::Entry::Vacant(entry) => {
4805 entry.insert(None);
4806 }
4807 btree_map::Entry::Occupied(entry) => {
4808 entry.remove();
4809 }
4810 }
4811 }
4812 }
4813 Subscription::Observation {
4814 id,
4815 entity_id,
4816 observations,
4817 } => {
4818 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
4819 match observations
4820 .lock()
4821 .entry(*entity_id)
4822 .or_default()
4823 .entry(*id)
4824 {
4825 btree_map::Entry::Vacant(entry) => {
4826 entry.insert(None);
4827 }
4828 btree_map::Entry::Occupied(entry) => {
4829 entry.remove();
4830 }
4831 }
4832 }
4833 }
4834 Subscription::GlobalObservation {
4835 id,
4836 type_id,
4837 observations,
4838 } => {
4839 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
4840 match observations.lock().entry(*type_id).or_default().entry(*id) {
4841 collections::btree_map::Entry::Vacant(entry) => {
4842 entry.insert(None);
4843 }
4844 collections::btree_map::Entry::Occupied(entry) => {
4845 entry.remove();
4846 }
4847 }
4848 }
4849 }
4850 Subscription::ReleaseObservation {
4851 id,
4852 entity_id,
4853 observations,
4854 } => {
4855 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
4856 if let Some(observations) = observations.lock().get_mut(entity_id) {
4857 observations.remove(id);
4858 }
4859 }
4860 }
4861 Subscription::FocusObservation {
4862 id,
4863 view_id,
4864 observations,
4865 } => {
4866 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
4867 match observations.lock().entry(*view_id).or_default().entry(*id) {
4868 btree_map::Entry::Vacant(entry) => {
4869 entry.insert(None);
4870 }
4871 btree_map::Entry::Occupied(entry) => {
4872 entry.remove();
4873 }
4874 }
4875 }
4876 }
4877 Subscription::ActionObservation { id, observations } => {
4878 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
4879 observations.lock().remove(&id);
4880 }
4881 }
4882 }
4883 }
4884}
4885
4886lazy_static! {
4887 static ref LEAK_BACKTRACE: bool =
4888 std::env::var("LEAK_BACKTRACE").map_or(false, |b| !b.is_empty());
4889}
4890
4891#[cfg(any(test, feature = "test-support"))]
4892#[derive(Default)]
4893pub struct LeakDetector {
4894 next_handle_id: usize,
4895 handle_backtraces: HashMap<
4896 usize,
4897 (
4898 Option<&'static str>,
4899 HashMap<usize, Option<backtrace::Backtrace>>,
4900 ),
4901 >,
4902}
4903
4904#[cfg(any(test, feature = "test-support"))]
4905impl LeakDetector {
4906 fn handle_created(&mut self, type_name: Option<&'static str>, entity_id: usize) -> usize {
4907 let handle_id = post_inc(&mut self.next_handle_id);
4908 let entry = self.handle_backtraces.entry(entity_id).or_default();
4909 let backtrace = if *LEAK_BACKTRACE {
4910 Some(backtrace::Backtrace::new_unresolved())
4911 } else {
4912 None
4913 };
4914 if let Some(type_name) = type_name {
4915 entry.0.get_or_insert(type_name);
4916 }
4917 entry.1.insert(handle_id, backtrace);
4918 handle_id
4919 }
4920
4921 fn handle_dropped(&mut self, entity_id: usize, handle_id: usize) {
4922 if let Some((_, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
4923 assert!(backtraces.remove(&handle_id).is_some());
4924 if backtraces.is_empty() {
4925 self.handle_backtraces.remove(&entity_id);
4926 }
4927 }
4928 }
4929
4930 pub fn assert_dropped(&mut self, entity_id: usize) {
4931 if let Some((type_name, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
4932 for trace in backtraces.values_mut() {
4933 if let Some(trace) = trace {
4934 trace.resolve();
4935 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
4936 }
4937 }
4938
4939 let hint = if *LEAK_BACKTRACE {
4940 ""
4941 } else {
4942 " – set LEAK_BACKTRACE=1 for more information"
4943 };
4944
4945 panic!(
4946 "{} handles to {} {} still exist{}",
4947 backtraces.len(),
4948 type_name.unwrap_or("entity"),
4949 entity_id,
4950 hint
4951 );
4952 }
4953 }
4954
4955 pub fn detect(&mut self) {
4956 let mut found_leaks = false;
4957 for (id, (type_name, backtraces)) in self.handle_backtraces.iter_mut() {
4958 eprintln!(
4959 "leaked {} handles to {} {}",
4960 backtraces.len(),
4961 type_name.unwrap_or("entity"),
4962 id
4963 );
4964 for trace in backtraces.values_mut() {
4965 if let Some(trace) = trace {
4966 trace.resolve();
4967 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
4968 }
4969 }
4970 found_leaks = true;
4971 }
4972
4973 let hint = if *LEAK_BACKTRACE {
4974 ""
4975 } else {
4976 " – set LEAK_BACKTRACE=1 for more information"
4977 };
4978 assert!(!found_leaks, "detected leaked handles{}", hint);
4979 }
4980}
4981
4982#[derive(Default)]
4983struct RefCounts {
4984 entity_counts: HashMap<usize, usize>,
4985 element_state_counts: HashMap<ElementStateId, ElementStateRefCount>,
4986 dropped_models: HashSet<usize>,
4987 dropped_views: HashSet<(usize, usize)>,
4988 dropped_element_states: HashSet<ElementStateId>,
4989
4990 #[cfg(any(test, feature = "test-support"))]
4991 leak_detector: Arc<Mutex<LeakDetector>>,
4992}
4993
4994struct ElementStateRefCount {
4995 ref_count: usize,
4996 frame_id: usize,
4997}
4998
4999impl RefCounts {
5000 fn inc_model(&mut self, model_id: usize) {
5001 match self.entity_counts.entry(model_id) {
5002 Entry::Occupied(mut entry) => {
5003 *entry.get_mut() += 1;
5004 }
5005 Entry::Vacant(entry) => {
5006 entry.insert(1);
5007 self.dropped_models.remove(&model_id);
5008 }
5009 }
5010 }
5011
5012 fn inc_view(&mut self, window_id: usize, view_id: usize) {
5013 match self.entity_counts.entry(view_id) {
5014 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
5015 Entry::Vacant(entry) => {
5016 entry.insert(1);
5017 self.dropped_views.remove(&(window_id, view_id));
5018 }
5019 }
5020 }
5021
5022 fn inc_element_state(&mut self, id: ElementStateId, frame_id: usize) {
5023 match self.element_state_counts.entry(id) {
5024 Entry::Occupied(mut entry) => {
5025 let entry = entry.get_mut();
5026 if entry.frame_id == frame_id || entry.ref_count >= 2 {
5027 panic!("used the same element state more than once in the same frame");
5028 }
5029 entry.ref_count += 1;
5030 entry.frame_id = frame_id;
5031 }
5032 Entry::Vacant(entry) => {
5033 entry.insert(ElementStateRefCount {
5034 ref_count: 1,
5035 frame_id,
5036 });
5037 self.dropped_element_states.remove(&id);
5038 }
5039 }
5040 }
5041
5042 fn dec_model(&mut self, model_id: usize) {
5043 let count = self.entity_counts.get_mut(&model_id).unwrap();
5044 *count -= 1;
5045 if *count == 0 {
5046 self.entity_counts.remove(&model_id);
5047 self.dropped_models.insert(model_id);
5048 }
5049 }
5050
5051 fn dec_view(&mut self, window_id: usize, view_id: usize) {
5052 let count = self.entity_counts.get_mut(&view_id).unwrap();
5053 *count -= 1;
5054 if *count == 0 {
5055 self.entity_counts.remove(&view_id);
5056 self.dropped_views.insert((window_id, view_id));
5057 }
5058 }
5059
5060 fn dec_element_state(&mut self, id: ElementStateId) {
5061 let entry = self.element_state_counts.get_mut(&id).unwrap();
5062 entry.ref_count -= 1;
5063 if entry.ref_count == 0 {
5064 self.element_state_counts.remove(&id);
5065 self.dropped_element_states.insert(id);
5066 }
5067 }
5068
5069 fn is_entity_alive(&self, entity_id: usize) -> bool {
5070 self.entity_counts.contains_key(&entity_id)
5071 }
5072
5073 fn take_dropped(
5074 &mut self,
5075 ) -> (
5076 HashSet<usize>,
5077 HashSet<(usize, usize)>,
5078 HashSet<ElementStateId>,
5079 ) {
5080 (
5081 std::mem::take(&mut self.dropped_models),
5082 std::mem::take(&mut self.dropped_views),
5083 std::mem::take(&mut self.dropped_element_states),
5084 )
5085 }
5086}
5087
5088#[cfg(test)]
5089mod tests {
5090 use super::*;
5091 use crate::{actions, elements::*, impl_actions};
5092 use serde::Deserialize;
5093 use smol::future::poll_once;
5094 use std::{
5095 cell::Cell,
5096 sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
5097 };
5098
5099 #[crate::test(self)]
5100 fn test_model_handles(cx: &mut MutableAppContext) {
5101 struct Model {
5102 other: Option<ModelHandle<Model>>,
5103 events: Vec<String>,
5104 }
5105
5106 impl Entity for Model {
5107 type Event = usize;
5108 }
5109
5110 impl Model {
5111 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
5112 if let Some(other) = other.as_ref() {
5113 cx.observe(other, |me, _, _| {
5114 me.events.push("notified".into());
5115 })
5116 .detach();
5117 cx.subscribe(other, |me, _, event, _| {
5118 me.events.push(format!("observed event {}", event));
5119 })
5120 .detach();
5121 }
5122
5123 Self {
5124 other,
5125 events: Vec::new(),
5126 }
5127 }
5128 }
5129
5130 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
5131 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
5132 assert_eq!(cx.cx.models.len(), 2);
5133
5134 handle_1.update(cx, |model, cx| {
5135 model.events.push("updated".into());
5136 cx.emit(1);
5137 cx.notify();
5138 cx.emit(2);
5139 });
5140 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5141 assert_eq!(
5142 handle_2.read(cx).events,
5143 vec![
5144 "observed event 1".to_string(),
5145 "notified".to_string(),
5146 "observed event 2".to_string(),
5147 ]
5148 );
5149
5150 handle_2.update(cx, |model, _| {
5151 drop(handle_1);
5152 model.other.take();
5153 });
5154
5155 assert_eq!(cx.cx.models.len(), 1);
5156 assert!(cx.subscriptions.lock().is_empty());
5157 assert!(cx.observations.lock().is_empty());
5158 }
5159
5160 #[crate::test(self)]
5161 fn test_model_events(cx: &mut MutableAppContext) {
5162 #[derive(Default)]
5163 struct Model {
5164 events: Vec<usize>,
5165 }
5166
5167 impl Entity for Model {
5168 type Event = usize;
5169 }
5170
5171 let handle_1 = cx.add_model(|_| Model::default());
5172 let handle_2 = cx.add_model(|_| Model::default());
5173
5174 handle_1.update(cx, |_, cx| {
5175 cx.subscribe(&handle_2, move |model: &mut Model, emitter, event, cx| {
5176 model.events.push(*event);
5177
5178 cx.subscribe(&emitter, |model, _, event, _| {
5179 model.events.push(*event * 2);
5180 })
5181 .detach();
5182 })
5183 .detach();
5184 });
5185
5186 handle_2.update(cx, |_, c| c.emit(7));
5187 assert_eq!(handle_1.read(cx).events, vec![7]);
5188
5189 handle_2.update(cx, |_, c| c.emit(5));
5190 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
5191 }
5192
5193 #[crate::test(self)]
5194 fn test_model_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
5195 #[derive(Default)]
5196 struct Model;
5197
5198 impl Entity for Model {
5199 type Event = ();
5200 }
5201
5202 let events = Rc::new(RefCell::new(Vec::new()));
5203 cx.add_model(|cx| {
5204 drop(cx.subscribe(&cx.handle(), {
5205 let events = events.clone();
5206 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
5207 }));
5208 cx.subscribe(&cx.handle(), {
5209 let events = events.clone();
5210 move |_, _, _, _| events.borrow_mut().push("before emit")
5211 })
5212 .detach();
5213 cx.emit(());
5214 cx.subscribe(&cx.handle(), {
5215 let events = events.clone();
5216 move |_, _, _, _| events.borrow_mut().push("after emit")
5217 })
5218 .detach();
5219 Model
5220 });
5221 assert_eq!(*events.borrow(), ["before emit"]);
5222 }
5223
5224 #[crate::test(self)]
5225 fn test_observe_and_notify_from_model(cx: &mut MutableAppContext) {
5226 #[derive(Default)]
5227 struct Model {
5228 count: usize,
5229 events: Vec<usize>,
5230 }
5231
5232 impl Entity for Model {
5233 type Event = ();
5234 }
5235
5236 let handle_1 = cx.add_model(|_| Model::default());
5237 let handle_2 = cx.add_model(|_| Model::default());
5238
5239 handle_1.update(cx, |_, c| {
5240 c.observe(&handle_2, move |model, observed, c| {
5241 model.events.push(observed.read(c).count);
5242 c.observe(&observed, |model, observed, c| {
5243 model.events.push(observed.read(c).count * 2);
5244 })
5245 .detach();
5246 })
5247 .detach();
5248 });
5249
5250 handle_2.update(cx, |model, c| {
5251 model.count = 7;
5252 c.notify()
5253 });
5254 assert_eq!(handle_1.read(cx).events, vec![7]);
5255
5256 handle_2.update(cx, |model, c| {
5257 model.count = 5;
5258 c.notify()
5259 });
5260 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10])
5261 }
5262
5263 #[crate::test(self)]
5264 fn test_model_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
5265 #[derive(Default)]
5266 struct Model;
5267
5268 impl Entity for Model {
5269 type Event = ();
5270 }
5271
5272 let events = Rc::new(RefCell::new(Vec::new()));
5273 cx.add_model(|cx| {
5274 drop(cx.observe(&cx.handle(), {
5275 let events = events.clone();
5276 move |_, _, _| events.borrow_mut().push("dropped before flush")
5277 }));
5278 cx.observe(&cx.handle(), {
5279 let events = events.clone();
5280 move |_, _, _| events.borrow_mut().push("before notify")
5281 })
5282 .detach();
5283 cx.notify();
5284 cx.observe(&cx.handle(), {
5285 let events = events.clone();
5286 move |_, _, _| events.borrow_mut().push("after notify")
5287 })
5288 .detach();
5289 Model
5290 });
5291 assert_eq!(*events.borrow(), ["before notify"]);
5292 }
5293
5294 #[crate::test(self)]
5295 fn test_defer_and_after_window_update(cx: &mut MutableAppContext) {
5296 struct View {
5297 render_count: usize,
5298 }
5299
5300 impl Entity for View {
5301 type Event = usize;
5302 }
5303
5304 impl super::View for View {
5305 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5306 post_inc(&mut self.render_count);
5307 Empty::new().boxed()
5308 }
5309
5310 fn ui_name() -> &'static str {
5311 "View"
5312 }
5313 }
5314
5315 let (_, view) = cx.add_window(Default::default(), |_| View { render_count: 0 });
5316 let called_defer = Rc::new(AtomicBool::new(false));
5317 let called_after_window_update = Rc::new(AtomicBool::new(false));
5318
5319 view.update(cx, |this, cx| {
5320 assert_eq!(this.render_count, 1);
5321 cx.defer({
5322 let called_defer = called_defer.clone();
5323 move |this, _| {
5324 assert_eq!(this.render_count, 1);
5325 called_defer.store(true, SeqCst);
5326 }
5327 });
5328 cx.after_window_update({
5329 let called_after_window_update = called_after_window_update.clone();
5330 move |this, cx| {
5331 assert_eq!(this.render_count, 2);
5332 called_after_window_update.store(true, SeqCst);
5333 cx.notify();
5334 }
5335 });
5336 assert!(!called_defer.load(SeqCst));
5337 assert!(!called_after_window_update.load(SeqCst));
5338 cx.notify();
5339 });
5340
5341 assert!(called_defer.load(SeqCst));
5342 assert!(called_after_window_update.load(SeqCst));
5343 assert_eq!(view.read(cx).render_count, 3);
5344 }
5345
5346 #[crate::test(self)]
5347 fn test_view_handles(cx: &mut MutableAppContext) {
5348 struct View {
5349 other: Option<ViewHandle<View>>,
5350 events: Vec<String>,
5351 }
5352
5353 impl Entity for View {
5354 type Event = usize;
5355 }
5356
5357 impl super::View for View {
5358 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5359 Empty::new().boxed()
5360 }
5361
5362 fn ui_name() -> &'static str {
5363 "View"
5364 }
5365 }
5366
5367 impl View {
5368 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
5369 if let Some(other) = other.as_ref() {
5370 cx.subscribe(other, |me, _, event, _| {
5371 me.events.push(format!("observed event {}", event));
5372 })
5373 .detach();
5374 }
5375 Self {
5376 other,
5377 events: Vec::new(),
5378 }
5379 }
5380 }
5381
5382 let (window_id, _) = cx.add_window(Default::default(), |cx| View::new(None, cx));
5383 let handle_1 = cx.add_view(window_id, |cx| View::new(None, cx));
5384 let handle_2 = cx.add_view(window_id, |cx| View::new(Some(handle_1.clone()), cx));
5385 assert_eq!(cx.cx.views.len(), 3);
5386
5387 handle_1.update(cx, |view, cx| {
5388 view.events.push("updated".into());
5389 cx.emit(1);
5390 cx.emit(2);
5391 });
5392 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5393 assert_eq!(
5394 handle_2.read(cx).events,
5395 vec![
5396 "observed event 1".to_string(),
5397 "observed event 2".to_string(),
5398 ]
5399 );
5400
5401 handle_2.update(cx, |view, _| {
5402 drop(handle_1);
5403 view.other.take();
5404 });
5405
5406 assert_eq!(cx.cx.views.len(), 2);
5407 assert!(cx.subscriptions.lock().is_empty());
5408 assert!(cx.observations.lock().is_empty());
5409 }
5410
5411 #[crate::test(self)]
5412 fn test_add_window(cx: &mut MutableAppContext) {
5413 struct View {
5414 mouse_down_count: Arc<AtomicUsize>,
5415 }
5416
5417 impl Entity for View {
5418 type Event = ();
5419 }
5420
5421 impl super::View for View {
5422 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5423 let mouse_down_count = self.mouse_down_count.clone();
5424 EventHandler::new(Empty::new().boxed())
5425 .on_mouse_down(move |_| {
5426 mouse_down_count.fetch_add(1, SeqCst);
5427 true
5428 })
5429 .boxed()
5430 }
5431
5432 fn ui_name() -> &'static str {
5433 "View"
5434 }
5435 }
5436
5437 let mouse_down_count = Arc::new(AtomicUsize::new(0));
5438 let (window_id, _) = cx.add_window(Default::default(), |_| View {
5439 mouse_down_count: mouse_down_count.clone(),
5440 });
5441 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
5442 // Ensure window's root element is in a valid lifecycle state.
5443 presenter.borrow_mut().dispatch_event(
5444 Event::LeftMouseDown {
5445 position: Default::default(),
5446 ctrl: false,
5447 alt: false,
5448 shift: false,
5449 cmd: false,
5450 click_count: 1,
5451 },
5452 cx,
5453 );
5454 assert_eq!(mouse_down_count.load(SeqCst), 1);
5455 }
5456
5457 #[crate::test(self)]
5458 fn test_entity_release_hooks(cx: &mut MutableAppContext) {
5459 struct Model {
5460 released: Rc<Cell<bool>>,
5461 }
5462
5463 struct View {
5464 released: Rc<Cell<bool>>,
5465 }
5466
5467 impl Entity for Model {
5468 type Event = ();
5469
5470 fn release(&mut self, _: &mut MutableAppContext) {
5471 self.released.set(true);
5472 }
5473 }
5474
5475 impl Entity for View {
5476 type Event = ();
5477
5478 fn release(&mut self, _: &mut MutableAppContext) {
5479 self.released.set(true);
5480 }
5481 }
5482
5483 impl super::View for View {
5484 fn ui_name() -> &'static str {
5485 "View"
5486 }
5487
5488 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5489 Empty::new().boxed()
5490 }
5491 }
5492
5493 let model_released = Rc::new(Cell::new(false));
5494 let model_release_observed = Rc::new(Cell::new(false));
5495 let view_released = Rc::new(Cell::new(false));
5496 let view_release_observed = Rc::new(Cell::new(false));
5497
5498 let model = cx.add_model(|_| Model {
5499 released: model_released.clone(),
5500 });
5501 let (window_id, view) = cx.add_window(Default::default(), |_| View {
5502 released: view_released.clone(),
5503 });
5504 assert!(!model_released.get());
5505 assert!(!view_released.get());
5506
5507 cx.observe_release(&model, {
5508 let model_release_observed = model_release_observed.clone();
5509 move |_, _| model_release_observed.set(true)
5510 })
5511 .detach();
5512 cx.observe_release(&view, {
5513 let view_release_observed = view_release_observed.clone();
5514 move |_, _| view_release_observed.set(true)
5515 })
5516 .detach();
5517
5518 cx.update(move |_| {
5519 drop(model);
5520 });
5521 assert!(model_released.get());
5522 assert!(model_release_observed.get());
5523
5524 drop(view);
5525 cx.remove_window(window_id);
5526 assert!(view_released.get());
5527 assert!(view_release_observed.get());
5528 }
5529
5530 #[crate::test(self)]
5531 fn test_view_events(cx: &mut MutableAppContext) {
5532 #[derive(Default)]
5533 struct View {
5534 events: Vec<usize>,
5535 }
5536
5537 impl Entity for View {
5538 type Event = usize;
5539 }
5540
5541 impl super::View for View {
5542 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5543 Empty::new().boxed()
5544 }
5545
5546 fn ui_name() -> &'static str {
5547 "View"
5548 }
5549 }
5550
5551 struct Model;
5552
5553 impl Entity for Model {
5554 type Event = usize;
5555 }
5556
5557 let (window_id, handle_1) = cx.add_window(Default::default(), |_| View::default());
5558 let handle_2 = cx.add_view(window_id, |_| View::default());
5559 let handle_3 = cx.add_model(|_| Model);
5560
5561 handle_1.update(cx, |_, cx| {
5562 cx.subscribe(&handle_2, move |me, emitter, event, cx| {
5563 me.events.push(*event);
5564
5565 cx.subscribe(&emitter, |me, _, event, _| {
5566 me.events.push(*event * 2);
5567 })
5568 .detach();
5569 })
5570 .detach();
5571
5572 cx.subscribe(&handle_3, |me, _, event, _| {
5573 me.events.push(*event);
5574 })
5575 .detach();
5576 });
5577
5578 handle_2.update(cx, |_, c| c.emit(7));
5579 assert_eq!(handle_1.read(cx).events, vec![7]);
5580
5581 handle_2.update(cx, |_, c| c.emit(5));
5582 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
5583
5584 handle_3.update(cx, |_, c| c.emit(9));
5585 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10, 9]);
5586 }
5587
5588 #[crate::test(self)]
5589 fn test_global_events(cx: &mut MutableAppContext) {
5590 #[derive(Clone, Debug, Eq, PartialEq)]
5591 struct GlobalEvent(u64);
5592
5593 let events = Rc::new(RefCell::new(Vec::new()));
5594 let first_subscription;
5595 let second_subscription;
5596
5597 {
5598 let events = events.clone();
5599 first_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
5600 events.borrow_mut().push(("First", e.clone()));
5601 });
5602 }
5603
5604 {
5605 let events = events.clone();
5606 second_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
5607 events.borrow_mut().push(("Second", e.clone()));
5608 });
5609 }
5610
5611 cx.update(|cx| {
5612 cx.emit_global(GlobalEvent(1));
5613 cx.emit_global(GlobalEvent(2));
5614 });
5615
5616 drop(first_subscription);
5617
5618 cx.update(|cx| {
5619 cx.emit_global(GlobalEvent(3));
5620 });
5621
5622 drop(second_subscription);
5623
5624 cx.update(|cx| {
5625 cx.emit_global(GlobalEvent(4));
5626 });
5627
5628 assert_eq!(
5629 &*events.borrow(),
5630 &[
5631 ("First", GlobalEvent(1)),
5632 ("Second", GlobalEvent(1)),
5633 ("First", GlobalEvent(2)),
5634 ("Second", GlobalEvent(2)),
5635 ("Second", GlobalEvent(3)),
5636 ]
5637 );
5638 }
5639
5640 #[crate::test(self)]
5641 fn test_global_events_emitted_before_subscription_in_same_update_cycle(
5642 cx: &mut MutableAppContext,
5643 ) {
5644 let events = Rc::new(RefCell::new(Vec::new()));
5645 cx.update(|cx| {
5646 {
5647 let events = events.clone();
5648 drop(cx.subscribe_global(move |_: &(), _| {
5649 events.borrow_mut().push("dropped before emit");
5650 }));
5651 }
5652
5653 {
5654 let events = events.clone();
5655 cx.subscribe_global(move |_: &(), _| {
5656 events.borrow_mut().push("before emit");
5657 })
5658 .detach();
5659 }
5660
5661 cx.emit_global(());
5662
5663 {
5664 let events = events.clone();
5665 cx.subscribe_global(move |_: &(), _| {
5666 events.borrow_mut().push("after emit");
5667 })
5668 .detach();
5669 }
5670 });
5671
5672 assert_eq!(*events.borrow(), ["before emit"]);
5673 }
5674
5675 #[crate::test(self)]
5676 fn test_global_nested_events(cx: &mut MutableAppContext) {
5677 #[derive(Clone, Debug, Eq, PartialEq)]
5678 struct GlobalEvent(u64);
5679
5680 let events = Rc::new(RefCell::new(Vec::new()));
5681
5682 {
5683 let events = events.clone();
5684 cx.subscribe_global(move |e: &GlobalEvent, cx| {
5685 events.borrow_mut().push(("Outer", e.clone()));
5686
5687 if e.0 == 1 {
5688 let events = events.clone();
5689 cx.subscribe_global(move |e: &GlobalEvent, _| {
5690 events.borrow_mut().push(("Inner", e.clone()));
5691 })
5692 .detach();
5693 }
5694 })
5695 .detach();
5696 }
5697
5698 cx.update(|cx| {
5699 cx.emit_global(GlobalEvent(1));
5700 cx.emit_global(GlobalEvent(2));
5701 cx.emit_global(GlobalEvent(3));
5702 });
5703 cx.update(|cx| {
5704 cx.emit_global(GlobalEvent(4));
5705 });
5706
5707 assert_eq!(
5708 &*events.borrow(),
5709 &[
5710 ("Outer", GlobalEvent(1)),
5711 ("Outer", GlobalEvent(2)),
5712 ("Outer", GlobalEvent(3)),
5713 ("Outer", GlobalEvent(4)),
5714 ("Inner", GlobalEvent(4)),
5715 ]
5716 );
5717 }
5718
5719 #[crate::test(self)]
5720 fn test_global(cx: &mut MutableAppContext) {
5721 type Global = usize;
5722
5723 let observation_count = Rc::new(RefCell::new(0));
5724 let subscription = cx.observe_global::<Global, _>({
5725 let observation_count = observation_count.clone();
5726 move |_, _| {
5727 *observation_count.borrow_mut() += 1;
5728 }
5729 });
5730
5731 assert!(!cx.has_global::<Global>());
5732 assert_eq!(cx.default_global::<Global>(), &0);
5733 assert_eq!(*observation_count.borrow(), 1);
5734 assert!(cx.has_global::<Global>());
5735 assert_eq!(
5736 cx.update_global::<Global, _, _>(|global, _| {
5737 *global = 1;
5738 "Update Result"
5739 }),
5740 "Update Result"
5741 );
5742 assert_eq!(*observation_count.borrow(), 2);
5743 assert_eq!(cx.global::<Global>(), &1);
5744
5745 drop(subscription);
5746 cx.update_global::<Global, _, _>(|global, _| {
5747 *global = 2;
5748 });
5749 assert_eq!(*observation_count.borrow(), 2);
5750
5751 type OtherGlobal = f32;
5752
5753 let observation_count = Rc::new(RefCell::new(0));
5754 cx.observe_global::<OtherGlobal, _>({
5755 let observation_count = observation_count.clone();
5756 move |_, _| {
5757 *observation_count.borrow_mut() += 1;
5758 }
5759 })
5760 .detach();
5761
5762 assert_eq!(
5763 cx.update_default_global::<OtherGlobal, _, _>(|global, _| {
5764 assert_eq!(global, &0.0);
5765 *global = 2.0;
5766 "Default update result"
5767 }),
5768 "Default update result"
5769 );
5770 assert_eq!(cx.global::<OtherGlobal>(), &2.0);
5771 assert_eq!(*observation_count.borrow(), 1);
5772 }
5773
5774 #[crate::test(self)]
5775 fn test_dropping_subscribers(cx: &mut MutableAppContext) {
5776 struct View;
5777
5778 impl Entity for View {
5779 type Event = ();
5780 }
5781
5782 impl super::View for View {
5783 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5784 Empty::new().boxed()
5785 }
5786
5787 fn ui_name() -> &'static str {
5788 "View"
5789 }
5790 }
5791
5792 struct Model;
5793
5794 impl Entity for Model {
5795 type Event = ();
5796 }
5797
5798 let (window_id, _) = cx.add_window(Default::default(), |_| View);
5799 let observing_view = cx.add_view(window_id, |_| View);
5800 let emitting_view = cx.add_view(window_id, |_| View);
5801 let observing_model = cx.add_model(|_| Model);
5802 let observed_model = cx.add_model(|_| Model);
5803
5804 observing_view.update(cx, |_, cx| {
5805 cx.subscribe(&emitting_view, |_, _, _, _| {}).detach();
5806 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
5807 });
5808 observing_model.update(cx, |_, cx| {
5809 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
5810 });
5811
5812 cx.update(|_| {
5813 drop(observing_view);
5814 drop(observing_model);
5815 });
5816
5817 emitting_view.update(cx, |_, cx| cx.emit(()));
5818 observed_model.update(cx, |_, cx| cx.emit(()));
5819 }
5820
5821 #[crate::test(self)]
5822 fn test_view_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
5823 #[derive(Default)]
5824 struct TestView;
5825
5826 impl Entity for TestView {
5827 type Event = ();
5828 }
5829
5830 impl View for TestView {
5831 fn ui_name() -> &'static str {
5832 "TestView"
5833 }
5834
5835 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5836 Empty::new().boxed()
5837 }
5838 }
5839
5840 let events = Rc::new(RefCell::new(Vec::new()));
5841 cx.add_window(Default::default(), |cx| {
5842 drop(cx.subscribe(&cx.handle(), {
5843 let events = events.clone();
5844 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
5845 }));
5846 cx.subscribe(&cx.handle(), {
5847 let events = events.clone();
5848 move |_, _, _, _| events.borrow_mut().push("before emit")
5849 })
5850 .detach();
5851 cx.emit(());
5852 cx.subscribe(&cx.handle(), {
5853 let events = events.clone();
5854 move |_, _, _, _| events.borrow_mut().push("after emit")
5855 })
5856 .detach();
5857 TestView
5858 });
5859 assert_eq!(*events.borrow(), ["before emit"]);
5860 }
5861
5862 #[crate::test(self)]
5863 fn test_observe_and_notify_from_view(cx: &mut MutableAppContext) {
5864 #[derive(Default)]
5865 struct View {
5866 events: Vec<usize>,
5867 }
5868
5869 impl Entity for View {
5870 type Event = usize;
5871 }
5872
5873 impl super::View for View {
5874 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5875 Empty::new().boxed()
5876 }
5877
5878 fn ui_name() -> &'static str {
5879 "View"
5880 }
5881 }
5882
5883 #[derive(Default)]
5884 struct Model {
5885 count: usize,
5886 }
5887
5888 impl Entity for Model {
5889 type Event = ();
5890 }
5891
5892 let (_, view) = cx.add_window(Default::default(), |_| View::default());
5893 let model = cx.add_model(|_| Model::default());
5894
5895 view.update(cx, |_, c| {
5896 c.observe(&model, |me, observed, c| {
5897 me.events.push(observed.read(c).count)
5898 })
5899 .detach();
5900 });
5901
5902 model.update(cx, |model, c| {
5903 model.count = 11;
5904 c.notify();
5905 });
5906 assert_eq!(view.read(cx).events, vec![11]);
5907 }
5908
5909 #[crate::test(self)]
5910 fn test_view_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
5911 #[derive(Default)]
5912 struct TestView;
5913
5914 impl Entity for TestView {
5915 type Event = ();
5916 }
5917
5918 impl View for TestView {
5919 fn ui_name() -> &'static str {
5920 "TestView"
5921 }
5922
5923 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5924 Empty::new().boxed()
5925 }
5926 }
5927
5928 let events = Rc::new(RefCell::new(Vec::new()));
5929 cx.add_window(Default::default(), |cx| {
5930 drop(cx.observe(&cx.handle(), {
5931 let events = events.clone();
5932 move |_, _, _| events.borrow_mut().push("dropped before flush")
5933 }));
5934 cx.observe(&cx.handle(), {
5935 let events = events.clone();
5936 move |_, _, _| events.borrow_mut().push("before notify")
5937 })
5938 .detach();
5939 cx.notify();
5940 cx.observe(&cx.handle(), {
5941 let events = events.clone();
5942 move |_, _, _| events.borrow_mut().push("after notify")
5943 })
5944 .detach();
5945 TestView
5946 });
5947 assert_eq!(*events.borrow(), ["before notify"]);
5948 }
5949
5950 #[crate::test(self)]
5951 fn test_dropping_observers(cx: &mut MutableAppContext) {
5952 struct View;
5953
5954 impl Entity for View {
5955 type Event = ();
5956 }
5957
5958 impl super::View for View {
5959 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5960 Empty::new().boxed()
5961 }
5962
5963 fn ui_name() -> &'static str {
5964 "View"
5965 }
5966 }
5967
5968 struct Model;
5969
5970 impl Entity for Model {
5971 type Event = ();
5972 }
5973
5974 let (window_id, _) = cx.add_window(Default::default(), |_| View);
5975 let observing_view = cx.add_view(window_id, |_| View);
5976 let observing_model = cx.add_model(|_| Model);
5977 let observed_model = cx.add_model(|_| Model);
5978
5979 observing_view.update(cx, |_, cx| {
5980 cx.observe(&observed_model, |_, _, _| {}).detach();
5981 });
5982 observing_model.update(cx, |_, cx| {
5983 cx.observe(&observed_model, |_, _, _| {}).detach();
5984 });
5985
5986 cx.update(|_| {
5987 drop(observing_view);
5988 drop(observing_model);
5989 });
5990
5991 observed_model.update(cx, |_, cx| cx.notify());
5992 }
5993
5994 #[crate::test(self)]
5995 fn test_dropping_subscriptions_during_callback(cx: &mut MutableAppContext) {
5996 struct Model;
5997
5998 impl Entity for Model {
5999 type Event = u64;
6000 }
6001
6002 // Events
6003 let observing_model = cx.add_model(|_| Model);
6004 let observed_model = cx.add_model(|_| Model);
6005
6006 let events = Rc::new(RefCell::new(Vec::new()));
6007
6008 observing_model.update(cx, |_, cx| {
6009 let events = events.clone();
6010 let subscription = Rc::new(RefCell::new(None));
6011 *subscription.borrow_mut() = Some(cx.subscribe(&observed_model, {
6012 let subscription = subscription.clone();
6013 move |_, _, e, _| {
6014 subscription.borrow_mut().take();
6015 events.borrow_mut().push(e.clone());
6016 }
6017 }));
6018 });
6019
6020 observed_model.update(cx, |_, cx| {
6021 cx.emit(1);
6022 cx.emit(2);
6023 });
6024
6025 assert_eq!(*events.borrow(), [1]);
6026
6027 // Global Events
6028 #[derive(Clone, Debug, Eq, PartialEq)]
6029 struct GlobalEvent(u64);
6030
6031 let events = Rc::new(RefCell::new(Vec::new()));
6032
6033 {
6034 let events = events.clone();
6035 let subscription = Rc::new(RefCell::new(None));
6036 *subscription.borrow_mut() = Some(cx.subscribe_global({
6037 let subscription = subscription.clone();
6038 move |e: &GlobalEvent, _| {
6039 subscription.borrow_mut().take();
6040 events.borrow_mut().push(e.clone());
6041 }
6042 }));
6043 }
6044
6045 cx.update(|cx| {
6046 cx.emit_global(GlobalEvent(1));
6047 cx.emit_global(GlobalEvent(2));
6048 });
6049
6050 assert_eq!(*events.borrow(), [GlobalEvent(1)]);
6051
6052 // Model Observation
6053 let observing_model = cx.add_model(|_| Model);
6054 let observed_model = cx.add_model(|_| Model);
6055
6056 let observation_count = Rc::new(RefCell::new(0));
6057
6058 observing_model.update(cx, |_, cx| {
6059 let observation_count = observation_count.clone();
6060 let subscription = Rc::new(RefCell::new(None));
6061 *subscription.borrow_mut() = Some(cx.observe(&observed_model, {
6062 let subscription = subscription.clone();
6063 move |_, _, _| {
6064 subscription.borrow_mut().take();
6065 *observation_count.borrow_mut() += 1;
6066 }
6067 }));
6068 });
6069
6070 observed_model.update(cx, |_, cx| {
6071 cx.notify();
6072 });
6073
6074 observed_model.update(cx, |_, cx| {
6075 cx.notify();
6076 });
6077
6078 assert_eq!(*observation_count.borrow(), 1);
6079
6080 // View Observation
6081 struct View;
6082
6083 impl Entity for View {
6084 type Event = ();
6085 }
6086
6087 impl super::View for View {
6088 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6089 Empty::new().boxed()
6090 }
6091
6092 fn ui_name() -> &'static str {
6093 "View"
6094 }
6095 }
6096
6097 let (window_id, _) = cx.add_window(Default::default(), |_| View);
6098 let observing_view = cx.add_view(window_id, |_| View);
6099 let observed_view = cx.add_view(window_id, |_| View);
6100
6101 let observation_count = Rc::new(RefCell::new(0));
6102 observing_view.update(cx, |_, cx| {
6103 let observation_count = observation_count.clone();
6104 let subscription = Rc::new(RefCell::new(None));
6105 *subscription.borrow_mut() = Some(cx.observe(&observed_view, {
6106 let subscription = subscription.clone();
6107 move |_, _, _| {
6108 subscription.borrow_mut().take();
6109 *observation_count.borrow_mut() += 1;
6110 }
6111 }));
6112 });
6113
6114 observed_view.update(cx, |_, cx| {
6115 cx.notify();
6116 });
6117
6118 observed_view.update(cx, |_, cx| {
6119 cx.notify();
6120 });
6121
6122 assert_eq!(*observation_count.borrow(), 1);
6123
6124 // Global Observation
6125 let observation_count = Rc::new(RefCell::new(0));
6126 let subscription = Rc::new(RefCell::new(None));
6127 *subscription.borrow_mut() = Some(cx.observe_global::<(), _>({
6128 let observation_count = observation_count.clone();
6129 let subscription = subscription.clone();
6130 move |_, _| {
6131 subscription.borrow_mut().take();
6132 *observation_count.borrow_mut() += 1;
6133 }
6134 }));
6135
6136 cx.default_global::<()>();
6137 cx.set_global(());
6138 assert_eq!(*observation_count.borrow(), 1);
6139 }
6140
6141 #[crate::test(self)]
6142 fn test_focus(cx: &mut MutableAppContext) {
6143 struct View {
6144 name: String,
6145 events: Arc<Mutex<Vec<String>>>,
6146 }
6147
6148 impl Entity for View {
6149 type Event = ();
6150 }
6151
6152 impl super::View for View {
6153 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6154 Empty::new().boxed()
6155 }
6156
6157 fn ui_name() -> &'static str {
6158 "View"
6159 }
6160
6161 fn on_focus(&mut self, _: &mut ViewContext<Self>) {
6162 self.events.lock().push(format!("{} focused", &self.name));
6163 }
6164
6165 fn on_blur(&mut self, _: &mut ViewContext<Self>) {
6166 self.events.lock().push(format!("{} blurred", &self.name));
6167 }
6168 }
6169
6170 let view_events: Arc<Mutex<Vec<String>>> = Default::default();
6171 let (window_id, view_1) = cx.add_window(Default::default(), |_| View {
6172 events: view_events.clone(),
6173 name: "view 1".to_string(),
6174 });
6175 let view_2 = cx.add_view(window_id, |_| View {
6176 events: view_events.clone(),
6177 name: "view 2".to_string(),
6178 });
6179
6180 let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
6181 view_1.update(cx, |_, cx| {
6182 cx.observe_focus(&view_2, {
6183 let observed_events = observed_events.clone();
6184 move |this, view, cx| {
6185 observed_events.lock().push(format!(
6186 "{} observed {}'s focus",
6187 this.name,
6188 view.read(cx).name
6189 ))
6190 }
6191 })
6192 .detach();
6193 });
6194 view_2.update(cx, |_, cx| {
6195 cx.observe_focus(&view_1, {
6196 let observed_events = observed_events.clone();
6197 move |this, view, cx| {
6198 observed_events.lock().push(format!(
6199 "{} observed {}'s focus",
6200 this.name,
6201 view.read(cx).name
6202 ))
6203 }
6204 })
6205 .detach();
6206 });
6207
6208 view_1.update(cx, |_, cx| {
6209 // Ensure only the latest focus is honored.
6210 cx.focus(&view_2);
6211 cx.focus(&view_1);
6212 cx.focus(&view_2);
6213 });
6214 view_1.update(cx, |_, cx| cx.focus(&view_1));
6215 view_1.update(cx, |_, cx| cx.focus(&view_2));
6216 view_1.update(cx, |_, _| drop(view_2));
6217
6218 assert_eq!(
6219 *view_events.lock(),
6220 [
6221 "view 1 focused".to_string(),
6222 "view 1 blurred".to_string(),
6223 "view 2 focused".to_string(),
6224 "view 2 blurred".to_string(),
6225 "view 1 focused".to_string(),
6226 "view 1 blurred".to_string(),
6227 "view 2 focused".to_string(),
6228 "view 1 focused".to_string(),
6229 ],
6230 );
6231 assert_eq!(
6232 *observed_events.lock(),
6233 [
6234 "view 1 observed view 2's focus".to_string(),
6235 "view 2 observed view 1's focus".to_string(),
6236 "view 1 observed view 2's focus".to_string(),
6237 ]
6238 );
6239 }
6240
6241 #[crate::test(self)]
6242 fn test_deserialize_actions(cx: &mut MutableAppContext) {
6243 #[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
6244 pub struct ComplexAction {
6245 arg: String,
6246 count: usize,
6247 }
6248
6249 actions!(test::something, [SimpleAction]);
6250 impl_actions!(test::something, [ComplexAction]);
6251
6252 cx.add_global_action(move |_: &SimpleAction, _: &mut MutableAppContext| {});
6253 cx.add_global_action(move |_: &ComplexAction, _: &mut MutableAppContext| {});
6254
6255 let action1 = cx
6256 .deserialize_action(
6257 "test::something::ComplexAction",
6258 Some(r#"{"arg": "a", "count": 5}"#),
6259 )
6260 .unwrap();
6261 let action2 = cx
6262 .deserialize_action("test::something::SimpleAction", None)
6263 .unwrap();
6264 assert_eq!(
6265 action1.as_any().downcast_ref::<ComplexAction>().unwrap(),
6266 &ComplexAction {
6267 arg: "a".to_string(),
6268 count: 5,
6269 }
6270 );
6271 assert_eq!(
6272 action2.as_any().downcast_ref::<SimpleAction>().unwrap(),
6273 &SimpleAction
6274 );
6275 }
6276
6277 #[crate::test(self)]
6278 fn test_dispatch_action(cx: &mut MutableAppContext) {
6279 struct ViewA {
6280 id: usize,
6281 }
6282
6283 impl Entity for ViewA {
6284 type Event = ();
6285 }
6286
6287 impl View for ViewA {
6288 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6289 Empty::new().boxed()
6290 }
6291
6292 fn ui_name() -> &'static str {
6293 "View"
6294 }
6295 }
6296
6297 struct ViewB {
6298 id: usize,
6299 }
6300
6301 impl Entity for ViewB {
6302 type Event = ();
6303 }
6304
6305 impl View for ViewB {
6306 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6307 Empty::new().boxed()
6308 }
6309
6310 fn ui_name() -> &'static str {
6311 "View"
6312 }
6313 }
6314
6315 #[derive(Clone, Default, Deserialize)]
6316 pub struct Action(pub String);
6317
6318 impl_actions!(test, [Action]);
6319
6320 let actions = Rc::new(RefCell::new(Vec::new()));
6321
6322 cx.add_global_action({
6323 let actions = actions.clone();
6324 move |_: &Action, _: &mut MutableAppContext| {
6325 actions.borrow_mut().push("global".to_string());
6326 }
6327 });
6328
6329 cx.add_action({
6330 let actions = actions.clone();
6331 move |view: &mut ViewA, action: &Action, cx| {
6332 assert_eq!(action.0, "bar");
6333 cx.propagate_action();
6334 actions.borrow_mut().push(format!("{} a", view.id));
6335 }
6336 });
6337
6338 cx.add_action({
6339 let actions = actions.clone();
6340 move |view: &mut ViewA, _: &Action, cx| {
6341 if view.id != 1 {
6342 cx.add_view(|cx| {
6343 cx.propagate_action(); // Still works on a nested ViewContext
6344 ViewB { id: 5 }
6345 });
6346 }
6347 actions.borrow_mut().push(format!("{} b", view.id));
6348 }
6349 });
6350
6351 cx.add_action({
6352 let actions = actions.clone();
6353 move |view: &mut ViewB, _: &Action, cx| {
6354 cx.propagate_action();
6355 actions.borrow_mut().push(format!("{} c", view.id));
6356 }
6357 });
6358
6359 cx.add_action({
6360 let actions = actions.clone();
6361 move |view: &mut ViewB, _: &Action, cx| {
6362 cx.propagate_action();
6363 actions.borrow_mut().push(format!("{} d", view.id));
6364 }
6365 });
6366
6367 cx.capture_action({
6368 let actions = actions.clone();
6369 move |view: &mut ViewA, _: &Action, cx| {
6370 cx.propagate_action();
6371 actions.borrow_mut().push(format!("{} capture", view.id));
6372 }
6373 });
6374
6375 let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 });
6376 let view_2 = cx.add_view(window_id, |_| ViewB { id: 2 });
6377 let view_3 = cx.add_view(window_id, |_| ViewA { id: 3 });
6378 let view_4 = cx.add_view(window_id, |_| ViewB { id: 4 });
6379
6380 let observed_actions = Rc::new(RefCell::new(Vec::new()));
6381 cx.observe_actions({
6382 let observed_actions = observed_actions.clone();
6383 move |action_id, _| observed_actions.borrow_mut().push(action_id)
6384 })
6385 .detach();
6386
6387 cx.dispatch_action(
6388 window_id,
6389 vec![view_1.id(), view_2.id(), view_3.id(), view_4.id()],
6390 &Action("bar".to_string()),
6391 );
6392
6393 assert_eq!(
6394 *actions.borrow(),
6395 vec![
6396 "1 capture",
6397 "3 capture",
6398 "4 d",
6399 "4 c",
6400 "3 b",
6401 "3 a",
6402 "2 d",
6403 "2 c",
6404 "1 b"
6405 ]
6406 );
6407 assert_eq!(*observed_actions.borrow(), [Action::default().id()]);
6408
6409 // Remove view_1, which doesn't propagate the action
6410 actions.borrow_mut().clear();
6411 cx.dispatch_action(
6412 window_id,
6413 vec![view_2.id(), view_3.id(), view_4.id()],
6414 &Action("bar".to_string()),
6415 );
6416
6417 assert_eq!(
6418 *actions.borrow(),
6419 vec![
6420 "3 capture",
6421 "4 d",
6422 "4 c",
6423 "3 b",
6424 "3 a",
6425 "2 d",
6426 "2 c",
6427 "global"
6428 ]
6429 );
6430 assert_eq!(
6431 *observed_actions.borrow(),
6432 [Action::default().id(), Action::default().id()]
6433 );
6434 }
6435
6436 #[crate::test(self)]
6437 fn test_dispatch_keystroke(cx: &mut MutableAppContext) {
6438 #[derive(Clone, Deserialize)]
6439 pub struct Action(String);
6440
6441 impl_actions!(test, [Action]);
6442
6443 struct View {
6444 id: usize,
6445 keymap_context: keymap::Context,
6446 }
6447
6448 impl Entity for View {
6449 type Event = ();
6450 }
6451
6452 impl super::View for View {
6453 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6454 Empty::new().boxed()
6455 }
6456
6457 fn ui_name() -> &'static str {
6458 "View"
6459 }
6460
6461 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
6462 self.keymap_context.clone()
6463 }
6464 }
6465
6466 impl View {
6467 fn new(id: usize) -> Self {
6468 View {
6469 id,
6470 keymap_context: keymap::Context::default(),
6471 }
6472 }
6473 }
6474
6475 let mut view_1 = View::new(1);
6476 let mut view_2 = View::new(2);
6477 let mut view_3 = View::new(3);
6478 view_1.keymap_context.set.insert("a".into());
6479 view_2.keymap_context.set.insert("a".into());
6480 view_2.keymap_context.set.insert("b".into());
6481 view_3.keymap_context.set.insert("a".into());
6482 view_3.keymap_context.set.insert("b".into());
6483 view_3.keymap_context.set.insert("c".into());
6484
6485 let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1);
6486 let view_2 = cx.add_view(window_id, |_| view_2);
6487 let view_3 = cx.add_view(window_id, |_| view_3);
6488
6489 // This keymap's only binding dispatches an action on view 2 because that view will have
6490 // "a" and "b" in its context, but not "c".
6491 cx.add_bindings(vec![keymap::Binding::new(
6492 "a",
6493 Action("a".to_string()),
6494 Some("a && b && !c"),
6495 )]);
6496
6497 cx.add_bindings(vec![keymap::Binding::new(
6498 "b",
6499 Action("b".to_string()),
6500 None,
6501 )]);
6502
6503 let actions = Rc::new(RefCell::new(Vec::new()));
6504 cx.add_action({
6505 let actions = actions.clone();
6506 move |view: &mut View, action: &Action, cx| {
6507 if action.0 == "a" {
6508 actions.borrow_mut().push(format!("{} a", view.id));
6509 } else {
6510 actions
6511 .borrow_mut()
6512 .push(format!("{} {}", view.id, action.0));
6513 cx.propagate_action();
6514 }
6515 }
6516 });
6517
6518 cx.add_global_action({
6519 let actions = actions.clone();
6520 move |action: &Action, _| {
6521 actions.borrow_mut().push(format!("global {}", action.0));
6522 }
6523 });
6524
6525 cx.dispatch_keystroke(
6526 window_id,
6527 vec![view_1.id(), view_2.id(), view_3.id()],
6528 &Keystroke::parse("a").unwrap(),
6529 );
6530
6531 assert_eq!(&*actions.borrow(), &["2 a"]);
6532
6533 actions.borrow_mut().clear();
6534 cx.dispatch_keystroke(
6535 window_id,
6536 vec![view_1.id(), view_2.id(), view_3.id()],
6537 &Keystroke::parse("b").unwrap(),
6538 );
6539
6540 assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
6541 }
6542
6543 #[crate::test(self)]
6544 async fn test_model_condition(cx: &mut TestAppContext) {
6545 struct Counter(usize);
6546
6547 impl super::Entity for Counter {
6548 type Event = ();
6549 }
6550
6551 impl Counter {
6552 fn inc(&mut self, cx: &mut ModelContext<Self>) {
6553 self.0 += 1;
6554 cx.notify();
6555 }
6556 }
6557
6558 let model = cx.add_model(|_| Counter(0));
6559
6560 let condition1 = model.condition(&cx, |model, _| model.0 == 2);
6561 let condition2 = model.condition(&cx, |model, _| model.0 == 3);
6562 smol::pin!(condition1, condition2);
6563
6564 model.update(cx, |model, cx| model.inc(cx));
6565 assert_eq!(poll_once(&mut condition1).await, None);
6566 assert_eq!(poll_once(&mut condition2).await, None);
6567
6568 model.update(cx, |model, cx| model.inc(cx));
6569 assert_eq!(poll_once(&mut condition1).await, Some(()));
6570 assert_eq!(poll_once(&mut condition2).await, None);
6571
6572 model.update(cx, |model, cx| model.inc(cx));
6573 assert_eq!(poll_once(&mut condition2).await, Some(()));
6574
6575 model.update(cx, |_, cx| cx.notify());
6576 }
6577
6578 #[crate::test(self)]
6579 #[should_panic]
6580 async fn test_model_condition_timeout(cx: &mut TestAppContext) {
6581 struct Model;
6582
6583 impl super::Entity for Model {
6584 type Event = ();
6585 }
6586
6587 let model = cx.add_model(|_| Model);
6588 model.condition(&cx, |_, _| false).await;
6589 }
6590
6591 #[crate::test(self)]
6592 #[should_panic(expected = "model dropped with pending condition")]
6593 async fn test_model_condition_panic_on_drop(cx: &mut TestAppContext) {
6594 struct Model;
6595
6596 impl super::Entity for Model {
6597 type Event = ();
6598 }
6599
6600 let model = cx.add_model(|_| Model);
6601 let condition = model.condition(&cx, |_, _| false);
6602 cx.update(|_| drop(model));
6603 condition.await;
6604 }
6605
6606 #[crate::test(self)]
6607 async fn test_view_condition(cx: &mut TestAppContext) {
6608 struct Counter(usize);
6609
6610 impl super::Entity for Counter {
6611 type Event = ();
6612 }
6613
6614 impl super::View for Counter {
6615 fn ui_name() -> &'static str {
6616 "test view"
6617 }
6618
6619 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6620 Empty::new().boxed()
6621 }
6622 }
6623
6624 impl Counter {
6625 fn inc(&mut self, cx: &mut ViewContext<Self>) {
6626 self.0 += 1;
6627 cx.notify();
6628 }
6629 }
6630
6631 let (_, view) = cx.add_window(|_| Counter(0));
6632
6633 let condition1 = view.condition(&cx, |view, _| view.0 == 2);
6634 let condition2 = view.condition(&cx, |view, _| view.0 == 3);
6635 smol::pin!(condition1, condition2);
6636
6637 view.update(cx, |view, cx| view.inc(cx));
6638 assert_eq!(poll_once(&mut condition1).await, None);
6639 assert_eq!(poll_once(&mut condition2).await, None);
6640
6641 view.update(cx, |view, cx| view.inc(cx));
6642 assert_eq!(poll_once(&mut condition1).await, Some(()));
6643 assert_eq!(poll_once(&mut condition2).await, None);
6644
6645 view.update(cx, |view, cx| view.inc(cx));
6646 assert_eq!(poll_once(&mut condition2).await, Some(()));
6647 view.update(cx, |_, cx| cx.notify());
6648 }
6649
6650 #[crate::test(self)]
6651 #[should_panic]
6652 async fn test_view_condition_timeout(cx: &mut TestAppContext) {
6653 struct View;
6654
6655 impl super::Entity for View {
6656 type Event = ();
6657 }
6658
6659 impl super::View for View {
6660 fn ui_name() -> &'static str {
6661 "test view"
6662 }
6663
6664 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6665 Empty::new().boxed()
6666 }
6667 }
6668
6669 let (_, view) = cx.add_window(|_| View);
6670 view.condition(&cx, |_, _| false).await;
6671 }
6672
6673 #[crate::test(self)]
6674 #[should_panic(expected = "view dropped with pending condition")]
6675 async fn test_view_condition_panic_on_drop(cx: &mut TestAppContext) {
6676 struct View;
6677
6678 impl super::Entity for View {
6679 type Event = ();
6680 }
6681
6682 impl super::View for View {
6683 fn ui_name() -> &'static str {
6684 "test view"
6685 }
6686
6687 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6688 Empty::new().boxed()
6689 }
6690 }
6691
6692 let window_id = cx.add_window(|_| View).0;
6693 let view = cx.add_view(window_id, |_| View);
6694
6695 let condition = view.condition(&cx, |_, _| false);
6696 cx.update(|_| drop(view));
6697 condition.await;
6698 }
6699
6700 #[crate::test(self)]
6701 fn test_refresh_windows(cx: &mut MutableAppContext) {
6702 struct View(usize);
6703
6704 impl super::Entity for View {
6705 type Event = ();
6706 }
6707
6708 impl super::View for View {
6709 fn ui_name() -> &'static str {
6710 "test view"
6711 }
6712
6713 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6714 Empty::new().named(format!("render count: {}", post_inc(&mut self.0)))
6715 }
6716 }
6717
6718 let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0));
6719 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
6720
6721 assert_eq!(
6722 presenter.borrow().rendered_views[&root_view.id()].name(),
6723 Some("render count: 0")
6724 );
6725
6726 let view = cx.add_view(window_id, |cx| {
6727 cx.refresh_windows();
6728 View(0)
6729 });
6730
6731 assert_eq!(
6732 presenter.borrow().rendered_views[&root_view.id()].name(),
6733 Some("render count: 1")
6734 );
6735 assert_eq!(
6736 presenter.borrow().rendered_views[&view.id()].name(),
6737 Some("render count: 0")
6738 );
6739
6740 cx.update(|cx| cx.refresh_windows());
6741 assert_eq!(
6742 presenter.borrow().rendered_views[&root_view.id()].name(),
6743 Some("render count: 2")
6744 );
6745 assert_eq!(
6746 presenter.borrow().rendered_views[&view.id()].name(),
6747 Some("render count: 1")
6748 );
6749
6750 cx.update(|cx| {
6751 cx.refresh_windows();
6752 drop(view);
6753 });
6754 assert_eq!(
6755 presenter.borrow().rendered_views[&root_view.id()].name(),
6756 Some("render count: 3")
6757 );
6758 assert_eq!(presenter.borrow().rendered_views.len(), 1);
6759 }
6760}