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