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