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