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