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