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