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