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