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