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