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