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