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