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