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