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