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