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