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