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