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