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