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