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