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