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