1use crate::{
2 elements::ElementBox,
3 executor::{self, Task},
4 keymap::{self, Keystroke},
5 platform::{self, CursorStyle, Platform, PromptLevel, WindowOptions},
6 presenter::Presenter,
7 util::post_inc,
8 AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache,
9};
10use anyhow::{anyhow, Result};
11use keymap::MatchResult;
12use lazy_static::lazy_static;
13use parking_lot::Mutex;
14use platform::Event;
15use postage::oneshot;
16use smol::prelude::*;
17use std::{
18 any::{type_name, Any, TypeId},
19 cell::RefCell,
20 collections::{hash_map::Entry, BTreeMap, HashMap, HashSet, VecDeque},
21 fmt::{self, Debug},
22 hash::{Hash, Hasher},
23 marker::PhantomData,
24 mem,
25 ops::{Deref, DerefMut},
26 path::{Path, PathBuf},
27 pin::Pin,
28 rc::{self, Rc},
29 sync::{
30 atomic::{AtomicUsize, Ordering::SeqCst},
31 Arc, Weak,
32 },
33 time::Duration,
34};
35
36pub trait Entity: 'static {
37 type Event;
38
39 fn release(&mut self, _: &mut MutableAppContext) {}
40 fn app_will_quit(
41 &mut self,
42 _: &mut MutableAppContext,
43 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
44 None
45 }
46}
47
48pub trait View: Entity + Sized {
49 fn ui_name() -> &'static str;
50 fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox;
51 fn on_focus(&mut self, _: &mut ViewContext<Self>) {}
52 fn on_blur(&mut self, _: &mut ViewContext<Self>) {}
53 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
54 Self::default_keymap_context()
55 }
56 fn default_keymap_context() -> keymap::Context {
57 let mut cx = keymap::Context::default();
58 cx.set.insert(Self::ui_name().into());
59 cx
60 }
61}
62
63pub trait Delegator: Entity {
64 type Delegation;
65}
66
67pub trait ReadModel {
68 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T;
69}
70
71pub trait ReadModelWith {
72 fn read_model_with<E: Entity, T>(
73 &self,
74 handle: &ModelHandle<E>,
75 read: &mut dyn FnMut(&E, &AppContext) -> T,
76 ) -> T;
77}
78
79pub trait UpdateModel {
80 fn update_model<T: Entity, O>(
81 &mut self,
82 handle: &ModelHandle<T>,
83 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
84 ) -> O;
85}
86
87pub trait UpgradeModelHandle {
88 fn upgrade_model_handle<T: Entity>(
89 &self,
90 handle: &WeakModelHandle<T>,
91 ) -> Option<ModelHandle<T>>;
92
93 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool;
94
95 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle>;
96}
97
98pub trait UpgradeViewHandle {
99 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>>;
100}
101
102pub trait ReadView {
103 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T;
104}
105
106pub trait ReadViewWith {
107 fn read_view_with<V, T>(
108 &self,
109 handle: &ViewHandle<V>,
110 read: &mut dyn FnMut(&V, &AppContext) -> T,
111 ) -> T
112 where
113 V: View;
114}
115
116pub trait UpdateView {
117 fn update_view<T, S>(
118 &mut self,
119 handle: &ViewHandle<T>,
120 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
121 ) -> S
122 where
123 T: View;
124}
125
126pub trait ElementStateContext: DerefMut<Target = MutableAppContext> {
127 fn current_view_id(&self) -> usize;
128
129 fn element_state<Tag: 'static, T: 'static + Default>(
130 &mut self,
131 element_id: usize,
132 ) -> ElementStateHandle<T> {
133 let id = ElementStateId {
134 view_id: self.current_view_id(),
135 element_id,
136 tag: TypeId::of::<Tag>(),
137 };
138 self.cx
139 .element_states
140 .entry(id)
141 .or_insert_with(|| Box::new(T::default()));
142 ElementStateHandle::new(id, self.frame_count, &self.cx.ref_counts)
143 }
144}
145
146pub trait Action: 'static + AnyAction {
147 type Argument: 'static + Clone;
148}
149
150pub trait AnyAction {
151 fn id(&self) -> TypeId;
152 fn name(&self) -> &'static str;
153 fn as_any(&self) -> &dyn Any;
154 fn boxed_clone(&self) -> Box<dyn AnyAction>;
155 fn boxed_clone_as_any(&self) -> Box<dyn Any>;
156}
157
158#[macro_export]
159macro_rules! action {
160 ($name:ident, $arg:ty) => {
161 #[derive(Clone)]
162 pub struct $name(pub $arg);
163
164 impl $crate::Action for $name {
165 type Argument = $arg;
166 }
167
168 impl $crate::AnyAction for $name {
169 fn id(&self) -> std::any::TypeId {
170 std::any::TypeId::of::<$name>()
171 }
172
173 fn name(&self) -> &'static str {
174 stringify!($name)
175 }
176
177 fn as_any(&self) -> &dyn std::any::Any {
178 self
179 }
180
181 fn boxed_clone(&self) -> Box<dyn $crate::AnyAction> {
182 Box::new(self.clone())
183 }
184
185 fn boxed_clone_as_any(&self) -> Box<dyn std::any::Any> {
186 Box::new(self.clone())
187 }
188 }
189 };
190
191 ($name:ident) => {
192 #[derive(Clone, Debug, Eq, PartialEq)]
193 pub struct $name;
194
195 impl $crate::Action for $name {
196 type Argument = ();
197 }
198
199 impl $crate::AnyAction for $name {
200 fn id(&self) -> std::any::TypeId {
201 std::any::TypeId::of::<$name>()
202 }
203
204 fn name(&self) -> &'static str {
205 stringify!($name)
206 }
207
208 fn as_any(&self) -> &dyn std::any::Any {
209 self
210 }
211
212 fn boxed_clone(&self) -> Box<dyn $crate::AnyAction> {
213 Box::new(self.clone())
214 }
215
216 fn boxed_clone_as_any(&self) -> Box<dyn std::any::Any> {
217 Box::new(self.clone())
218 }
219 }
220 };
221}
222
223pub struct Menu<'a> {
224 pub name: &'a str,
225 pub items: Vec<MenuItem<'a>>,
226}
227
228pub enum MenuItem<'a> {
229 Action {
230 name: &'a str,
231 keystroke: Option<&'a str>,
232 action: Box<dyn AnyAction>,
233 },
234 Separator,
235}
236
237#[derive(Clone)]
238pub struct App(Rc<RefCell<MutableAppContext>>);
239
240#[derive(Clone)]
241pub struct AsyncAppContext(Rc<RefCell<MutableAppContext>>);
242
243#[cfg(any(test, feature = "test-support"))]
244pub struct TestAppContext {
245 cx: Rc<RefCell<MutableAppContext>>,
246 foreground_platform: Rc<platform::test::ForegroundPlatform>,
247}
248
249impl App {
250 pub fn new(asset_source: impl AssetSource) -> Result<Self> {
251 let platform = platform::current::platform();
252 let foreground_platform = platform::current::foreground_platform();
253 let foreground = Rc::new(executor::Foreground::platform(platform.dispatcher())?);
254 let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
255 foreground,
256 Arc::new(executor::Background::new()),
257 platform.clone(),
258 foreground_platform.clone(),
259 Arc::new(FontCache::new(platform.fonts())),
260 Default::default(),
261 asset_source,
262 ))));
263
264 foreground_platform.on_quit(Box::new({
265 let cx = app.0.clone();
266 move || {
267 cx.borrow_mut().quit();
268 }
269 }));
270 foreground_platform.on_menu_command(Box::new({
271 let cx = app.0.clone();
272 move |action| {
273 let mut cx = cx.borrow_mut();
274 if let Some(key_window_id) = cx.cx.platform.key_window_id() {
275 if let Some((presenter, _)) =
276 cx.presenters_and_platform_windows.get(&key_window_id)
277 {
278 let presenter = presenter.clone();
279 let path = presenter.borrow().dispatch_path(cx.as_ref());
280 cx.dispatch_action_any(key_window_id, &path, action);
281 } else {
282 cx.dispatch_global_action_any(action);
283 }
284 } else {
285 cx.dispatch_global_action_any(action);
286 }
287 }
288 }));
289
290 app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
291 Ok(app)
292 }
293
294 pub fn background(&self) -> Arc<executor::Background> {
295 self.0.borrow().background().clone()
296 }
297
298 pub fn on_become_active<F>(self, mut callback: F) -> Self
299 where
300 F: 'static + FnMut(&mut MutableAppContext),
301 {
302 let cx = self.0.clone();
303 self.0
304 .borrow_mut()
305 .foreground_platform
306 .on_become_active(Box::new(move || callback(&mut *cx.borrow_mut())));
307 self
308 }
309
310 pub fn on_resign_active<F>(self, mut callback: F) -> Self
311 where
312 F: 'static + FnMut(&mut MutableAppContext),
313 {
314 let cx = self.0.clone();
315 self.0
316 .borrow_mut()
317 .foreground_platform
318 .on_resign_active(Box::new(move || callback(&mut *cx.borrow_mut())));
319 self
320 }
321
322 pub fn on_quit<F>(self, mut callback: F) -> Self
323 where
324 F: 'static + FnMut(&mut MutableAppContext),
325 {
326 let cx = self.0.clone();
327 self.0
328 .borrow_mut()
329 .foreground_platform
330 .on_quit(Box::new(move || callback(&mut *cx.borrow_mut())));
331 self
332 }
333
334 pub fn on_event<F>(self, mut callback: F) -> Self
335 where
336 F: 'static + FnMut(Event, &mut MutableAppContext) -> bool,
337 {
338 let cx = self.0.clone();
339 self.0
340 .borrow_mut()
341 .foreground_platform
342 .on_event(Box::new(move |event| {
343 callback(event, &mut *cx.borrow_mut())
344 }));
345 self
346 }
347
348 pub fn on_open_files<F>(self, mut callback: F) -> Self
349 where
350 F: 'static + FnMut(Vec<PathBuf>, &mut MutableAppContext),
351 {
352 let cx = self.0.clone();
353 self.0
354 .borrow_mut()
355 .foreground_platform
356 .on_open_files(Box::new(move |paths| {
357 callback(paths, &mut *cx.borrow_mut())
358 }));
359 self
360 }
361
362 pub fn run<F>(self, on_finish_launching: F)
363 where
364 F: 'static + FnOnce(&mut MutableAppContext),
365 {
366 let platform = self.0.borrow().foreground_platform.clone();
367 platform.run(Box::new(move || {
368 let mut cx = self.0.borrow_mut();
369 let cx = &mut *cx;
370 crate::views::init(cx);
371 on_finish_launching(cx);
372 }))
373 }
374
375 pub fn platform(&self) -> Arc<dyn Platform> {
376 self.0.borrow().platform()
377 }
378
379 pub fn font_cache(&self) -> Arc<FontCache> {
380 self.0.borrow().cx.font_cache.clone()
381 }
382
383 fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
384 let mut state = self.0.borrow_mut();
385 let result = state.update(callback);
386 state.pending_notifications.clear();
387 result
388 }
389}
390
391#[cfg(any(test, feature = "test-support"))]
392impl TestAppContext {
393 pub fn new(
394 foreground_platform: Rc<platform::test::ForegroundPlatform>,
395 platform: Arc<dyn Platform>,
396 foreground: Rc<executor::Foreground>,
397 background: Arc<executor::Background>,
398 font_cache: Arc<FontCache>,
399 leak_detector: Arc<Mutex<LeakDetector>>,
400 first_entity_id: usize,
401 ) -> Self {
402 let mut cx = MutableAppContext::new(
403 foreground.clone(),
404 background,
405 platform,
406 foreground_platform.clone(),
407 font_cache,
408 RefCounts {
409 #[cfg(any(test, feature = "test-support"))]
410 leak_detector,
411 ..Default::default()
412 },
413 (),
414 );
415 cx.next_entity_id = first_entity_id;
416 let cx = TestAppContext {
417 cx: Rc::new(RefCell::new(cx)),
418 foreground_platform,
419 };
420 cx.cx.borrow_mut().weak_self = Some(Rc::downgrade(&cx.cx));
421 cx
422 }
423
424 pub fn dispatch_action<A: Action>(
425 &self,
426 window_id: usize,
427 responder_chain: Vec<usize>,
428 action: A,
429 ) {
430 self.cx
431 .borrow_mut()
432 .dispatch_action_any(window_id, &responder_chain, &action);
433 }
434
435 pub fn dispatch_global_action<A: Action>(&self, action: A) {
436 self.cx.borrow_mut().dispatch_global_action(action);
437 }
438
439 pub fn dispatch_keystroke(
440 &self,
441 window_id: usize,
442 responder_chain: Vec<usize>,
443 keystroke: &Keystroke,
444 ) -> Result<bool> {
445 let mut state = self.cx.borrow_mut();
446 state.dispatch_keystroke(window_id, responder_chain, keystroke)
447 }
448
449 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
450 where
451 T: Entity,
452 F: FnOnce(&mut ModelContext<T>) -> T,
453 {
454 self.cx.borrow_mut().add_model(build_model)
455 }
456
457 pub fn add_window<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>)
458 where
459 T: View,
460 F: FnOnce(&mut ViewContext<T>) -> T,
461 {
462 self.cx
463 .borrow_mut()
464 .add_window(Default::default(), build_root_view)
465 }
466
467 pub fn window_ids(&self) -> Vec<usize> {
468 self.cx.borrow().window_ids().collect()
469 }
470
471 pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
472 self.cx.borrow().root_view(window_id)
473 }
474
475 pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
476 where
477 T: View,
478 F: FnOnce(&mut ViewContext<T>) -> T,
479 {
480 self.cx.borrow_mut().add_view(window_id, build_view)
481 }
482
483 pub fn add_option_view<T, F>(
484 &mut self,
485 window_id: usize,
486 build_view: F,
487 ) -> Option<ViewHandle<T>>
488 where
489 T: View,
490 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
491 {
492 self.cx.borrow_mut().add_option_view(window_id, build_view)
493 }
494
495 pub fn read<T, F: FnOnce(&AppContext) -> T>(&self, callback: F) -> T {
496 callback(self.cx.borrow().as_ref())
497 }
498
499 pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
500 let mut state = self.cx.borrow_mut();
501 // Don't increment pending flushes in order to effects to be flushed before the callback
502 // completes, which is helpful in tests.
503 let result = callback(&mut *state);
504 // Flush effects after the callback just in case there are any. This can happen in edge
505 // cases such as the closure dropping handles.
506 state.flush_effects();
507 result
508 }
509
510 pub fn to_async(&self) -> AsyncAppContext {
511 AsyncAppContext(self.cx.clone())
512 }
513
514 pub fn font_cache(&self) -> Arc<FontCache> {
515 self.cx.borrow().cx.font_cache.clone()
516 }
517
518 pub fn foreground_platform(&self) -> Rc<platform::test::ForegroundPlatform> {
519 self.foreground_platform.clone()
520 }
521
522 pub fn platform(&self) -> Arc<dyn platform::Platform> {
523 self.cx.borrow().cx.platform.clone()
524 }
525
526 pub fn foreground(&self) -> Rc<executor::Foreground> {
527 self.cx.borrow().foreground().clone()
528 }
529
530 pub fn background(&self) -> Arc<executor::Background> {
531 self.cx.borrow().background().clone()
532 }
533
534 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
535 where
536 F: FnOnce(AsyncAppContext) -> Fut,
537 Fut: 'static + Future<Output = T>,
538 T: 'static,
539 {
540 self.cx.borrow_mut().spawn(f)
541 }
542
543 pub fn simulate_new_path_selection(&self, result: impl FnOnce(PathBuf) -> Option<PathBuf>) {
544 self.foreground_platform.simulate_new_path_selection(result);
545 }
546
547 pub fn did_prompt_for_new_path(&self) -> bool {
548 self.foreground_platform.as_ref().did_prompt_for_new_path()
549 }
550
551 pub fn simulate_prompt_answer(&self, window_id: usize, answer: usize) {
552 use postage::prelude::Sink as _;
553
554 let mut state = self.cx.borrow_mut();
555 let (_, window) = state
556 .presenters_and_platform_windows
557 .get_mut(&window_id)
558 .unwrap();
559 let test_window = window
560 .as_any_mut()
561 .downcast_mut::<platform::test::Window>()
562 .unwrap();
563 let mut done_tx = test_window
564 .last_prompt
565 .take()
566 .expect("prompt was not called");
567 let _ = done_tx.try_send(answer);
568 }
569
570 #[cfg(any(test, feature = "test-support"))]
571 pub fn leak_detector(&self) -> Arc<Mutex<LeakDetector>> {
572 self.cx.borrow().leak_detector()
573 }
574}
575
576impl AsyncAppContext {
577 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
578 where
579 F: FnOnce(AsyncAppContext) -> Fut,
580 Fut: 'static + Future<Output = T>,
581 T: 'static,
582 {
583 self.0.borrow().foreground.spawn(f(self.clone()))
584 }
585
586 pub fn read<T, F: FnOnce(&AppContext) -> T>(&mut self, callback: F) -> T {
587 callback(self.0.borrow().as_ref())
588 }
589
590 pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
591 self.0.borrow_mut().update(callback)
592 }
593
594 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
595 where
596 T: Entity,
597 F: FnOnce(&mut ModelContext<T>) -> T,
598 {
599 self.update(|cx| cx.add_model(build_model))
600 }
601
602 pub fn platform(&self) -> Arc<dyn Platform> {
603 self.0.borrow().platform()
604 }
605
606 pub fn foreground(&self) -> Rc<executor::Foreground> {
607 self.0.borrow().foreground.clone()
608 }
609
610 pub fn background(&self) -> Arc<executor::Background> {
611 self.0.borrow().cx.background.clone()
612 }
613}
614
615impl UpdateModel for AsyncAppContext {
616 fn update_model<E: Entity, O>(
617 &mut self,
618 handle: &ModelHandle<E>,
619 update: &mut dyn FnMut(&mut E, &mut ModelContext<E>) -> O,
620 ) -> O {
621 self.0.borrow_mut().update_model(handle, update)
622 }
623}
624
625impl UpgradeModelHandle for AsyncAppContext {
626 fn upgrade_model_handle<T: Entity>(
627 &self,
628 handle: &WeakModelHandle<T>,
629 ) -> Option<ModelHandle<T>> {
630 self.0.borrow().upgrade_model_handle(handle)
631 }
632
633 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
634 self.0.borrow().model_handle_is_upgradable(handle)
635 }
636
637 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
638 self.0.borrow().upgrade_any_model_handle(handle)
639 }
640}
641
642impl UpgradeViewHandle for AsyncAppContext {
643 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
644 self.0.borrow_mut().upgrade_view_handle(handle)
645 }
646}
647
648impl ReadModelWith for AsyncAppContext {
649 fn read_model_with<E: Entity, T>(
650 &self,
651 handle: &ModelHandle<E>,
652 read: &mut dyn FnMut(&E, &AppContext) -> T,
653 ) -> T {
654 let cx = self.0.borrow();
655 let cx = cx.as_ref();
656 read(handle.read(cx), cx)
657 }
658}
659
660impl UpdateView for AsyncAppContext {
661 fn update_view<T, S>(
662 &mut self,
663 handle: &ViewHandle<T>,
664 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
665 ) -> S
666 where
667 T: View,
668 {
669 self.0.borrow_mut().update_view(handle, update)
670 }
671}
672
673impl ReadViewWith for AsyncAppContext {
674 fn read_view_with<V, T>(
675 &self,
676 handle: &ViewHandle<V>,
677 read: &mut dyn FnMut(&V, &AppContext) -> T,
678 ) -> T
679 where
680 V: View,
681 {
682 let cx = self.0.borrow();
683 let cx = cx.as_ref();
684 read(handle.read(cx), cx)
685 }
686}
687
688#[cfg(any(test, feature = "test-support"))]
689impl UpdateModel for TestAppContext {
690 fn update_model<T: Entity, O>(
691 &mut self,
692 handle: &ModelHandle<T>,
693 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
694 ) -> O {
695 self.cx.borrow_mut().update_model(handle, update)
696 }
697}
698
699#[cfg(any(test, feature = "test-support"))]
700impl ReadModelWith for TestAppContext {
701 fn read_model_with<E: Entity, T>(
702 &self,
703 handle: &ModelHandle<E>,
704 read: &mut dyn FnMut(&E, &AppContext) -> T,
705 ) -> T {
706 let cx = self.cx.borrow();
707 let cx = cx.as_ref();
708 read(handle.read(cx), cx)
709 }
710}
711
712#[cfg(any(test, feature = "test-support"))]
713impl UpdateView for TestAppContext {
714 fn update_view<T, S>(
715 &mut self,
716 handle: &ViewHandle<T>,
717 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
718 ) -> S
719 where
720 T: View,
721 {
722 self.cx.borrow_mut().update_view(handle, update)
723 }
724}
725
726#[cfg(any(test, feature = "test-support"))]
727impl ReadViewWith for TestAppContext {
728 fn read_view_with<V, T>(
729 &self,
730 handle: &ViewHandle<V>,
731 read: &mut dyn FnMut(&V, &AppContext) -> T,
732 ) -> T
733 where
734 V: View,
735 {
736 let cx = self.cx.borrow();
737 let cx = cx.as_ref();
738 read(handle.read(cx), cx)
739 }
740}
741
742type ActionCallback =
743 dyn FnMut(&mut dyn AnyView, &dyn AnyAction, &mut MutableAppContext, usize, usize);
744type GlobalActionCallback = dyn FnMut(&dyn AnyAction, &mut MutableAppContext);
745
746type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext) -> bool>;
747type DelegationCallback = Box<dyn FnMut(Box<dyn Any>, &mut MutableAppContext) -> bool>;
748type ObservationCallback = Box<dyn FnMut(&mut MutableAppContext) -> bool>;
749type ReleaseObservationCallback = Box<dyn FnMut(&mut MutableAppContext)>;
750
751pub struct MutableAppContext {
752 weak_self: Option<rc::Weak<RefCell<Self>>>,
753 foreground_platform: Rc<dyn platform::ForegroundPlatform>,
754 assets: Arc<AssetCache>,
755 cx: AppContext,
756 capture_actions: HashMap<TypeId, HashMap<TypeId, Vec<Box<ActionCallback>>>>,
757 actions: HashMap<TypeId, HashMap<TypeId, Vec<Box<ActionCallback>>>>,
758 global_actions: HashMap<TypeId, Box<GlobalActionCallback>>,
759 keystroke_matcher: keymap::Matcher,
760 next_entity_id: usize,
761 next_window_id: usize,
762 next_subscription_id: usize,
763 frame_count: usize,
764 subscriptions: Arc<Mutex<HashMap<usize, BTreeMap<usize, SubscriptionCallback>>>>,
765 delegations: Arc<Mutex<HashMap<usize, (usize, DelegationCallback)>>>,
766 observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ObservationCallback>>>>,
767 release_observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>,
768 presenters_and_platform_windows:
769 HashMap<usize, (Rc<RefCell<Presenter>>, Box<dyn platform::Window>)>,
770 foreground: Rc<executor::Foreground>,
771 pending_effects: VecDeque<Effect>,
772 pending_notifications: HashSet<usize>,
773 pending_flushes: usize,
774 flushing_effects: bool,
775 next_cursor_style_handle_id: Arc<AtomicUsize>,
776 halt_action_dispatch: bool,
777}
778
779impl MutableAppContext {
780 fn new(
781 foreground: Rc<executor::Foreground>,
782 background: Arc<executor::Background>,
783 platform: Arc<dyn platform::Platform>,
784 foreground_platform: Rc<dyn platform::ForegroundPlatform>,
785 font_cache: Arc<FontCache>,
786 ref_counts: RefCounts,
787 asset_source: impl AssetSource,
788 ) -> Self {
789 Self {
790 weak_self: None,
791 foreground_platform,
792 assets: Arc::new(AssetCache::new(asset_source)),
793 cx: AppContext {
794 models: Default::default(),
795 views: Default::default(),
796 windows: Default::default(),
797 app_states: Default::default(),
798 element_states: Default::default(),
799 ref_counts: Arc::new(Mutex::new(ref_counts)),
800 background,
801 font_cache,
802 platform,
803 },
804 capture_actions: HashMap::new(),
805 actions: HashMap::new(),
806 global_actions: HashMap::new(),
807 keystroke_matcher: keymap::Matcher::default(),
808 next_entity_id: 0,
809 next_window_id: 0,
810 next_subscription_id: 0,
811 frame_count: 0,
812 subscriptions: Default::default(),
813 delegations: Default::default(),
814 observations: Default::default(),
815 release_observations: Default::default(),
816 presenters_and_platform_windows: HashMap::new(),
817 foreground,
818 pending_effects: VecDeque::new(),
819 pending_notifications: HashSet::new(),
820 pending_flushes: 0,
821 flushing_effects: false,
822 next_cursor_style_handle_id: Default::default(),
823 halt_action_dispatch: false,
824 }
825 }
826
827 pub fn upgrade(&self) -> App {
828 App(self.weak_self.as_ref().unwrap().upgrade().unwrap())
829 }
830
831 pub fn quit(&mut self) {
832 let mut futures = Vec::new();
833 for model_id in self.cx.models.keys().copied().collect::<Vec<_>>() {
834 let mut model = self.cx.models.remove(&model_id).unwrap();
835 futures.extend(model.app_will_quit(self));
836 self.cx.models.insert(model_id, model);
837 }
838
839 for view_id in self.cx.views.keys().copied().collect::<Vec<_>>() {
840 let mut view = self.cx.views.remove(&view_id).unwrap();
841 futures.extend(view.app_will_quit(self));
842 self.cx.views.insert(view_id, view);
843 }
844
845 self.remove_all_windows();
846
847 let futures = futures::future::join_all(futures);
848 if self
849 .background
850 .block_with_timeout(Duration::from_millis(100), futures)
851 .is_err()
852 {
853 log::error!("timed out waiting on app_will_quit");
854 }
855 }
856
857 pub fn remove_all_windows(&mut self) {
858 for (window_id, _) in self.cx.windows.drain() {
859 self.presenters_and_platform_windows.remove(&window_id);
860 }
861 self.flush_effects();
862 }
863
864 pub fn platform(&self) -> Arc<dyn platform::Platform> {
865 self.cx.platform.clone()
866 }
867
868 pub fn font_cache(&self) -> &Arc<FontCache> {
869 &self.cx.font_cache
870 }
871
872 pub fn foreground(&self) -> &Rc<executor::Foreground> {
873 &self.foreground
874 }
875
876 pub fn background(&self) -> &Arc<executor::Background> {
877 &self.cx.background
878 }
879
880 pub fn debug_elements(&self, window_id: usize) -> Option<crate::json::Value> {
881 self.presenters_and_platform_windows
882 .get(&window_id)
883 .and_then(|(presenter, _)| presenter.borrow().debug_elements(self))
884 }
885
886 pub fn add_action<A, V, F>(&mut self, handler: F)
887 where
888 A: Action,
889 V: View,
890 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>),
891 {
892 self.add_action_internal(handler, false)
893 }
894
895 pub fn capture_action<A, V, F>(&mut self, handler: F)
896 where
897 A: Action,
898 V: View,
899 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>),
900 {
901 self.add_action_internal(handler, true)
902 }
903
904 fn add_action_internal<A, V, F>(&mut self, mut handler: F, capture: bool)
905 where
906 A: Action,
907 V: View,
908 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>),
909 {
910 let handler = Box::new(
911 move |view: &mut dyn AnyView,
912 action: &dyn AnyAction,
913 cx: &mut MutableAppContext,
914 window_id: usize,
915 view_id: usize| {
916 let action = action.as_any().downcast_ref().unwrap();
917 let mut cx = ViewContext::new(cx, window_id, view_id);
918 handler(
919 view.as_any_mut()
920 .downcast_mut()
921 .expect("downcast is type safe"),
922 action,
923 &mut cx,
924 );
925 },
926 );
927
928 let actions = if capture {
929 &mut self.capture_actions
930 } else {
931 &mut self.actions
932 };
933
934 actions
935 .entry(TypeId::of::<V>())
936 .or_default()
937 .entry(TypeId::of::<A>())
938 .or_default()
939 .push(handler);
940 }
941
942 pub fn add_async_action<A, V, F>(&mut self, mut handler: F)
943 where
944 A: Action,
945 V: View,
946 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>) -> Option<Task<Result<()>>>,
947 {
948 self.add_action(move |view, action, cx| {
949 handler(view, action, cx).map(|task| task.detach_and_log_err(cx));
950 })
951 }
952
953 pub fn add_global_action<A, F>(&mut self, mut handler: F)
954 where
955 A: Action,
956 F: 'static + FnMut(&A, &mut MutableAppContext),
957 {
958 let handler = Box::new(move |action: &dyn AnyAction, cx: &mut MutableAppContext| {
959 let action = action.as_any().downcast_ref().unwrap();
960 handler(action, cx);
961 });
962
963 if self
964 .global_actions
965 .insert(TypeId::of::<A>(), handler)
966 .is_some()
967 {
968 panic!("registered multiple global handlers for the same action type");
969 }
970 }
971
972 pub fn window_ids(&self) -> impl Iterator<Item = usize> + '_ {
973 self.cx.windows.keys().cloned()
974 }
975
976 pub fn activate_window(&self, window_id: usize) {
977 if let Some((_, window)) = self.presenters_and_platform_windows.get(&window_id) {
978 window.activate()
979 }
980 }
981
982 pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
983 self.cx
984 .windows
985 .get(&window_id)
986 .and_then(|window| window.root_view.clone().downcast::<T>())
987 }
988
989 pub fn render_view(
990 &mut self,
991 window_id: usize,
992 view_id: usize,
993 titlebar_height: f32,
994 refreshing: bool,
995 ) -> Result<ElementBox> {
996 let mut view = self
997 .cx
998 .views
999 .remove(&(window_id, view_id))
1000 .ok_or(anyhow!("view not found"))?;
1001 let element = view.render(window_id, view_id, titlebar_height, refreshing, self);
1002 self.cx.views.insert((window_id, view_id), view);
1003 Ok(element)
1004 }
1005
1006 pub fn render_views(
1007 &mut self,
1008 window_id: usize,
1009 titlebar_height: f32,
1010 ) -> HashMap<usize, ElementBox> {
1011 self.start_frame();
1012 let view_ids = self
1013 .views
1014 .keys()
1015 .filter_map(|(win_id, view_id)| {
1016 if *win_id == window_id {
1017 Some(*view_id)
1018 } else {
1019 None
1020 }
1021 })
1022 .collect::<Vec<_>>();
1023 view_ids
1024 .into_iter()
1025 .map(|view_id| {
1026 (
1027 view_id,
1028 self.render_view(window_id, view_id, titlebar_height, false)
1029 .unwrap(),
1030 )
1031 })
1032 .collect()
1033 }
1034
1035 pub(crate) fn start_frame(&mut self) {
1036 self.frame_count += 1;
1037 }
1038
1039 pub fn update<T, F: FnOnce(&mut Self) -> T>(&mut self, callback: F) -> T {
1040 self.pending_flushes += 1;
1041 let result = callback(self);
1042 self.flush_effects();
1043 result
1044 }
1045
1046 pub fn set_menus(&mut self, menus: Vec<Menu>) {
1047 self.foreground_platform.set_menus(menus);
1048 }
1049
1050 fn prompt(
1051 &self,
1052 window_id: usize,
1053 level: PromptLevel,
1054 msg: &str,
1055 answers: &[&str],
1056 ) -> oneshot::Receiver<usize> {
1057 let (_, window) = &self.presenters_and_platform_windows[&window_id];
1058 window.prompt(level, msg, answers)
1059 }
1060
1061 pub fn prompt_for_paths(
1062 &self,
1063 options: PathPromptOptions,
1064 ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
1065 self.foreground_platform.prompt_for_paths(options)
1066 }
1067
1068 pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
1069 self.foreground_platform.prompt_for_new_path(directory)
1070 }
1071
1072 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1073 where
1074 E: Entity,
1075 E::Event: 'static,
1076 H: Handle<E>,
1077 F: 'static + FnMut(H, &E::Event, &mut Self),
1078 {
1079 self.subscribe_internal(handle, move |handle, event, cx| {
1080 callback(handle, event, cx);
1081 true
1082 })
1083 }
1084
1085 pub fn observe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1086 where
1087 E: Entity,
1088 E::Event: 'static,
1089 H: Handle<E>,
1090 F: 'static + FnMut(H, &mut Self),
1091 {
1092 self.observe_internal(handle, move |handle, cx| {
1093 callback(handle, cx);
1094 true
1095 })
1096 }
1097
1098 pub fn subscribe_internal<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1099 where
1100 E: Entity,
1101 E::Event: 'static,
1102 H: Handle<E>,
1103 F: 'static + FnMut(H, &E::Event, &mut Self) -> bool,
1104 {
1105 let id = post_inc(&mut self.next_subscription_id);
1106 let emitter = handle.downgrade();
1107 self.subscriptions
1108 .lock()
1109 .entry(handle.id())
1110 .or_default()
1111 .insert(
1112 id,
1113 Box::new(move |payload, cx| {
1114 if let Some(emitter) = H::upgrade_from(&emitter, cx.as_ref()) {
1115 let payload = payload.downcast_ref().expect("downcast is type safe");
1116 callback(emitter, payload, cx)
1117 } else {
1118 false
1119 }
1120 }),
1121 );
1122 Subscription::Subscription {
1123 id,
1124 entity_id: handle.id(),
1125 subscriptions: Some(Arc::downgrade(&self.subscriptions)),
1126 }
1127 }
1128
1129 fn observe_internal<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1130 where
1131 E: Entity,
1132 E::Event: 'static,
1133 H: Handle<E>,
1134 F: 'static + FnMut(H, &mut Self) -> bool,
1135 {
1136 let id = post_inc(&mut self.next_subscription_id);
1137 let observed = handle.downgrade();
1138 self.observations
1139 .lock()
1140 .entry(handle.id())
1141 .or_default()
1142 .insert(
1143 id,
1144 Box::new(move |cx| {
1145 if let Some(observed) = H::upgrade_from(&observed, cx) {
1146 callback(observed, cx)
1147 } else {
1148 false
1149 }
1150 }),
1151 );
1152 Subscription::Observation {
1153 id,
1154 entity_id: handle.id(),
1155 observations: Some(Arc::downgrade(&self.observations)),
1156 }
1157 }
1158
1159 pub fn become_delegate_internal<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1160 where
1161 E: Entity,
1162 E::Event: 'static,
1163 H: Handle<E>,
1164 F: 'static + FnMut(H, &E::Event, &mut Self) -> bool,
1165 {
1166 let id = post_inc(&mut self.next_subscription_id);
1167 let emitter = handle.downgrade();
1168 self.subscriptions
1169 .lock()
1170 .entry(handle.id())
1171 .or_default()
1172 .insert(
1173 id,
1174 Box::new(move |payload, cx| {
1175 if let Some(emitter) = H::upgrade_from(&emitter, cx.as_ref()) {
1176 let payload = payload.downcast_ref().expect("downcast is type safe");
1177 callback(emitter, payload, cx)
1178 } else {
1179 false
1180 }
1181 }),
1182 );
1183 Subscription::Subscription {
1184 id,
1185 entity_id: handle.id(),
1186 subscriptions: Some(Arc::downgrade(&self.subscriptions)),
1187 }
1188 }
1189
1190 pub fn observe_release<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1191 where
1192 E: Entity,
1193 E::Event: 'static,
1194 H: Handle<E>,
1195 F: 'static + FnMut(&mut Self),
1196 {
1197 let id = post_inc(&mut self.next_subscription_id);
1198 self.release_observations
1199 .lock()
1200 .entry(handle.id())
1201 .or_default()
1202 .insert(id, Box::new(move |cx| callback(cx)));
1203 Subscription::ReleaseObservation {
1204 id,
1205 entity_id: handle.id(),
1206 observations: Some(Arc::downgrade(&self.release_observations)),
1207 }
1208 }
1209
1210 fn defer(&mut self, callback: Box<dyn FnOnce(&mut MutableAppContext)>) {
1211 self.pending_effects.push_back(Effect::Deferred(callback))
1212 }
1213
1214 pub(crate) fn notify_model(&mut self, model_id: usize) {
1215 if self.pending_notifications.insert(model_id) {
1216 self.pending_effects
1217 .push_back(Effect::ModelNotification { model_id });
1218 }
1219 }
1220
1221 pub(crate) fn notify_view(&mut self, window_id: usize, view_id: usize) {
1222 if self.pending_notifications.insert(view_id) {
1223 self.pending_effects
1224 .push_back(Effect::ViewNotification { window_id, view_id });
1225 }
1226 }
1227
1228 pub fn dispatch_action<A: Action>(
1229 &mut self,
1230 window_id: usize,
1231 responder_chain: Vec<usize>,
1232 action: &A,
1233 ) {
1234 self.dispatch_action_any(window_id, &responder_chain, action);
1235 }
1236
1237 pub(crate) fn dispatch_action_any(
1238 &mut self,
1239 window_id: usize,
1240 path: &[usize],
1241 action: &dyn AnyAction,
1242 ) -> bool {
1243 self.update(|this| {
1244 this.halt_action_dispatch = false;
1245 for (capture_phase, view_id) in path
1246 .iter()
1247 .map(|view_id| (true, *view_id))
1248 .chain(path.iter().rev().map(|view_id| (false, *view_id)))
1249 {
1250 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
1251 let type_id = view.as_any().type_id();
1252
1253 if let Some((name, mut handlers)) = this
1254 .actions_mut(capture_phase)
1255 .get_mut(&type_id)
1256 .and_then(|h| h.remove_entry(&action.id()))
1257 {
1258 for handler in handlers.iter_mut().rev() {
1259 this.halt_action_dispatch = true;
1260 handler(view.as_mut(), action, this, window_id, view_id);
1261 if this.halt_action_dispatch {
1262 break;
1263 }
1264 }
1265 this.actions_mut(capture_phase)
1266 .get_mut(&type_id)
1267 .unwrap()
1268 .insert(name, handlers);
1269 }
1270
1271 this.cx.views.insert((window_id, view_id), view);
1272
1273 if this.halt_action_dispatch {
1274 break;
1275 }
1276 }
1277 }
1278
1279 if !this.halt_action_dispatch {
1280 this.halt_action_dispatch = this.dispatch_global_action_any(action);
1281 }
1282 this.halt_action_dispatch
1283 })
1284 }
1285
1286 fn actions_mut(
1287 &mut self,
1288 capture_phase: bool,
1289 ) -> &mut HashMap<TypeId, HashMap<TypeId, Vec<Box<ActionCallback>>>> {
1290 if capture_phase {
1291 &mut self.capture_actions
1292 } else {
1293 &mut self.actions
1294 }
1295 }
1296
1297 pub fn dispatch_global_action<A: Action>(&mut self, action: A) {
1298 self.dispatch_global_action_any(&action);
1299 }
1300
1301 fn dispatch_global_action_any(&mut self, action: &dyn AnyAction) -> bool {
1302 self.update(|this| {
1303 if let Some((name, mut handler)) = this.global_actions.remove_entry(&action.id()) {
1304 handler(action, this);
1305 this.global_actions.insert(name, handler);
1306 true
1307 } else {
1308 false
1309 }
1310 })
1311 }
1312
1313 pub fn add_bindings<T: IntoIterator<Item = keymap::Binding>>(&mut self, bindings: T) {
1314 self.keystroke_matcher.add_bindings(bindings);
1315 }
1316
1317 pub fn dispatch_keystroke(
1318 &mut self,
1319 window_id: usize,
1320 responder_chain: Vec<usize>,
1321 keystroke: &Keystroke,
1322 ) -> Result<bool> {
1323 let mut context_chain = Vec::new();
1324 for view_id in &responder_chain {
1325 if let Some(view) = self.cx.views.get(&(window_id, *view_id)) {
1326 context_chain.push(view.keymap_context(self.as_ref()));
1327 } else {
1328 return Err(anyhow!(
1329 "View {} in responder chain does not exist",
1330 view_id
1331 ));
1332 }
1333 }
1334
1335 let mut pending = false;
1336 for (i, cx) in context_chain.iter().enumerate().rev() {
1337 match self
1338 .keystroke_matcher
1339 .push_keystroke(keystroke.clone(), responder_chain[i], cx)
1340 {
1341 MatchResult::None => {}
1342 MatchResult::Pending => pending = true,
1343 MatchResult::Action(action) => {
1344 if self.dispatch_action_any(window_id, &responder_chain[0..=i], action.as_ref())
1345 {
1346 self.keystroke_matcher.clear_pending();
1347 return Ok(true);
1348 }
1349 }
1350 }
1351 }
1352
1353 Ok(pending)
1354 }
1355
1356 pub fn add_app_state<T: 'static>(&mut self, state: T) {
1357 self.cx
1358 .app_states
1359 .insert(TypeId::of::<T>(), Box::new(state));
1360 }
1361
1362 pub fn update_app_state<T: 'static, F, U>(&mut self, update: F) -> U
1363 where
1364 F: FnOnce(&mut T, &mut MutableAppContext) -> U,
1365 {
1366 let type_id = TypeId::of::<T>();
1367 let mut state = self
1368 .cx
1369 .app_states
1370 .remove(&type_id)
1371 .expect("no app state has been added for this type");
1372 let result = update(state.downcast_mut().unwrap(), self);
1373 self.cx.app_states.insert(type_id, state);
1374 result
1375 }
1376
1377 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
1378 where
1379 T: Entity,
1380 F: FnOnce(&mut ModelContext<T>) -> T,
1381 {
1382 self.update(|this| {
1383 let model_id = post_inc(&mut this.next_entity_id);
1384 let handle = ModelHandle::new(model_id, &this.cx.ref_counts);
1385 let mut cx = ModelContext::new(this, model_id);
1386 let model = build_model(&mut cx);
1387 this.cx.models.insert(model_id, Box::new(model));
1388 handle
1389 })
1390 }
1391
1392 pub fn add_window<T, F>(
1393 &mut self,
1394 window_options: WindowOptions,
1395 build_root_view: F,
1396 ) -> (usize, ViewHandle<T>)
1397 where
1398 T: View,
1399 F: FnOnce(&mut ViewContext<T>) -> T,
1400 {
1401 self.update(|this| {
1402 let window_id = post_inc(&mut this.next_window_id);
1403 let root_view = this.add_view(window_id, build_root_view);
1404
1405 this.cx.windows.insert(
1406 window_id,
1407 Window {
1408 root_view: root_view.clone().into(),
1409 focused_view_id: Some(root_view.id()),
1410 invalidation: None,
1411 },
1412 );
1413 this.open_platform_window(window_id, window_options);
1414 root_view.update(this, |view, cx| {
1415 view.on_focus(cx);
1416 cx.notify();
1417 });
1418
1419 (window_id, root_view)
1420 })
1421 }
1422
1423 pub fn remove_window(&mut self, window_id: usize) {
1424 self.cx.windows.remove(&window_id);
1425 self.presenters_and_platform_windows.remove(&window_id);
1426 self.flush_effects();
1427 }
1428
1429 fn open_platform_window(&mut self, window_id: usize, window_options: WindowOptions) {
1430 let mut window =
1431 self.cx
1432 .platform
1433 .open_window(window_id, window_options, self.foreground.clone());
1434 let presenter = Rc::new(RefCell::new(
1435 self.build_presenter(window_id, window.titlebar_height()),
1436 ));
1437
1438 {
1439 let mut app = self.upgrade();
1440 let presenter = presenter.clone();
1441 window.on_event(Box::new(move |event| {
1442 app.update(|cx| {
1443 if let Event::KeyDown { keystroke, .. } = &event {
1444 if cx
1445 .dispatch_keystroke(
1446 window_id,
1447 presenter.borrow().dispatch_path(cx.as_ref()),
1448 keystroke,
1449 )
1450 .unwrap()
1451 {
1452 return;
1453 }
1454 }
1455
1456 presenter.borrow_mut().dispatch_event(event, cx);
1457 })
1458 }));
1459 }
1460
1461 {
1462 let mut app = self.upgrade();
1463 window.on_resize(Box::new(move || {
1464 app.update(|cx| cx.resize_window(window_id))
1465 }));
1466 }
1467
1468 {
1469 let mut app = self.upgrade();
1470 window.on_close(Box::new(move || {
1471 app.update(|cx| cx.remove_window(window_id));
1472 }));
1473 }
1474
1475 self.presenters_and_platform_windows
1476 .insert(window_id, (presenter.clone(), window));
1477 }
1478
1479 pub fn build_presenter(&mut self, window_id: usize, titlebar_height: f32) -> Presenter {
1480 Presenter::new(
1481 window_id,
1482 titlebar_height,
1483 self.cx.font_cache.clone(),
1484 TextLayoutCache::new(self.cx.platform.fonts()),
1485 self.assets.clone(),
1486 self,
1487 )
1488 }
1489
1490 pub fn build_render_context<V: View>(
1491 &mut self,
1492 window_id: usize,
1493 view_id: usize,
1494 titlebar_height: f32,
1495 refreshing: bool,
1496 ) -> RenderContext<V> {
1497 RenderContext {
1498 app: self,
1499 titlebar_height,
1500 refreshing,
1501 window_id,
1502 view_id,
1503 view_type: PhantomData,
1504 }
1505 }
1506
1507 pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
1508 where
1509 T: View,
1510 F: FnOnce(&mut ViewContext<T>) -> T,
1511 {
1512 self.add_option_view(window_id, |cx| Some(build_view(cx)))
1513 .unwrap()
1514 }
1515
1516 pub fn add_option_view<T, F>(
1517 &mut self,
1518 window_id: usize,
1519 build_view: F,
1520 ) -> Option<ViewHandle<T>>
1521 where
1522 T: View,
1523 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
1524 {
1525 self.update(|this| {
1526 let view_id = post_inc(&mut this.next_entity_id);
1527 let mut cx = ViewContext::new(this, window_id, view_id);
1528 let handle = if let Some(view) = build_view(&mut cx) {
1529 this.cx.views.insert((window_id, view_id), Box::new(view));
1530 if let Some(window) = this.cx.windows.get_mut(&window_id) {
1531 window
1532 .invalidation
1533 .get_or_insert_with(Default::default)
1534 .updated
1535 .insert(view_id);
1536 }
1537 Some(ViewHandle::new(window_id, view_id, &this.cx.ref_counts))
1538 } else {
1539 None
1540 };
1541 handle
1542 })
1543 }
1544
1545 fn remove_dropped_entities(&mut self) {
1546 loop {
1547 let (dropped_models, dropped_views, dropped_element_states) =
1548 self.cx.ref_counts.lock().take_dropped();
1549 if dropped_models.is_empty()
1550 && dropped_views.is_empty()
1551 && dropped_element_states.is_empty()
1552 {
1553 break;
1554 }
1555
1556 for model_id in dropped_models {
1557 self.subscriptions.lock().remove(&model_id);
1558 self.observations.lock().remove(&model_id);
1559 let mut model = self.cx.models.remove(&model_id).unwrap();
1560 model.release(self);
1561 self.pending_effects.push_back(Effect::Release {
1562 entity_id: model_id,
1563 });
1564 }
1565
1566 for (window_id, view_id) in dropped_views {
1567 self.subscriptions.lock().remove(&view_id);
1568 self.observations.lock().remove(&view_id);
1569 let mut view = self.cx.views.remove(&(window_id, view_id)).unwrap();
1570 view.release(self);
1571 let change_focus_to = self.cx.windows.get_mut(&window_id).and_then(|window| {
1572 window
1573 .invalidation
1574 .get_or_insert_with(Default::default)
1575 .removed
1576 .push(view_id);
1577 if window.focused_view_id == Some(view_id) {
1578 Some(window.root_view.id())
1579 } else {
1580 None
1581 }
1582 });
1583
1584 if let Some(view_id) = change_focus_to {
1585 self.focus(window_id, Some(view_id));
1586 }
1587
1588 self.pending_effects
1589 .push_back(Effect::Release { entity_id: view_id });
1590 }
1591
1592 for key in dropped_element_states {
1593 self.cx.element_states.remove(&key);
1594 }
1595 }
1596 }
1597
1598 fn flush_effects(&mut self) {
1599 self.pending_flushes = self.pending_flushes.saturating_sub(1);
1600
1601 if !self.flushing_effects && self.pending_flushes == 0 {
1602 self.flushing_effects = true;
1603
1604 let mut refreshing = false;
1605 loop {
1606 if let Some(effect) = self.pending_effects.pop_front() {
1607 match effect {
1608 Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload),
1609 Effect::ModelNotification { model_id } => {
1610 self.notify_model_observers(model_id)
1611 }
1612 Effect::ViewNotification { window_id, view_id } => {
1613 self.notify_view_observers(window_id, view_id)
1614 }
1615 Effect::Deferred(callback) => callback(self),
1616 Effect::Release { entity_id } => self.notify_release_observers(entity_id),
1617 Effect::Focus { window_id, view_id } => {
1618 self.focus(window_id, view_id);
1619 }
1620 Effect::ResizeWindow { window_id } => {
1621 if let Some(window) = self.cx.windows.get_mut(&window_id) {
1622 window
1623 .invalidation
1624 .get_or_insert(WindowInvalidation::default());
1625 }
1626 }
1627 Effect::RefreshWindows => {
1628 refreshing = true;
1629 }
1630 }
1631 self.pending_notifications.clear();
1632 self.remove_dropped_entities();
1633 } else {
1634 self.remove_dropped_entities();
1635 if refreshing {
1636 self.perform_window_refresh();
1637 } else {
1638 self.update_windows();
1639 }
1640
1641 if self.pending_effects.is_empty() {
1642 self.flushing_effects = false;
1643 self.pending_notifications.clear();
1644 break;
1645 } else {
1646 refreshing = false;
1647 }
1648 }
1649 }
1650 }
1651 }
1652
1653 fn update_windows(&mut self) {
1654 let mut invalidations = HashMap::new();
1655 for (window_id, window) in &mut self.cx.windows {
1656 if let Some(invalidation) = window.invalidation.take() {
1657 invalidations.insert(*window_id, invalidation);
1658 }
1659 }
1660
1661 for (window_id, invalidation) in invalidations {
1662 if let Some((presenter, mut window)) =
1663 self.presenters_and_platform_windows.remove(&window_id)
1664 {
1665 {
1666 let mut presenter = presenter.borrow_mut();
1667 presenter.invalidate(invalidation, self);
1668 let scene =
1669 presenter.build_scene(window.size(), window.scale_factor(), false, self);
1670 window.present_scene(scene);
1671 }
1672 self.presenters_and_platform_windows
1673 .insert(window_id, (presenter, window));
1674 }
1675 }
1676 }
1677
1678 fn resize_window(&mut self, window_id: usize) {
1679 self.pending_effects
1680 .push_back(Effect::ResizeWindow { window_id });
1681 }
1682
1683 pub fn refresh_windows(&mut self) {
1684 self.pending_effects.push_back(Effect::RefreshWindows);
1685 }
1686
1687 fn perform_window_refresh(&mut self) {
1688 let mut presenters = mem::take(&mut self.presenters_and_platform_windows);
1689 for (window_id, (presenter, window)) in &mut presenters {
1690 let invalidation = self
1691 .cx
1692 .windows
1693 .get_mut(&window_id)
1694 .unwrap()
1695 .invalidation
1696 .take();
1697 let mut presenter = presenter.borrow_mut();
1698 presenter.refresh(invalidation, self);
1699 let scene = presenter.build_scene(window.size(), window.scale_factor(), true, self);
1700 window.present_scene(scene);
1701 }
1702 self.presenters_and_platform_windows = presenters;
1703 }
1704
1705 pub fn set_cursor_style(&mut self, style: CursorStyle) -> CursorStyleHandle {
1706 self.platform.set_cursor_style(style);
1707 let id = self.next_cursor_style_handle_id.fetch_add(1, SeqCst);
1708 CursorStyleHandle {
1709 id,
1710 next_cursor_style_handle_id: self.next_cursor_style_handle_id.clone(),
1711 platform: self.platform(),
1712 }
1713 }
1714
1715 fn emit_event(&mut self, entity_id: usize, payload: Box<dyn Any>) {
1716 let callbacks = self.subscriptions.lock().remove(&entity_id);
1717 if let Some(callbacks) = callbacks {
1718 for (id, mut callback) in callbacks {
1719 let alive = callback(payload.as_ref(), self);
1720 if alive {
1721 self.subscriptions
1722 .lock()
1723 .entry(entity_id)
1724 .or_default()
1725 .insert(id, callback);
1726 }
1727 }
1728 }
1729 }
1730
1731 fn notify_model_observers(&mut self, observed_id: usize) {
1732 let callbacks = self.observations.lock().remove(&observed_id);
1733 if let Some(callbacks) = callbacks {
1734 if self.cx.models.contains_key(&observed_id) {
1735 for (id, mut callback) in callbacks {
1736 let alive = callback(self);
1737 if alive {
1738 self.observations
1739 .lock()
1740 .entry(observed_id)
1741 .or_default()
1742 .insert(id, callback);
1743 }
1744 }
1745 }
1746 }
1747 }
1748
1749 fn notify_view_observers(&mut self, observed_window_id: usize, observed_view_id: usize) {
1750 if let Some(window) = self.cx.windows.get_mut(&observed_window_id) {
1751 window
1752 .invalidation
1753 .get_or_insert_with(Default::default)
1754 .updated
1755 .insert(observed_view_id);
1756 }
1757
1758 let callbacks = self.observations.lock().remove(&observed_view_id);
1759 if let Some(callbacks) = callbacks {
1760 if self
1761 .cx
1762 .views
1763 .contains_key(&(observed_window_id, observed_view_id))
1764 {
1765 for (id, mut callback) in callbacks {
1766 let alive = callback(self);
1767 if alive {
1768 self.observations
1769 .lock()
1770 .entry(observed_view_id)
1771 .or_default()
1772 .insert(id, callback);
1773 }
1774 }
1775 }
1776 }
1777 }
1778
1779 fn notify_release_observers(&mut self, entity_id: usize) {
1780 let callbacks = self.release_observations.lock().remove(&entity_id);
1781 if let Some(callbacks) = callbacks {
1782 for (_, mut callback) in callbacks {
1783 callback(self);
1784 }
1785 }
1786 }
1787
1788 fn focus(&mut self, window_id: usize, focused_id: Option<usize>) {
1789 if self
1790 .cx
1791 .windows
1792 .get(&window_id)
1793 .map(|w| w.focused_view_id)
1794 .map_or(false, |cur_focused| cur_focused == focused_id)
1795 {
1796 return;
1797 }
1798
1799 self.update(|this| {
1800 let blurred_id = this.cx.windows.get_mut(&window_id).and_then(|window| {
1801 let blurred_id = window.focused_view_id;
1802 window.focused_view_id = focused_id;
1803 blurred_id
1804 });
1805
1806 if let Some(blurred_id) = blurred_id {
1807 if let Some(mut blurred_view) = this.cx.views.remove(&(window_id, blurred_id)) {
1808 blurred_view.on_blur(this, window_id, blurred_id);
1809 this.cx.views.insert((window_id, blurred_id), blurred_view);
1810 }
1811 }
1812
1813 if let Some(focused_id) = focused_id {
1814 if let Some(mut focused_view) = this.cx.views.remove(&(window_id, focused_id)) {
1815 focused_view.on_focus(this, window_id, focused_id);
1816 this.cx.views.insert((window_id, focused_id), focused_view);
1817 }
1818 }
1819 })
1820 }
1821
1822 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
1823 where
1824 F: FnOnce(AsyncAppContext) -> Fut,
1825 Fut: 'static + Future<Output = T>,
1826 T: 'static,
1827 {
1828 let future = f(self.to_async());
1829 let cx = self.to_async();
1830 self.foreground.spawn(async move {
1831 let result = future.await;
1832 cx.0.borrow_mut().flush_effects();
1833 result
1834 })
1835 }
1836
1837 pub fn to_async(&self) -> AsyncAppContext {
1838 AsyncAppContext(self.weak_self.as_ref().unwrap().upgrade().unwrap())
1839 }
1840
1841 pub fn write_to_clipboard(&self, item: ClipboardItem) {
1842 self.cx.platform.write_to_clipboard(item);
1843 }
1844
1845 pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {
1846 self.cx.platform.read_from_clipboard()
1847 }
1848
1849 #[cfg(any(test, feature = "test-support"))]
1850 pub fn leak_detector(&self) -> Arc<Mutex<LeakDetector>> {
1851 self.cx.ref_counts.lock().leak_detector.clone()
1852 }
1853}
1854
1855impl ReadModel for MutableAppContext {
1856 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1857 if let Some(model) = self.cx.models.get(&handle.model_id) {
1858 model
1859 .as_any()
1860 .downcast_ref()
1861 .expect("downcast is type safe")
1862 } else {
1863 panic!("circular model reference");
1864 }
1865 }
1866}
1867
1868impl UpdateModel for MutableAppContext {
1869 fn update_model<T: Entity, V>(
1870 &mut self,
1871 handle: &ModelHandle<T>,
1872 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
1873 ) -> V {
1874 if let Some(mut model) = self.cx.models.remove(&handle.model_id) {
1875 self.update(|this| {
1876 let mut cx = ModelContext::new(this, handle.model_id);
1877 let result = update(
1878 model
1879 .as_any_mut()
1880 .downcast_mut()
1881 .expect("downcast is type safe"),
1882 &mut cx,
1883 );
1884 this.cx.models.insert(handle.model_id, model);
1885 result
1886 })
1887 } else {
1888 panic!("circular model update");
1889 }
1890 }
1891}
1892
1893impl UpgradeModelHandle for MutableAppContext {
1894 fn upgrade_model_handle<T: Entity>(
1895 &self,
1896 handle: &WeakModelHandle<T>,
1897 ) -> Option<ModelHandle<T>> {
1898 self.cx.upgrade_model_handle(handle)
1899 }
1900
1901 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
1902 self.cx.model_handle_is_upgradable(handle)
1903 }
1904
1905 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
1906 self.cx.upgrade_any_model_handle(handle)
1907 }
1908}
1909
1910impl UpgradeViewHandle for MutableAppContext {
1911 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
1912 self.cx.upgrade_view_handle(handle)
1913 }
1914}
1915
1916impl ReadView for MutableAppContext {
1917 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1918 if let Some(view) = self.cx.views.get(&(handle.window_id, handle.view_id)) {
1919 view.as_any().downcast_ref().expect("downcast is type safe")
1920 } else {
1921 panic!("circular view reference");
1922 }
1923 }
1924}
1925
1926impl UpdateView for MutableAppContext {
1927 fn update_view<T, S>(
1928 &mut self,
1929 handle: &ViewHandle<T>,
1930 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
1931 ) -> S
1932 where
1933 T: View,
1934 {
1935 self.update(|this| {
1936 let mut view = this
1937 .cx
1938 .views
1939 .remove(&(handle.window_id, handle.view_id))
1940 .expect("circular view update");
1941
1942 let mut cx = ViewContext::new(this, handle.window_id, handle.view_id);
1943 let result = update(
1944 view.as_any_mut()
1945 .downcast_mut()
1946 .expect("downcast is type safe"),
1947 &mut cx,
1948 );
1949 this.cx
1950 .views
1951 .insert((handle.window_id, handle.view_id), view);
1952 result
1953 })
1954 }
1955}
1956
1957impl AsRef<AppContext> for MutableAppContext {
1958 fn as_ref(&self) -> &AppContext {
1959 &self.cx
1960 }
1961}
1962
1963impl Deref for MutableAppContext {
1964 type Target = AppContext;
1965
1966 fn deref(&self) -> &Self::Target {
1967 &self.cx
1968 }
1969}
1970
1971pub struct AppContext {
1972 models: HashMap<usize, Box<dyn AnyModel>>,
1973 views: HashMap<(usize, usize), Box<dyn AnyView>>,
1974 windows: HashMap<usize, Window>,
1975 app_states: HashMap<TypeId, Box<dyn Any>>,
1976 element_states: HashMap<ElementStateId, Box<dyn Any>>,
1977 background: Arc<executor::Background>,
1978 ref_counts: Arc<Mutex<RefCounts>>,
1979 font_cache: Arc<FontCache>,
1980 platform: Arc<dyn Platform>,
1981}
1982
1983impl AppContext {
1984 pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
1985 self.windows
1986 .get(&window_id)
1987 .map(|window| window.root_view.id())
1988 }
1989
1990 pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
1991 self.windows
1992 .get(&window_id)
1993 .and_then(|window| window.focused_view_id)
1994 }
1995
1996 pub fn background(&self) -> &Arc<executor::Background> {
1997 &self.background
1998 }
1999
2000 pub fn font_cache(&self) -> &Arc<FontCache> {
2001 &self.font_cache
2002 }
2003
2004 pub fn platform(&self) -> &Arc<dyn Platform> {
2005 &self.platform
2006 }
2007
2008 pub fn app_state<T: 'static>(&self) -> &T {
2009 self.app_states
2010 .get(&TypeId::of::<T>())
2011 .expect("no app state has been added for this type")
2012 .downcast_ref()
2013 .unwrap()
2014 }
2015}
2016
2017impl ReadModel for AppContext {
2018 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2019 if let Some(model) = self.models.get(&handle.model_id) {
2020 model
2021 .as_any()
2022 .downcast_ref()
2023 .expect("downcast should be type safe")
2024 } else {
2025 panic!("circular model reference");
2026 }
2027 }
2028}
2029
2030impl UpgradeModelHandle for AppContext {
2031 fn upgrade_model_handle<T: Entity>(
2032 &self,
2033 handle: &WeakModelHandle<T>,
2034 ) -> Option<ModelHandle<T>> {
2035 if self.models.contains_key(&handle.model_id) {
2036 Some(ModelHandle::new(handle.model_id, &self.ref_counts))
2037 } else {
2038 None
2039 }
2040 }
2041
2042 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
2043 self.models.contains_key(&handle.model_id)
2044 }
2045
2046 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
2047 if self.models.contains_key(&handle.model_id) {
2048 Some(AnyModelHandle::new(
2049 handle.model_id,
2050 handle.model_type,
2051 self.ref_counts.clone(),
2052 ))
2053 } else {
2054 None
2055 }
2056 }
2057}
2058
2059impl UpgradeViewHandle for AppContext {
2060 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
2061 if self.ref_counts.lock().is_entity_alive(handle.view_id) {
2062 Some(ViewHandle::new(
2063 handle.window_id,
2064 handle.view_id,
2065 &self.ref_counts,
2066 ))
2067 } else {
2068 None
2069 }
2070 }
2071}
2072
2073impl ReadView for AppContext {
2074 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2075 if let Some(view) = self.views.get(&(handle.window_id, handle.view_id)) {
2076 view.as_any()
2077 .downcast_ref()
2078 .expect("downcast should be type safe")
2079 } else {
2080 panic!("circular view reference");
2081 }
2082 }
2083}
2084
2085struct Window {
2086 root_view: AnyViewHandle,
2087 focused_view_id: Option<usize>,
2088 invalidation: Option<WindowInvalidation>,
2089}
2090
2091#[derive(Default, Clone)]
2092pub struct WindowInvalidation {
2093 pub updated: HashSet<usize>,
2094 pub removed: Vec<usize>,
2095}
2096
2097pub enum Effect {
2098 Event {
2099 entity_id: usize,
2100 payload: Box<dyn Any>,
2101 },
2102 ModelNotification {
2103 model_id: usize,
2104 },
2105 ViewNotification {
2106 window_id: usize,
2107 view_id: usize,
2108 },
2109 Deferred(Box<dyn FnOnce(&mut MutableAppContext)>),
2110 Release {
2111 entity_id: usize,
2112 },
2113 Focus {
2114 window_id: usize,
2115 view_id: Option<usize>,
2116 },
2117 ResizeWindow {
2118 window_id: usize,
2119 },
2120 RefreshWindows,
2121}
2122
2123impl Debug for Effect {
2124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2125 match self {
2126 Effect::Event { entity_id, .. } => f
2127 .debug_struct("Effect::Event")
2128 .field("entity_id", entity_id)
2129 .finish(),
2130 Effect::ModelNotification { model_id } => f
2131 .debug_struct("Effect::ModelNotification")
2132 .field("model_id", model_id)
2133 .finish(),
2134 Effect::ViewNotification { window_id, view_id } => f
2135 .debug_struct("Effect::ViewNotification")
2136 .field("window_id", window_id)
2137 .field("view_id", view_id)
2138 .finish(),
2139 Effect::Deferred(_) => f.debug_struct("Effect::Deferred").finish(),
2140 Effect::Release { entity_id } => f
2141 .debug_struct("Effect::Release")
2142 .field("entity_id", entity_id)
2143 .finish(),
2144 Effect::Focus { window_id, view_id } => f
2145 .debug_struct("Effect::Focus")
2146 .field("window_id", window_id)
2147 .field("view_id", view_id)
2148 .finish(),
2149 Effect::ResizeWindow { window_id } => f
2150 .debug_struct("Effect::RefreshWindow")
2151 .field("window_id", window_id)
2152 .finish(),
2153 Effect::RefreshWindows => f.debug_struct("Effect::FullViewRefresh").finish(),
2154 }
2155 }
2156}
2157
2158pub trait AnyModel {
2159 fn as_any(&self) -> &dyn Any;
2160 fn as_any_mut(&mut self) -> &mut dyn Any;
2161 fn release(&mut self, cx: &mut MutableAppContext);
2162 fn app_will_quit(
2163 &mut self,
2164 cx: &mut MutableAppContext,
2165 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
2166}
2167
2168impl<T> AnyModel for T
2169where
2170 T: Entity,
2171{
2172 fn as_any(&self) -> &dyn Any {
2173 self
2174 }
2175
2176 fn as_any_mut(&mut self) -> &mut dyn Any {
2177 self
2178 }
2179
2180 fn release(&mut self, cx: &mut MutableAppContext) {
2181 self.release(cx);
2182 }
2183
2184 fn app_will_quit(
2185 &mut self,
2186 cx: &mut MutableAppContext,
2187 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
2188 self.app_will_quit(cx)
2189 }
2190}
2191
2192pub trait AnyView {
2193 fn as_any(&self) -> &dyn Any;
2194 fn as_any_mut(&mut self) -> &mut dyn Any;
2195 fn release(&mut self, cx: &mut MutableAppContext);
2196 fn app_will_quit(
2197 &mut self,
2198 cx: &mut MutableAppContext,
2199 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
2200 fn ui_name(&self) -> &'static str;
2201 fn render<'a>(
2202 &mut self,
2203 window_id: usize,
2204 view_id: usize,
2205 titlebar_height: f32,
2206 refreshing: bool,
2207 cx: &mut MutableAppContext,
2208 ) -> ElementBox;
2209 fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize);
2210 fn on_blur(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize);
2211 fn keymap_context(&self, cx: &AppContext) -> keymap::Context;
2212}
2213
2214impl<T> AnyView for T
2215where
2216 T: View,
2217{
2218 fn as_any(&self) -> &dyn Any {
2219 self
2220 }
2221
2222 fn as_any_mut(&mut self) -> &mut dyn Any {
2223 self
2224 }
2225
2226 fn release(&mut self, cx: &mut MutableAppContext) {
2227 self.release(cx);
2228 }
2229
2230 fn app_will_quit(
2231 &mut self,
2232 cx: &mut MutableAppContext,
2233 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
2234 self.app_will_quit(cx)
2235 }
2236
2237 fn ui_name(&self) -> &'static str {
2238 T::ui_name()
2239 }
2240
2241 fn render<'a>(
2242 &mut self,
2243 window_id: usize,
2244 view_id: usize,
2245 titlebar_height: f32,
2246 refreshing: bool,
2247 cx: &mut MutableAppContext,
2248 ) -> ElementBox {
2249 View::render(
2250 self,
2251 &mut RenderContext {
2252 window_id,
2253 view_id,
2254 app: cx,
2255 view_type: PhantomData::<T>,
2256 titlebar_height,
2257 refreshing,
2258 },
2259 )
2260 }
2261
2262 fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) {
2263 let mut cx = ViewContext::new(cx, window_id, view_id);
2264 View::on_focus(self, &mut cx);
2265 }
2266
2267 fn on_blur(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) {
2268 let mut cx = ViewContext::new(cx, window_id, view_id);
2269 View::on_blur(self, &mut cx);
2270 }
2271
2272 fn keymap_context(&self, cx: &AppContext) -> keymap::Context {
2273 View::keymap_context(self, cx)
2274 }
2275}
2276
2277pub struct ModelContext<'a, T: ?Sized> {
2278 app: &'a mut MutableAppContext,
2279 model_id: usize,
2280 model_type: PhantomData<T>,
2281 halt_stream: bool,
2282}
2283
2284impl<'a, T: Entity> ModelContext<'a, T> {
2285 fn new(app: &'a mut MutableAppContext, model_id: usize) -> Self {
2286 Self {
2287 app,
2288 model_id,
2289 model_type: PhantomData,
2290 halt_stream: false,
2291 }
2292 }
2293
2294 pub fn background(&self) -> &Arc<executor::Background> {
2295 &self.app.cx.background
2296 }
2297
2298 pub fn halt_stream(&mut self) {
2299 self.halt_stream = true;
2300 }
2301
2302 pub fn model_id(&self) -> usize {
2303 self.model_id
2304 }
2305
2306 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
2307 where
2308 S: Entity,
2309 F: FnOnce(&mut ModelContext<S>) -> S,
2310 {
2311 self.app.add_model(build_model)
2312 }
2313
2314 pub fn emit(&mut self, payload: T::Event) {
2315 self.app.pending_effects.push_back(Effect::Event {
2316 entity_id: self.model_id,
2317 payload: Box::new(payload),
2318 });
2319 }
2320
2321 pub fn notify(&mut self) {
2322 self.app.notify_model(self.model_id);
2323 }
2324
2325 pub fn subscribe<S: Entity, F>(
2326 &mut self,
2327 handle: &ModelHandle<S>,
2328 mut callback: F,
2329 ) -> Subscription
2330 where
2331 S::Event: 'static,
2332 F: 'static + FnMut(&mut T, ModelHandle<S>, &S::Event, &mut ModelContext<T>),
2333 {
2334 let subscriber = self.weak_handle();
2335 self.app
2336 .subscribe_internal(handle, move |emitter, event, cx| {
2337 if let Some(subscriber) = subscriber.upgrade(cx) {
2338 subscriber.update(cx, |subscriber, cx| {
2339 callback(subscriber, emitter, event, cx);
2340 });
2341 true
2342 } else {
2343 false
2344 }
2345 })
2346 }
2347
2348 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F) -> Subscription
2349 where
2350 S: Entity,
2351 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ModelContext<T>),
2352 {
2353 let observer = self.weak_handle();
2354 self.app.observe_internal(handle, move |observed, cx| {
2355 if let Some(observer) = observer.upgrade(cx) {
2356 observer.update(cx, |observer, cx| {
2357 callback(observer, observed, cx);
2358 });
2359 true
2360 } else {
2361 false
2362 }
2363 })
2364 }
2365
2366 pub fn observe_release<S, F>(
2367 &mut self,
2368 handle: &ModelHandle<S>,
2369 mut callback: F,
2370 ) -> Subscription
2371 where
2372 S: Entity,
2373 F: 'static + FnMut(&mut T, &mut ModelContext<T>),
2374 {
2375 let observer = self.weak_handle();
2376 self.app.observe_release(handle, move |cx| {
2377 if let Some(observer) = observer.upgrade(cx) {
2378 observer.update(cx, |observer, cx| {
2379 callback(observer, cx);
2380 });
2381 }
2382 })
2383 }
2384
2385 pub fn handle(&self) -> ModelHandle<T> {
2386 ModelHandle::new(self.model_id, &self.app.cx.ref_counts)
2387 }
2388
2389 pub fn weak_handle(&self) -> WeakModelHandle<T> {
2390 WeakModelHandle::new(self.model_id)
2391 }
2392
2393 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
2394 where
2395 F: FnOnce(ModelHandle<T>, AsyncAppContext) -> Fut,
2396 Fut: 'static + Future<Output = S>,
2397 S: 'static,
2398 {
2399 let handle = self.handle();
2400 self.app.spawn(|cx| f(handle, cx))
2401 }
2402
2403 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
2404 where
2405 F: FnOnce(WeakModelHandle<T>, AsyncAppContext) -> Fut,
2406 Fut: 'static + Future<Output = S>,
2407 S: 'static,
2408 {
2409 let handle = self.weak_handle();
2410 self.app.spawn(|cx| f(handle, cx))
2411 }
2412}
2413
2414impl<M> AsRef<AppContext> for ModelContext<'_, M> {
2415 fn as_ref(&self) -> &AppContext {
2416 &self.app.cx
2417 }
2418}
2419
2420impl<M> AsMut<MutableAppContext> for ModelContext<'_, M> {
2421 fn as_mut(&mut self) -> &mut MutableAppContext {
2422 self.app
2423 }
2424}
2425
2426impl<M> ReadModel for ModelContext<'_, M> {
2427 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2428 self.app.read_model(handle)
2429 }
2430}
2431
2432impl<M> UpdateModel for ModelContext<'_, M> {
2433 fn update_model<T: Entity, V>(
2434 &mut self,
2435 handle: &ModelHandle<T>,
2436 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
2437 ) -> V {
2438 self.app.update_model(handle, update)
2439 }
2440}
2441
2442impl<M> UpgradeModelHandle for ModelContext<'_, M> {
2443 fn upgrade_model_handle<T: Entity>(
2444 &self,
2445 handle: &WeakModelHandle<T>,
2446 ) -> Option<ModelHandle<T>> {
2447 self.cx.upgrade_model_handle(handle)
2448 }
2449
2450 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
2451 self.cx.model_handle_is_upgradable(handle)
2452 }
2453
2454 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
2455 self.cx.upgrade_any_model_handle(handle)
2456 }
2457}
2458
2459impl<M> Deref for ModelContext<'_, M> {
2460 type Target = MutableAppContext;
2461
2462 fn deref(&self) -> &Self::Target {
2463 &self.app
2464 }
2465}
2466
2467impl<M> DerefMut for ModelContext<'_, M> {
2468 fn deref_mut(&mut self) -> &mut Self::Target {
2469 &mut self.app
2470 }
2471}
2472
2473pub struct ViewContext<'a, T: ?Sized> {
2474 app: &'a mut MutableAppContext,
2475 window_id: usize,
2476 view_id: usize,
2477 view_type: PhantomData<T>,
2478}
2479
2480impl<'a, T: View> ViewContext<'a, T> {
2481 fn new(app: &'a mut MutableAppContext, window_id: usize, view_id: usize) -> Self {
2482 Self {
2483 app,
2484 window_id,
2485 view_id,
2486 view_type: PhantomData,
2487 }
2488 }
2489
2490 pub fn handle(&self) -> ViewHandle<T> {
2491 ViewHandle::new(self.window_id, self.view_id, &self.app.cx.ref_counts)
2492 }
2493
2494 pub fn weak_handle(&self) -> WeakViewHandle<T> {
2495 WeakViewHandle::new(self.window_id, self.view_id)
2496 }
2497
2498 pub fn window_id(&self) -> usize {
2499 self.window_id
2500 }
2501
2502 pub fn view_id(&self) -> usize {
2503 self.view_id
2504 }
2505
2506 pub fn foreground(&self) -> &Rc<executor::Foreground> {
2507 self.app.foreground()
2508 }
2509
2510 pub fn background_executor(&self) -> &Arc<executor::Background> {
2511 &self.app.cx.background
2512 }
2513
2514 pub fn platform(&self) -> Arc<dyn Platform> {
2515 self.app.platform()
2516 }
2517
2518 pub fn prompt(
2519 &self,
2520 level: PromptLevel,
2521 msg: &str,
2522 answers: &[&str],
2523 ) -> oneshot::Receiver<usize> {
2524 self.app.prompt(self.window_id, level, msg, answers)
2525 }
2526
2527 pub fn prompt_for_paths(
2528 &self,
2529 options: PathPromptOptions,
2530 ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
2531 self.app.prompt_for_paths(options)
2532 }
2533
2534 pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
2535 self.app.prompt_for_new_path(directory)
2536 }
2537
2538 pub fn debug_elements(&self) -> crate::json::Value {
2539 self.app.debug_elements(self.window_id).unwrap()
2540 }
2541
2542 pub fn focus<S>(&mut self, handle: S)
2543 where
2544 S: Into<AnyViewHandle>,
2545 {
2546 let handle = handle.into();
2547 self.app.pending_effects.push_back(Effect::Focus {
2548 window_id: handle.window_id,
2549 view_id: Some(handle.view_id),
2550 });
2551 }
2552
2553 pub fn focus_self(&mut self) {
2554 self.app.pending_effects.push_back(Effect::Focus {
2555 window_id: self.window_id,
2556 view_id: Some(self.view_id),
2557 });
2558 }
2559
2560 pub fn blur(&mut self) {
2561 self.app.pending_effects.push_back(Effect::Focus {
2562 window_id: self.window_id,
2563 view_id: None,
2564 });
2565 }
2566
2567 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
2568 where
2569 S: Entity,
2570 F: FnOnce(&mut ModelContext<S>) -> S,
2571 {
2572 self.app.add_model(build_model)
2573 }
2574
2575 pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
2576 where
2577 S: View,
2578 F: FnOnce(&mut ViewContext<S>) -> S,
2579 {
2580 self.app.add_view(self.window_id, build_view)
2581 }
2582
2583 pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
2584 where
2585 S: View,
2586 F: FnOnce(&mut ViewContext<S>) -> Option<S>,
2587 {
2588 self.app.add_option_view(self.window_id, build_view)
2589 }
2590
2591 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
2592 where
2593 E: Entity,
2594 E::Event: 'static,
2595 H: Handle<E>,
2596 F: 'static + FnMut(&mut T, H, &E::Event, &mut ViewContext<T>),
2597 {
2598 let subscriber = self.weak_handle();
2599 self.app
2600 .subscribe_internal(handle, move |emitter, event, cx| {
2601 if let Some(subscriber) = subscriber.upgrade(cx) {
2602 subscriber.update(cx, |subscriber, cx| {
2603 callback(subscriber, emitter, event, cx);
2604 });
2605 true
2606 } else {
2607 false
2608 }
2609 })
2610 }
2611
2612 pub fn observe<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
2613 where
2614 E: Entity,
2615 H: Handle<E>,
2616 F: 'static + FnMut(&mut T, H, &mut ViewContext<T>),
2617 {
2618 let observer = self.weak_handle();
2619 self.app.observe_internal(handle, move |observed, cx| {
2620 if let Some(observer) = observer.upgrade(cx) {
2621 observer.update(cx, |observer, cx| {
2622 callback(observer, observed, cx);
2623 });
2624 true
2625 } else {
2626 false
2627 }
2628 })
2629 }
2630
2631 pub fn become_delegate<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
2632 where
2633 E: Delegator,
2634 E::Event: 'static,
2635 H: Handle<E>,
2636 F: 'static + FnMut(&mut T, H, E::Event, &mut ViewContext<T>),
2637 {
2638 // let subscriber = self.weak_handle();
2639 // self.app
2640 // .subscribe_internal(handle, move |emitter, event, cx| {
2641 // if let Some(subscriber) = subscriber.upgrade(cx) {
2642 // subscriber.update(cx, |subscriber, cx| {
2643 // callback(subscriber, emitter, event, cx);
2644 // });
2645 // true
2646 // } else {
2647 // false
2648 // }
2649 // })
2650 }
2651
2652 pub fn observe_release<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
2653 where
2654 E: Entity,
2655 H: Handle<E>,
2656 F: 'static + FnMut(&mut T, &mut ViewContext<T>),
2657 {
2658 let observer = self.weak_handle();
2659 self.app.observe_release(handle, move |cx| {
2660 if let Some(observer) = observer.upgrade(cx) {
2661 observer.update(cx, |observer, cx| {
2662 callback(observer, cx);
2663 });
2664 }
2665 })
2666 }
2667
2668 pub fn emit(&mut self, payload: T::Event) {
2669 self.app.pending_effects.push_back(Effect::Event {
2670 entity_id: self.view_id,
2671 payload: Box::new(payload),
2672 });
2673 }
2674
2675 pub fn notify(&mut self) {
2676 self.app.notify_view(self.window_id, self.view_id);
2677 }
2678
2679 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>)) {
2680 let handle = self.handle();
2681 self.app.defer(Box::new(move |cx| {
2682 handle.update(cx, |view, cx| {
2683 callback(view, cx);
2684 })
2685 }))
2686 }
2687
2688 pub fn propagate_action(&mut self) {
2689 self.app.halt_action_dispatch = false;
2690 }
2691
2692 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
2693 where
2694 F: FnOnce(ViewHandle<T>, AsyncAppContext) -> Fut,
2695 Fut: 'static + Future<Output = S>,
2696 S: 'static,
2697 {
2698 let handle = self.handle();
2699 self.app.spawn(|cx| f(handle, cx))
2700 }
2701
2702 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
2703 where
2704 F: FnOnce(WeakViewHandle<T>, AsyncAppContext) -> Fut,
2705 Fut: 'static + Future<Output = S>,
2706 S: 'static,
2707 {
2708 let handle = self.weak_handle();
2709 self.app.spawn(|cx| f(handle, cx))
2710 }
2711}
2712
2713pub struct RenderContext<'a, T: View> {
2714 pub app: &'a mut MutableAppContext,
2715 pub titlebar_height: f32,
2716 pub refreshing: bool,
2717 window_id: usize,
2718 view_id: usize,
2719 view_type: PhantomData<T>,
2720}
2721
2722impl<'a, T: View> RenderContext<'a, T> {
2723 pub fn handle(&self) -> WeakViewHandle<T> {
2724 WeakViewHandle::new(self.window_id, self.view_id)
2725 }
2726
2727 pub fn view_id(&self) -> usize {
2728 self.view_id
2729 }
2730}
2731
2732impl AsRef<AppContext> for &AppContext {
2733 fn as_ref(&self) -> &AppContext {
2734 self
2735 }
2736}
2737
2738impl<V: View> Deref for RenderContext<'_, V> {
2739 type Target = MutableAppContext;
2740
2741 fn deref(&self) -> &Self::Target {
2742 self.app
2743 }
2744}
2745
2746impl<V: View> DerefMut for RenderContext<'_, V> {
2747 fn deref_mut(&mut self) -> &mut Self::Target {
2748 self.app
2749 }
2750}
2751
2752impl<V: View> ReadModel for RenderContext<'_, V> {
2753 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2754 self.app.read_model(handle)
2755 }
2756}
2757
2758impl<V: View> UpdateModel for RenderContext<'_, V> {
2759 fn update_model<T: Entity, O>(
2760 &mut self,
2761 handle: &ModelHandle<T>,
2762 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
2763 ) -> O {
2764 self.app.update_model(handle, update)
2765 }
2766}
2767
2768impl<V: View> ReadView for RenderContext<'_, V> {
2769 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2770 self.app.read_view(handle)
2771 }
2772}
2773
2774impl<V: View> ElementStateContext for RenderContext<'_, V> {
2775 fn current_view_id(&self) -> usize {
2776 self.view_id
2777 }
2778}
2779
2780impl<M> AsRef<AppContext> for ViewContext<'_, M> {
2781 fn as_ref(&self) -> &AppContext {
2782 &self.app.cx
2783 }
2784}
2785
2786impl<M> Deref for ViewContext<'_, M> {
2787 type Target = MutableAppContext;
2788
2789 fn deref(&self) -> &Self::Target {
2790 &self.app
2791 }
2792}
2793
2794impl<M> DerefMut for ViewContext<'_, M> {
2795 fn deref_mut(&mut self) -> &mut Self::Target {
2796 &mut self.app
2797 }
2798}
2799
2800impl<M> AsMut<MutableAppContext> for ViewContext<'_, M> {
2801 fn as_mut(&mut self) -> &mut MutableAppContext {
2802 self.app
2803 }
2804}
2805
2806impl<V> ReadModel for ViewContext<'_, V> {
2807 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2808 self.app.read_model(handle)
2809 }
2810}
2811
2812impl<V> UpgradeModelHandle for ViewContext<'_, V> {
2813 fn upgrade_model_handle<T: Entity>(
2814 &self,
2815 handle: &WeakModelHandle<T>,
2816 ) -> Option<ModelHandle<T>> {
2817 self.cx.upgrade_model_handle(handle)
2818 }
2819
2820 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
2821 self.cx.model_handle_is_upgradable(handle)
2822 }
2823
2824 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
2825 self.cx.upgrade_any_model_handle(handle)
2826 }
2827}
2828
2829impl<V> UpgradeViewHandle for ViewContext<'_, V> {
2830 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
2831 self.cx.upgrade_view_handle(handle)
2832 }
2833}
2834
2835impl<V: View> UpdateModel for ViewContext<'_, V> {
2836 fn update_model<T: Entity, O>(
2837 &mut self,
2838 handle: &ModelHandle<T>,
2839 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
2840 ) -> O {
2841 self.app.update_model(handle, update)
2842 }
2843}
2844
2845impl<V: View> ReadView for ViewContext<'_, V> {
2846 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2847 self.app.read_view(handle)
2848 }
2849}
2850
2851impl<V: View> UpdateView for ViewContext<'_, V> {
2852 fn update_view<T, S>(
2853 &mut self,
2854 handle: &ViewHandle<T>,
2855 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
2856 ) -> S
2857 where
2858 T: View,
2859 {
2860 self.app.update_view(handle, update)
2861 }
2862}
2863
2864impl<V: View> ElementStateContext for ViewContext<'_, V> {
2865 fn current_view_id(&self) -> usize {
2866 self.view_id
2867 }
2868}
2869
2870pub trait Handle<T> {
2871 type Weak: 'static;
2872 fn id(&self) -> usize;
2873 fn location(&self) -> EntityLocation;
2874 fn downgrade(&self) -> Self::Weak;
2875 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
2876 where
2877 Self: Sized;
2878}
2879
2880#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
2881pub enum EntityLocation {
2882 Model(usize),
2883 View(usize, usize),
2884}
2885
2886pub struct ModelHandle<T: Entity> {
2887 model_id: usize,
2888 model_type: PhantomData<T>,
2889 ref_counts: Arc<Mutex<RefCounts>>,
2890
2891 #[cfg(any(test, feature = "test-support"))]
2892 handle_id: usize,
2893}
2894
2895impl<T: Entity> ModelHandle<T> {
2896 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
2897 ref_counts.lock().inc_model(model_id);
2898
2899 #[cfg(any(test, feature = "test-support"))]
2900 let handle_id = ref_counts
2901 .lock()
2902 .leak_detector
2903 .lock()
2904 .handle_created(Some(type_name::<T>()), model_id);
2905
2906 Self {
2907 model_id,
2908 model_type: PhantomData,
2909 ref_counts: ref_counts.clone(),
2910
2911 #[cfg(any(test, feature = "test-support"))]
2912 handle_id,
2913 }
2914 }
2915
2916 pub fn downgrade(&self) -> WeakModelHandle<T> {
2917 WeakModelHandle::new(self.model_id)
2918 }
2919
2920 pub fn id(&self) -> usize {
2921 self.model_id
2922 }
2923
2924 pub fn read<'a, C: ReadModel>(&self, cx: &'a C) -> &'a T {
2925 cx.read_model(self)
2926 }
2927
2928 pub fn read_with<'a, C, F, S>(&self, cx: &C, read: F) -> S
2929 where
2930 C: ReadModelWith,
2931 F: FnOnce(&T, &AppContext) -> S,
2932 {
2933 let mut read = Some(read);
2934 cx.read_model_with(self, &mut |model, cx| {
2935 let read = read.take().unwrap();
2936 read(model, cx)
2937 })
2938 }
2939
2940 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
2941 where
2942 C: UpdateModel,
2943 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
2944 {
2945 let mut update = Some(update);
2946 cx.update_model(self, &mut |model, cx| {
2947 let update = update.take().unwrap();
2948 update(model, cx)
2949 })
2950 }
2951
2952 #[cfg(any(test, feature = "test-support"))]
2953 pub fn next_notification(&self, cx: &TestAppContext) -> impl Future<Output = ()> {
2954 use postage::prelude::{Sink as _, Stream as _};
2955
2956 let (mut tx, mut rx) = postage::mpsc::channel(1);
2957 let mut cx = cx.cx.borrow_mut();
2958 let subscription = cx.observe(self, move |_, _| {
2959 tx.try_send(()).ok();
2960 });
2961
2962 let duration = if std::env::var("CI").is_ok() {
2963 Duration::from_secs(5)
2964 } else {
2965 Duration::from_secs(1)
2966 };
2967
2968 async move {
2969 let notification = crate::util::timeout(duration, rx.recv())
2970 .await
2971 .expect("next notification timed out");
2972 drop(subscription);
2973 notification.expect("model dropped while test was waiting for its next notification")
2974 }
2975 }
2976
2977 #[cfg(any(test, feature = "test-support"))]
2978 pub fn next_event(&self, cx: &TestAppContext) -> impl Future<Output = T::Event>
2979 where
2980 T::Event: Clone,
2981 {
2982 use postage::prelude::{Sink as _, Stream as _};
2983
2984 let (mut tx, mut rx) = postage::mpsc::channel(1);
2985 let mut cx = cx.cx.borrow_mut();
2986 let subscription = cx.subscribe(self, move |_, event, _| {
2987 tx.blocking_send(event.clone()).ok();
2988 });
2989
2990 let duration = if std::env::var("CI").is_ok() {
2991 Duration::from_secs(5)
2992 } else {
2993 Duration::from_secs(1)
2994 };
2995
2996 async move {
2997 let event = crate::util::timeout(duration, rx.recv())
2998 .await
2999 .expect("next event timed out");
3000 drop(subscription);
3001 event.expect("model dropped while test was waiting for its next event")
3002 }
3003 }
3004
3005 #[cfg(any(test, feature = "test-support"))]
3006 pub fn condition(
3007 &self,
3008 cx: &TestAppContext,
3009 mut predicate: impl FnMut(&T, &AppContext) -> bool,
3010 ) -> impl Future<Output = ()> {
3011 use postage::prelude::{Sink as _, Stream as _};
3012
3013 let (tx, mut rx) = postage::mpsc::channel(1024);
3014
3015 let mut cx = cx.cx.borrow_mut();
3016 let subscriptions = (
3017 cx.observe(self, {
3018 let mut tx = tx.clone();
3019 move |_, _| {
3020 tx.blocking_send(()).ok();
3021 }
3022 }),
3023 cx.subscribe(self, {
3024 let mut tx = tx.clone();
3025 move |_, _, _| {
3026 tx.blocking_send(()).ok();
3027 }
3028 }),
3029 );
3030
3031 let cx = cx.weak_self.as_ref().unwrap().upgrade().unwrap();
3032 let handle = self.downgrade();
3033 let duration = if std::env::var("CI").is_ok() {
3034 Duration::from_secs(5)
3035 } else {
3036 Duration::from_secs(1)
3037 };
3038
3039 async move {
3040 crate::util::timeout(duration, async move {
3041 loop {
3042 {
3043 let cx = cx.borrow();
3044 let cx = cx.as_ref();
3045 if predicate(
3046 handle
3047 .upgrade(cx)
3048 .expect("model dropped with pending condition")
3049 .read(cx),
3050 cx,
3051 ) {
3052 break;
3053 }
3054 }
3055
3056 cx.borrow().foreground().start_waiting();
3057 rx.recv()
3058 .await
3059 .expect("model dropped with pending condition");
3060 cx.borrow().foreground().finish_waiting();
3061 }
3062 })
3063 .await
3064 .expect("condition timed out");
3065 drop(subscriptions);
3066 }
3067 }
3068}
3069
3070impl<T: Entity> Clone for ModelHandle<T> {
3071 fn clone(&self) -> Self {
3072 Self::new(self.model_id, &self.ref_counts)
3073 }
3074}
3075
3076impl<T: Entity> PartialEq for ModelHandle<T> {
3077 fn eq(&self, other: &Self) -> bool {
3078 self.model_id == other.model_id
3079 }
3080}
3081
3082impl<T: Entity> Eq for ModelHandle<T> {}
3083
3084impl<T: Entity> PartialEq<WeakModelHandle<T>> for ModelHandle<T> {
3085 fn eq(&self, other: &WeakModelHandle<T>) -> bool {
3086 self.model_id == other.model_id
3087 }
3088}
3089
3090impl<T: Entity> Hash for ModelHandle<T> {
3091 fn hash<H: Hasher>(&self, state: &mut H) {
3092 self.model_id.hash(state);
3093 }
3094}
3095
3096impl<T: Entity> std::borrow::Borrow<usize> for ModelHandle<T> {
3097 fn borrow(&self) -> &usize {
3098 &self.model_id
3099 }
3100}
3101
3102impl<T: Entity> Debug for ModelHandle<T> {
3103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3104 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
3105 .field(&self.model_id)
3106 .finish()
3107 }
3108}
3109
3110unsafe impl<T: Entity> Send for ModelHandle<T> {}
3111unsafe impl<T: Entity> Sync for ModelHandle<T> {}
3112
3113impl<T: Entity> Drop for ModelHandle<T> {
3114 fn drop(&mut self) {
3115 let mut ref_counts = self.ref_counts.lock();
3116 ref_counts.dec_model(self.model_id);
3117
3118 #[cfg(any(test, feature = "test-support"))]
3119 ref_counts
3120 .leak_detector
3121 .lock()
3122 .handle_dropped(self.model_id, self.handle_id);
3123 }
3124}
3125
3126impl<T: Entity> Handle<T> for ModelHandle<T> {
3127 type Weak = WeakModelHandle<T>;
3128
3129 fn id(&self) -> usize {
3130 self.model_id
3131 }
3132
3133 fn location(&self) -> EntityLocation {
3134 EntityLocation::Model(self.model_id)
3135 }
3136
3137 fn downgrade(&self) -> Self::Weak {
3138 self.downgrade()
3139 }
3140
3141 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
3142 where
3143 Self: Sized,
3144 {
3145 weak.upgrade(cx)
3146 }
3147}
3148
3149pub struct WeakModelHandle<T> {
3150 model_id: usize,
3151 model_type: PhantomData<T>,
3152}
3153
3154unsafe impl<T> Send for WeakModelHandle<T> {}
3155unsafe impl<T> Sync for WeakModelHandle<T> {}
3156
3157impl<T: Entity> WeakModelHandle<T> {
3158 fn new(model_id: usize) -> Self {
3159 Self {
3160 model_id,
3161 model_type: PhantomData,
3162 }
3163 }
3164
3165 pub fn id(&self) -> usize {
3166 self.model_id
3167 }
3168
3169 pub fn is_upgradable(&self, cx: &impl UpgradeModelHandle) -> bool {
3170 cx.model_handle_is_upgradable(self)
3171 }
3172
3173 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<ModelHandle<T>> {
3174 cx.upgrade_model_handle(self)
3175 }
3176}
3177
3178impl<T> Hash for WeakModelHandle<T> {
3179 fn hash<H: Hasher>(&self, state: &mut H) {
3180 self.model_id.hash(state)
3181 }
3182}
3183
3184impl<T> PartialEq for WeakModelHandle<T> {
3185 fn eq(&self, other: &Self) -> bool {
3186 self.model_id == other.model_id
3187 }
3188}
3189
3190impl<T> Eq for WeakModelHandle<T> {}
3191
3192impl<T> Clone for WeakModelHandle<T> {
3193 fn clone(&self) -> Self {
3194 Self {
3195 model_id: self.model_id,
3196 model_type: PhantomData,
3197 }
3198 }
3199}
3200
3201impl<T> Copy for WeakModelHandle<T> {}
3202
3203pub struct ViewHandle<T> {
3204 window_id: usize,
3205 view_id: usize,
3206 view_type: PhantomData<T>,
3207 ref_counts: Arc<Mutex<RefCounts>>,
3208 #[cfg(any(test, feature = "test-support"))]
3209 handle_id: usize,
3210}
3211
3212impl<T: View> ViewHandle<T> {
3213 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
3214 ref_counts.lock().inc_view(window_id, view_id);
3215 #[cfg(any(test, feature = "test-support"))]
3216 let handle_id = ref_counts
3217 .lock()
3218 .leak_detector
3219 .lock()
3220 .handle_created(Some(type_name::<T>()), view_id);
3221
3222 Self {
3223 window_id,
3224 view_id,
3225 view_type: PhantomData,
3226 ref_counts: ref_counts.clone(),
3227
3228 #[cfg(any(test, feature = "test-support"))]
3229 handle_id,
3230 }
3231 }
3232
3233 pub fn downgrade(&self) -> WeakViewHandle<T> {
3234 WeakViewHandle::new(self.window_id, self.view_id)
3235 }
3236
3237 pub fn window_id(&self) -> usize {
3238 self.window_id
3239 }
3240
3241 pub fn id(&self) -> usize {
3242 self.view_id
3243 }
3244
3245 pub fn read<'a, C: ReadView>(&self, cx: &'a C) -> &'a T {
3246 cx.read_view(self)
3247 }
3248
3249 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
3250 where
3251 C: ReadViewWith,
3252 F: FnOnce(&T, &AppContext) -> S,
3253 {
3254 let mut read = Some(read);
3255 cx.read_view_with(self, &mut |view, cx| {
3256 let read = read.take().unwrap();
3257 read(view, cx)
3258 })
3259 }
3260
3261 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
3262 where
3263 C: UpdateView,
3264 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
3265 {
3266 let mut update = Some(update);
3267 cx.update_view(self, &mut |view, cx| {
3268 let update = update.take().unwrap();
3269 update(view, cx)
3270 })
3271 }
3272
3273 pub fn defer<C, F>(&self, cx: &mut C, update: F)
3274 where
3275 C: AsMut<MutableAppContext>,
3276 F: 'static + FnOnce(&mut T, &mut ViewContext<T>),
3277 {
3278 let this = self.clone();
3279 cx.as_mut().defer(Box::new(move |cx| {
3280 this.update(cx, |view, cx| update(view, cx));
3281 }));
3282 }
3283
3284 pub fn is_focused(&self, cx: &AppContext) -> bool {
3285 cx.focused_view_id(self.window_id)
3286 .map_or(false, |focused_id| focused_id == self.view_id)
3287 }
3288
3289 #[cfg(any(test, feature = "test-support"))]
3290 pub fn next_notification(&self, cx: &TestAppContext) -> impl Future<Output = ()> {
3291 use postage::prelude::{Sink as _, Stream as _};
3292
3293 let (mut tx, mut rx) = postage::mpsc::channel(1);
3294 let mut cx = cx.cx.borrow_mut();
3295 let subscription = cx.observe(self, move |_, _| {
3296 tx.try_send(()).ok();
3297 });
3298
3299 let duration = if std::env::var("CI").is_ok() {
3300 Duration::from_secs(5)
3301 } else {
3302 Duration::from_secs(1)
3303 };
3304
3305 async move {
3306 let notification = crate::util::timeout(duration, rx.recv())
3307 .await
3308 .expect("next notification timed out");
3309 drop(subscription);
3310 notification.expect("model dropped while test was waiting for its next notification")
3311 }
3312 }
3313
3314 #[cfg(any(test, feature = "test-support"))]
3315 pub fn condition(
3316 &self,
3317 cx: &TestAppContext,
3318 mut predicate: impl FnMut(&T, &AppContext) -> bool,
3319 ) -> impl Future<Output = ()> {
3320 use postage::prelude::{Sink as _, Stream as _};
3321
3322 let (tx, mut rx) = postage::mpsc::channel(1024);
3323
3324 let mut cx = cx.cx.borrow_mut();
3325 let subscriptions = self.update(&mut *cx, |_, cx| {
3326 (
3327 cx.observe(self, {
3328 let mut tx = tx.clone();
3329 move |_, _, _| {
3330 tx.blocking_send(()).ok();
3331 }
3332 }),
3333 cx.subscribe(self, {
3334 let mut tx = tx.clone();
3335 move |_, _, _, _| {
3336 tx.blocking_send(()).ok();
3337 }
3338 }),
3339 )
3340 });
3341
3342 let cx = cx.weak_self.as_ref().unwrap().upgrade().unwrap();
3343 let handle = self.downgrade();
3344 let duration = if std::env::var("CI").is_ok() {
3345 Duration::from_secs(2)
3346 } else {
3347 Duration::from_millis(500)
3348 };
3349
3350 async move {
3351 crate::util::timeout(duration, async move {
3352 loop {
3353 {
3354 let cx = cx.borrow();
3355 let cx = cx.as_ref();
3356 if predicate(
3357 handle
3358 .upgrade(cx)
3359 .expect("view dropped with pending condition")
3360 .read(cx),
3361 cx,
3362 ) {
3363 break;
3364 }
3365 }
3366
3367 cx.borrow().foreground().start_waiting();
3368 rx.recv()
3369 .await
3370 .expect("view dropped with pending condition");
3371 cx.borrow().foreground().finish_waiting();
3372 }
3373 })
3374 .await
3375 .expect("condition timed out");
3376 drop(subscriptions);
3377 }
3378 }
3379}
3380
3381impl<T: View> Clone for ViewHandle<T> {
3382 fn clone(&self) -> Self {
3383 ViewHandle::new(self.window_id, self.view_id, &self.ref_counts)
3384 }
3385}
3386
3387impl<T> PartialEq for ViewHandle<T> {
3388 fn eq(&self, other: &Self) -> bool {
3389 self.window_id == other.window_id && self.view_id == other.view_id
3390 }
3391}
3392
3393impl<T> Eq for ViewHandle<T> {}
3394
3395impl<T> Debug for ViewHandle<T> {
3396 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3397 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
3398 .field("window_id", &self.window_id)
3399 .field("view_id", &self.view_id)
3400 .finish()
3401 }
3402}
3403
3404impl<T> Drop for ViewHandle<T> {
3405 fn drop(&mut self) {
3406 self.ref_counts
3407 .lock()
3408 .dec_view(self.window_id, self.view_id);
3409 #[cfg(any(test, feature = "test-support"))]
3410 self.ref_counts
3411 .lock()
3412 .leak_detector
3413 .lock()
3414 .handle_dropped(self.view_id, self.handle_id);
3415 }
3416}
3417
3418impl<T: View> Handle<T> for ViewHandle<T> {
3419 type Weak = WeakViewHandle<T>;
3420
3421 fn id(&self) -> usize {
3422 self.view_id
3423 }
3424
3425 fn location(&self) -> EntityLocation {
3426 EntityLocation::View(self.window_id, self.view_id)
3427 }
3428
3429 fn downgrade(&self) -> Self::Weak {
3430 self.downgrade()
3431 }
3432
3433 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
3434 where
3435 Self: Sized,
3436 {
3437 weak.upgrade(cx)
3438 }
3439}
3440
3441pub struct AnyViewHandle {
3442 window_id: usize,
3443 view_id: usize,
3444 view_type: TypeId,
3445 ref_counts: Arc<Mutex<RefCounts>>,
3446
3447 #[cfg(any(test, feature = "test-support"))]
3448 handle_id: usize,
3449}
3450
3451impl AnyViewHandle {
3452 fn new(
3453 window_id: usize,
3454 view_id: usize,
3455 view_type: TypeId,
3456 ref_counts: Arc<Mutex<RefCounts>>,
3457 ) -> Self {
3458 ref_counts.lock().inc_view(window_id, view_id);
3459
3460 #[cfg(any(test, feature = "test-support"))]
3461 let handle_id = ref_counts
3462 .lock()
3463 .leak_detector
3464 .lock()
3465 .handle_created(None, view_id);
3466
3467 Self {
3468 window_id,
3469 view_id,
3470 view_type,
3471 ref_counts,
3472 #[cfg(any(test, feature = "test-support"))]
3473 handle_id,
3474 }
3475 }
3476
3477 pub fn id(&self) -> usize {
3478 self.view_id
3479 }
3480
3481 pub fn is<T: 'static>(&self) -> bool {
3482 TypeId::of::<T>() == self.view_type
3483 }
3484
3485 pub fn is_focused(&self, cx: &AppContext) -> bool {
3486 cx.focused_view_id(self.window_id)
3487 .map_or(false, |focused_id| focused_id == self.view_id)
3488 }
3489
3490 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
3491 if self.is::<T>() {
3492 let result = Some(ViewHandle {
3493 window_id: self.window_id,
3494 view_id: self.view_id,
3495 ref_counts: self.ref_counts.clone(),
3496 view_type: PhantomData,
3497 #[cfg(any(test, feature = "test-support"))]
3498 handle_id: self.handle_id,
3499 });
3500 unsafe {
3501 Arc::decrement_strong_count(&self.ref_counts);
3502 }
3503 std::mem::forget(self);
3504 result
3505 } else {
3506 None
3507 }
3508 }
3509}
3510
3511impl Clone for AnyViewHandle {
3512 fn clone(&self) -> Self {
3513 Self::new(
3514 self.window_id,
3515 self.view_id,
3516 self.view_type,
3517 self.ref_counts.clone(),
3518 )
3519 }
3520}
3521
3522impl From<&AnyViewHandle> for AnyViewHandle {
3523 fn from(handle: &AnyViewHandle) -> Self {
3524 handle.clone()
3525 }
3526}
3527
3528impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
3529 fn from(handle: &ViewHandle<T>) -> Self {
3530 Self::new(
3531 handle.window_id,
3532 handle.view_id,
3533 TypeId::of::<T>(),
3534 handle.ref_counts.clone(),
3535 )
3536 }
3537}
3538
3539impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
3540 fn from(handle: ViewHandle<T>) -> Self {
3541 let any_handle = AnyViewHandle {
3542 window_id: handle.window_id,
3543 view_id: handle.view_id,
3544 view_type: TypeId::of::<T>(),
3545 ref_counts: handle.ref_counts.clone(),
3546 #[cfg(any(test, feature = "test-support"))]
3547 handle_id: handle.handle_id,
3548 };
3549 unsafe {
3550 Arc::decrement_strong_count(&handle.ref_counts);
3551 }
3552 std::mem::forget(handle);
3553 any_handle
3554 }
3555}
3556
3557impl Drop for AnyViewHandle {
3558 fn drop(&mut self) {
3559 self.ref_counts
3560 .lock()
3561 .dec_view(self.window_id, self.view_id);
3562 #[cfg(any(test, feature = "test-support"))]
3563 self.ref_counts
3564 .lock()
3565 .leak_detector
3566 .lock()
3567 .handle_dropped(self.view_id, self.handle_id);
3568 }
3569}
3570
3571pub struct AnyModelHandle {
3572 model_id: usize,
3573 model_type: TypeId,
3574 ref_counts: Arc<Mutex<RefCounts>>,
3575
3576 #[cfg(any(test, feature = "test-support"))]
3577 handle_id: usize,
3578}
3579
3580impl AnyModelHandle {
3581 fn new(model_id: usize, model_type: TypeId, ref_counts: Arc<Mutex<RefCounts>>) -> Self {
3582 ref_counts.lock().inc_model(model_id);
3583
3584 #[cfg(any(test, feature = "test-support"))]
3585 let handle_id = ref_counts
3586 .lock()
3587 .leak_detector
3588 .lock()
3589 .handle_created(None, model_id);
3590
3591 Self {
3592 model_id,
3593 model_type,
3594 ref_counts,
3595
3596 #[cfg(any(test, feature = "test-support"))]
3597 handle_id,
3598 }
3599 }
3600
3601 pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> {
3602 if self.is::<T>() {
3603 let result = Some(ModelHandle {
3604 model_id: self.model_id,
3605 model_type: PhantomData,
3606 ref_counts: self.ref_counts.clone(),
3607
3608 #[cfg(any(test, feature = "test-support"))]
3609 handle_id: self.handle_id,
3610 });
3611 unsafe {
3612 Arc::decrement_strong_count(&self.ref_counts);
3613 }
3614 std::mem::forget(self);
3615 result
3616 } else {
3617 None
3618 }
3619 }
3620
3621 pub fn downgrade(&self) -> AnyWeakModelHandle {
3622 AnyWeakModelHandle {
3623 model_id: self.model_id,
3624 model_type: self.model_type,
3625 }
3626 }
3627
3628 pub fn is<T: Entity>(&self) -> bool {
3629 self.model_type == TypeId::of::<T>()
3630 }
3631}
3632
3633impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
3634 fn from(handle: ModelHandle<T>) -> Self {
3635 Self::new(
3636 handle.model_id,
3637 TypeId::of::<T>(),
3638 handle.ref_counts.clone(),
3639 )
3640 }
3641}
3642
3643impl Clone for AnyModelHandle {
3644 fn clone(&self) -> Self {
3645 Self::new(self.model_id, self.model_type, self.ref_counts.clone())
3646 }
3647}
3648
3649impl Drop for AnyModelHandle {
3650 fn drop(&mut self) {
3651 let mut ref_counts = self.ref_counts.lock();
3652 ref_counts.dec_model(self.model_id);
3653
3654 #[cfg(any(test, feature = "test-support"))]
3655 ref_counts
3656 .leak_detector
3657 .lock()
3658 .handle_dropped(self.model_id, self.handle_id);
3659 }
3660}
3661
3662pub struct AnyWeakModelHandle {
3663 model_id: usize,
3664 model_type: TypeId,
3665}
3666
3667impl AnyWeakModelHandle {
3668 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<AnyModelHandle> {
3669 cx.upgrade_any_model_handle(self)
3670 }
3671}
3672
3673impl<T: Entity> From<WeakModelHandle<T>> for AnyWeakModelHandle {
3674 fn from(handle: WeakModelHandle<T>) -> Self {
3675 AnyWeakModelHandle {
3676 model_id: handle.model_id,
3677 model_type: TypeId::of::<T>(),
3678 }
3679 }
3680}
3681
3682pub struct WeakViewHandle<T> {
3683 window_id: usize,
3684 view_id: usize,
3685 view_type: PhantomData<T>,
3686}
3687
3688impl<T: View> WeakViewHandle<T> {
3689 fn new(window_id: usize, view_id: usize) -> Self {
3690 Self {
3691 window_id,
3692 view_id,
3693 view_type: PhantomData,
3694 }
3695 }
3696
3697 pub fn id(&self) -> usize {
3698 self.view_id
3699 }
3700
3701 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<ViewHandle<T>> {
3702 cx.upgrade_view_handle(self)
3703 }
3704}
3705
3706impl<T> Clone for WeakViewHandle<T> {
3707 fn clone(&self) -> Self {
3708 Self {
3709 window_id: self.window_id,
3710 view_id: self.view_id,
3711 view_type: PhantomData,
3712 }
3713 }
3714}
3715
3716impl<T> PartialEq for WeakViewHandle<T> {
3717 fn eq(&self, other: &Self) -> bool {
3718 self.window_id == other.window_id && self.view_id == other.view_id
3719 }
3720}
3721
3722impl<T> Eq for WeakViewHandle<T> {}
3723
3724impl<T> Hash for WeakViewHandle<T> {
3725 fn hash<H: Hasher>(&self, state: &mut H) {
3726 self.window_id.hash(state);
3727 self.view_id.hash(state);
3728 }
3729}
3730
3731#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3732pub struct ElementStateId {
3733 view_id: usize,
3734 element_id: usize,
3735 tag: TypeId,
3736}
3737
3738pub struct ElementStateHandle<T> {
3739 value_type: PhantomData<T>,
3740 id: ElementStateId,
3741 ref_counts: Weak<Mutex<RefCounts>>,
3742}
3743
3744impl<T: 'static> ElementStateHandle<T> {
3745 fn new(id: ElementStateId, frame_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
3746 ref_counts.lock().inc_element_state(id, frame_id);
3747 Self {
3748 value_type: PhantomData,
3749 id,
3750 ref_counts: Arc::downgrade(ref_counts),
3751 }
3752 }
3753
3754 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
3755 cx.element_states
3756 .get(&self.id)
3757 .unwrap()
3758 .downcast_ref()
3759 .unwrap()
3760 }
3761
3762 pub fn update<C, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R
3763 where
3764 C: DerefMut<Target = MutableAppContext>,
3765 {
3766 let mut element_state = cx.deref_mut().cx.element_states.remove(&self.id).unwrap();
3767 let result = f(element_state.downcast_mut().unwrap(), cx);
3768 cx.deref_mut()
3769 .cx
3770 .element_states
3771 .insert(self.id, element_state);
3772 result
3773 }
3774}
3775
3776impl<T> Drop for ElementStateHandle<T> {
3777 fn drop(&mut self) {
3778 if let Some(ref_counts) = self.ref_counts.upgrade() {
3779 ref_counts.lock().dec_element_state(self.id);
3780 }
3781 }
3782}
3783
3784pub struct CursorStyleHandle {
3785 id: usize,
3786 next_cursor_style_handle_id: Arc<AtomicUsize>,
3787 platform: Arc<dyn Platform>,
3788}
3789
3790impl Drop for CursorStyleHandle {
3791 fn drop(&mut self) {
3792 if self.id + 1 == self.next_cursor_style_handle_id.load(SeqCst) {
3793 self.platform.set_cursor_style(CursorStyle::Arrow);
3794 }
3795 }
3796}
3797
3798#[must_use]
3799pub enum Subscription {
3800 Subscription {
3801 id: usize,
3802 entity_id: usize,
3803 subscriptions: Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, SubscriptionCallback>>>>>,
3804 },
3805 Observation {
3806 id: usize,
3807 entity_id: usize,
3808 observations: Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, ObservationCallback>>>>>,
3809 },
3810 ReleaseObservation {
3811 id: usize,
3812 entity_id: usize,
3813 observations:
3814 Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>>,
3815 },
3816}
3817
3818impl Subscription {
3819 pub fn detach(&mut self) {
3820 match self {
3821 Subscription::Subscription { subscriptions, .. } => {
3822 subscriptions.take();
3823 }
3824 Subscription::Observation { observations, .. } => {
3825 observations.take();
3826 }
3827 Subscription::ReleaseObservation { observations, .. } => {
3828 observations.take();
3829 }
3830 }
3831 }
3832}
3833
3834impl Drop for Subscription {
3835 fn drop(&mut self) {
3836 match self {
3837 Subscription::Observation {
3838 id,
3839 entity_id,
3840 observations,
3841 } => {
3842 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
3843 if let Some(observations) = observations.lock().get_mut(entity_id) {
3844 observations.remove(id);
3845 }
3846 }
3847 }
3848 Subscription::ReleaseObservation {
3849 id,
3850 entity_id,
3851 observations,
3852 } => {
3853 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
3854 if let Some(observations) = observations.lock().get_mut(entity_id) {
3855 observations.remove(id);
3856 }
3857 }
3858 }
3859 Subscription::Subscription {
3860 id,
3861 entity_id,
3862 subscriptions,
3863 } => {
3864 if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
3865 if let Some(subscriptions) = subscriptions.lock().get_mut(entity_id) {
3866 subscriptions.remove(id);
3867 }
3868 }
3869 }
3870 }
3871 }
3872}
3873
3874lazy_static! {
3875 static ref LEAK_BACKTRACE: bool =
3876 std::env::var("LEAK_BACKTRACE").map_or(false, |b| !b.is_empty());
3877}
3878
3879#[cfg(any(test, feature = "test-support"))]
3880#[derive(Default)]
3881pub struct LeakDetector {
3882 next_handle_id: usize,
3883 handle_backtraces: HashMap<
3884 usize,
3885 (
3886 Option<&'static str>,
3887 HashMap<usize, Option<backtrace::Backtrace>>,
3888 ),
3889 >,
3890}
3891
3892#[cfg(any(test, feature = "test-support"))]
3893impl LeakDetector {
3894 fn handle_created(&mut self, type_name: Option<&'static str>, entity_id: usize) -> usize {
3895 let handle_id = post_inc(&mut self.next_handle_id);
3896 let entry = self.handle_backtraces.entry(entity_id).or_default();
3897 let backtrace = if *LEAK_BACKTRACE {
3898 Some(backtrace::Backtrace::new_unresolved())
3899 } else {
3900 None
3901 };
3902 if let Some(type_name) = type_name {
3903 entry.0.get_or_insert(type_name);
3904 }
3905 entry.1.insert(handle_id, backtrace);
3906 handle_id
3907 }
3908
3909 fn handle_dropped(&mut self, entity_id: usize, handle_id: usize) {
3910 if let Some((_, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
3911 assert!(backtraces.remove(&handle_id).is_some());
3912 if backtraces.is_empty() {
3913 self.handle_backtraces.remove(&entity_id);
3914 }
3915 }
3916 }
3917
3918 pub fn detect(&mut self) {
3919 let mut found_leaks = false;
3920 for (id, (type_name, backtraces)) in self.handle_backtraces.iter_mut() {
3921 eprintln!(
3922 "leaked {} handles to {:?} {}",
3923 backtraces.len(),
3924 type_name.unwrap_or("entity"),
3925 id
3926 );
3927 for trace in backtraces.values_mut() {
3928 if let Some(trace) = trace {
3929 trace.resolve();
3930 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
3931 }
3932 }
3933 found_leaks = true;
3934 }
3935
3936 let hint = if *LEAK_BACKTRACE {
3937 ""
3938 } else {
3939 " – set LEAK_BACKTRACE=1 for more information"
3940 };
3941 assert!(!found_leaks, "detected leaked handles{}", hint);
3942 }
3943}
3944
3945#[derive(Default)]
3946struct RefCounts {
3947 entity_counts: HashMap<usize, usize>,
3948 element_state_counts: HashMap<ElementStateId, ElementStateRefCount>,
3949 dropped_models: HashSet<usize>,
3950 dropped_views: HashSet<(usize, usize)>,
3951 dropped_element_states: HashSet<ElementStateId>,
3952
3953 #[cfg(any(test, feature = "test-support"))]
3954 leak_detector: Arc<Mutex<LeakDetector>>,
3955}
3956
3957struct ElementStateRefCount {
3958 ref_count: usize,
3959 frame_id: usize,
3960}
3961
3962impl RefCounts {
3963 fn inc_model(&mut self, model_id: usize) {
3964 match self.entity_counts.entry(model_id) {
3965 Entry::Occupied(mut entry) => {
3966 *entry.get_mut() += 1;
3967 }
3968 Entry::Vacant(entry) => {
3969 entry.insert(1);
3970 self.dropped_models.remove(&model_id);
3971 }
3972 }
3973 }
3974
3975 fn inc_view(&mut self, window_id: usize, view_id: usize) {
3976 match self.entity_counts.entry(view_id) {
3977 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
3978 Entry::Vacant(entry) => {
3979 entry.insert(1);
3980 self.dropped_views.remove(&(window_id, view_id));
3981 }
3982 }
3983 }
3984
3985 fn inc_element_state(&mut self, id: ElementStateId, frame_id: usize) {
3986 match self.element_state_counts.entry(id) {
3987 Entry::Occupied(mut entry) => {
3988 let entry = entry.get_mut();
3989 if entry.frame_id == frame_id || entry.ref_count >= 2 {
3990 panic!("used the same element state more than once in the same frame");
3991 }
3992 entry.ref_count += 1;
3993 entry.frame_id = frame_id;
3994 }
3995 Entry::Vacant(entry) => {
3996 entry.insert(ElementStateRefCount {
3997 ref_count: 1,
3998 frame_id,
3999 });
4000 self.dropped_element_states.remove(&id);
4001 }
4002 }
4003 }
4004
4005 fn dec_model(&mut self, model_id: usize) {
4006 let count = self.entity_counts.get_mut(&model_id).unwrap();
4007 *count -= 1;
4008 if *count == 0 {
4009 self.entity_counts.remove(&model_id);
4010 self.dropped_models.insert(model_id);
4011 }
4012 }
4013
4014 fn dec_view(&mut self, window_id: usize, view_id: usize) {
4015 let count = self.entity_counts.get_mut(&view_id).unwrap();
4016 *count -= 1;
4017 if *count == 0 {
4018 self.entity_counts.remove(&view_id);
4019 self.dropped_views.insert((window_id, view_id));
4020 }
4021 }
4022
4023 fn dec_element_state(&mut self, id: ElementStateId) {
4024 let entry = self.element_state_counts.get_mut(&id).unwrap();
4025 entry.ref_count -= 1;
4026 if entry.ref_count == 0 {
4027 self.element_state_counts.remove(&id);
4028 self.dropped_element_states.insert(id);
4029 }
4030 }
4031
4032 fn is_entity_alive(&self, entity_id: usize) -> bool {
4033 self.entity_counts.contains_key(&entity_id)
4034 }
4035
4036 fn take_dropped(
4037 &mut self,
4038 ) -> (
4039 HashSet<usize>,
4040 HashSet<(usize, usize)>,
4041 HashSet<ElementStateId>,
4042 ) {
4043 (
4044 std::mem::take(&mut self.dropped_models),
4045 std::mem::take(&mut self.dropped_views),
4046 std::mem::take(&mut self.dropped_element_states),
4047 )
4048 }
4049}
4050
4051#[cfg(test)]
4052mod tests {
4053 use super::*;
4054 use crate::elements::*;
4055 use smol::future::poll_once;
4056 use std::{
4057 cell::Cell,
4058 sync::atomic::{AtomicUsize, Ordering::SeqCst},
4059 };
4060
4061 #[crate::test(self)]
4062 fn test_model_handles(cx: &mut MutableAppContext) {
4063 struct Model {
4064 other: Option<ModelHandle<Model>>,
4065 events: Vec<String>,
4066 }
4067
4068 impl Entity for Model {
4069 type Event = usize;
4070 }
4071
4072 impl Model {
4073 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
4074 if let Some(other) = other.as_ref() {
4075 cx.observe(other, |me, _, _| {
4076 me.events.push("notified".into());
4077 })
4078 .detach();
4079 cx.subscribe(other, |me, _, event, _| {
4080 me.events.push(format!("observed event {}", event));
4081 })
4082 .detach();
4083 }
4084
4085 Self {
4086 other,
4087 events: Vec::new(),
4088 }
4089 }
4090 }
4091
4092 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
4093 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
4094 assert_eq!(cx.cx.models.len(), 2);
4095
4096 handle_1.update(cx, |model, cx| {
4097 model.events.push("updated".into());
4098 cx.emit(1);
4099 cx.notify();
4100 cx.emit(2);
4101 });
4102 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
4103 assert_eq!(
4104 handle_2.read(cx).events,
4105 vec![
4106 "observed event 1".to_string(),
4107 "notified".to_string(),
4108 "observed event 2".to_string(),
4109 ]
4110 );
4111
4112 handle_2.update(cx, |model, _| {
4113 drop(handle_1);
4114 model.other.take();
4115 });
4116
4117 assert_eq!(cx.cx.models.len(), 1);
4118 assert!(cx.subscriptions.lock().is_empty());
4119 assert!(cx.observations.lock().is_empty());
4120 }
4121
4122 #[crate::test(self)]
4123 fn test_subscribe_and_emit_from_model(cx: &mut MutableAppContext) {
4124 #[derive(Default)]
4125 struct Model {
4126 events: Vec<usize>,
4127 }
4128
4129 impl Entity for Model {
4130 type Event = usize;
4131 }
4132
4133 let handle_1 = cx.add_model(|_| Model::default());
4134 let handle_2 = cx.add_model(|_| Model::default());
4135 handle_1.update(cx, |_, c| {
4136 c.subscribe(&handle_2, move |model: &mut Model, emitter, event, c| {
4137 model.events.push(*event);
4138
4139 c.subscribe(&emitter, |model, _, event, _| {
4140 model.events.push(*event * 2);
4141 })
4142 .detach();
4143 })
4144 .detach();
4145 });
4146
4147 handle_2.update(cx, |_, c| c.emit(7));
4148 assert_eq!(handle_1.read(cx).events, vec![7]);
4149
4150 handle_2.update(cx, |_, c| c.emit(5));
4151 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
4152 }
4153
4154 #[crate::test(self)]
4155 fn test_observe_and_notify_from_model(cx: &mut MutableAppContext) {
4156 #[derive(Default)]
4157 struct Model {
4158 count: usize,
4159 events: Vec<usize>,
4160 }
4161
4162 impl Entity for Model {
4163 type Event = ();
4164 }
4165
4166 let handle_1 = cx.add_model(|_| Model::default());
4167 let handle_2 = cx.add_model(|_| Model::default());
4168
4169 handle_1.update(cx, |_, c| {
4170 c.observe(&handle_2, move |model, observed, c| {
4171 model.events.push(observed.read(c).count);
4172 c.observe(&observed, |model, observed, c| {
4173 model.events.push(observed.read(c).count * 2);
4174 })
4175 .detach();
4176 })
4177 .detach();
4178 });
4179
4180 handle_2.update(cx, |model, c| {
4181 model.count = 7;
4182 c.notify()
4183 });
4184 assert_eq!(handle_1.read(cx).events, vec![7]);
4185
4186 handle_2.update(cx, |model, c| {
4187 model.count = 5;
4188 c.notify()
4189 });
4190 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10])
4191 }
4192
4193 #[crate::test(self)]
4194 fn test_view_handles(cx: &mut MutableAppContext) {
4195 struct View {
4196 other: Option<ViewHandle<View>>,
4197 events: Vec<String>,
4198 }
4199
4200 impl Entity for View {
4201 type Event = usize;
4202 }
4203
4204 impl super::View for View {
4205 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4206 Empty::new().boxed()
4207 }
4208
4209 fn ui_name() -> &'static str {
4210 "View"
4211 }
4212 }
4213
4214 impl View {
4215 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
4216 if let Some(other) = other.as_ref() {
4217 cx.subscribe(other, |me, _, event, _| {
4218 me.events.push(format!("observed event {}", event));
4219 })
4220 .detach();
4221 }
4222 Self {
4223 other,
4224 events: Vec::new(),
4225 }
4226 }
4227 }
4228
4229 let (window_id, _) = cx.add_window(Default::default(), |cx| View::new(None, cx));
4230 let handle_1 = cx.add_view(window_id, |cx| View::new(None, cx));
4231 let handle_2 = cx.add_view(window_id, |cx| View::new(Some(handle_1.clone()), cx));
4232 assert_eq!(cx.cx.views.len(), 3);
4233
4234 handle_1.update(cx, |view, cx| {
4235 view.events.push("updated".into());
4236 cx.emit(1);
4237 cx.emit(2);
4238 });
4239 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
4240 assert_eq!(
4241 handle_2.read(cx).events,
4242 vec![
4243 "observed event 1".to_string(),
4244 "observed event 2".to_string(),
4245 ]
4246 );
4247
4248 handle_2.update(cx, |view, _| {
4249 drop(handle_1);
4250 view.other.take();
4251 });
4252
4253 assert_eq!(cx.cx.views.len(), 2);
4254 assert!(cx.subscriptions.lock().is_empty());
4255 assert!(cx.observations.lock().is_empty());
4256 }
4257
4258 #[crate::test(self)]
4259 fn test_add_window(cx: &mut MutableAppContext) {
4260 struct View {
4261 mouse_down_count: Arc<AtomicUsize>,
4262 }
4263
4264 impl Entity for View {
4265 type Event = ();
4266 }
4267
4268 impl super::View for View {
4269 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4270 let mouse_down_count = self.mouse_down_count.clone();
4271 EventHandler::new(Empty::new().boxed())
4272 .on_mouse_down(move |_| {
4273 mouse_down_count.fetch_add(1, SeqCst);
4274 true
4275 })
4276 .boxed()
4277 }
4278
4279 fn ui_name() -> &'static str {
4280 "View"
4281 }
4282 }
4283
4284 let mouse_down_count = Arc::new(AtomicUsize::new(0));
4285 let (window_id, _) = cx.add_window(Default::default(), |_| View {
4286 mouse_down_count: mouse_down_count.clone(),
4287 });
4288 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
4289 // Ensure window's root element is in a valid lifecycle state.
4290 presenter.borrow_mut().dispatch_event(
4291 Event::LeftMouseDown {
4292 position: Default::default(),
4293 ctrl: false,
4294 alt: false,
4295 shift: false,
4296 cmd: false,
4297 click_count: 1,
4298 },
4299 cx,
4300 );
4301 assert_eq!(mouse_down_count.load(SeqCst), 1);
4302 }
4303
4304 #[crate::test(self)]
4305 fn test_entity_release_hooks(cx: &mut MutableAppContext) {
4306 struct Model {
4307 released: Rc<Cell<bool>>,
4308 }
4309
4310 struct View {
4311 released: Rc<Cell<bool>>,
4312 }
4313
4314 impl Entity for Model {
4315 type Event = ();
4316
4317 fn release(&mut self, _: &mut MutableAppContext) {
4318 self.released.set(true);
4319 }
4320 }
4321
4322 impl Entity for View {
4323 type Event = ();
4324
4325 fn release(&mut self, _: &mut MutableAppContext) {
4326 self.released.set(true);
4327 }
4328 }
4329
4330 impl super::View for View {
4331 fn ui_name() -> &'static str {
4332 "View"
4333 }
4334
4335 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4336 Empty::new().boxed()
4337 }
4338 }
4339
4340 let model_released = Rc::new(Cell::new(false));
4341 let model_release_observed = Rc::new(Cell::new(false));
4342 let view_released = Rc::new(Cell::new(false));
4343 let view_release_observed = Rc::new(Cell::new(false));
4344
4345 let model = cx.add_model(|_| Model {
4346 released: model_released.clone(),
4347 });
4348 let (window_id, view) = cx.add_window(Default::default(), |_| View {
4349 released: view_released.clone(),
4350 });
4351 assert!(!model_released.get());
4352 assert!(!view_released.get());
4353
4354 cx.observe_release(&model, {
4355 let model_release_observed = model_release_observed.clone();
4356 move |_| model_release_observed.set(true)
4357 })
4358 .detach();
4359 cx.observe_release(&view, {
4360 let view_release_observed = view_release_observed.clone();
4361 move |_| view_release_observed.set(true)
4362 })
4363 .detach();
4364
4365 cx.update(move |_| {
4366 drop(model);
4367 });
4368 assert!(model_released.get());
4369 assert!(model_release_observed.get());
4370
4371 drop(view);
4372 cx.remove_window(window_id);
4373 assert!(view_released.get());
4374 assert!(view_release_observed.get());
4375 }
4376
4377 #[crate::test(self)]
4378 fn test_subscribe_and_emit_from_view(cx: &mut MutableAppContext) {
4379 #[derive(Default)]
4380 struct View {
4381 events: Vec<usize>,
4382 }
4383
4384 impl Entity for View {
4385 type Event = usize;
4386 }
4387
4388 impl super::View for View {
4389 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4390 Empty::new().boxed()
4391 }
4392
4393 fn ui_name() -> &'static str {
4394 "View"
4395 }
4396 }
4397
4398 struct Model;
4399
4400 impl Entity for Model {
4401 type Event = usize;
4402 }
4403
4404 let (window_id, handle_1) = cx.add_window(Default::default(), |_| View::default());
4405 let handle_2 = cx.add_view(window_id, |_| View::default());
4406 let handle_3 = cx.add_model(|_| Model);
4407
4408 handle_1.update(cx, |_, c| {
4409 c.subscribe(&handle_2, move |me, emitter, event, c| {
4410 me.events.push(*event);
4411
4412 c.subscribe(&emitter, |me, _, event, _| {
4413 me.events.push(*event * 2);
4414 })
4415 .detach();
4416 })
4417 .detach();
4418
4419 c.subscribe(&handle_3, |me, _, event, _| {
4420 me.events.push(*event);
4421 })
4422 .detach();
4423 });
4424
4425 handle_2.update(cx, |_, c| c.emit(7));
4426 assert_eq!(handle_1.read(cx).events, vec![7]);
4427
4428 handle_2.update(cx, |_, c| c.emit(5));
4429 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
4430
4431 handle_3.update(cx, |_, c| c.emit(9));
4432 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10, 9]);
4433 }
4434
4435 #[crate::test(self)]
4436 fn test_dropping_subscribers(cx: &mut MutableAppContext) {
4437 struct View;
4438
4439 impl Entity for View {
4440 type Event = ();
4441 }
4442
4443 impl super::View for View {
4444 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4445 Empty::new().boxed()
4446 }
4447
4448 fn ui_name() -> &'static str {
4449 "View"
4450 }
4451 }
4452
4453 struct Model;
4454
4455 impl Entity for Model {
4456 type Event = ();
4457 }
4458
4459 let (window_id, _) = cx.add_window(Default::default(), |_| View);
4460 let observing_view = cx.add_view(window_id, |_| View);
4461 let emitting_view = cx.add_view(window_id, |_| View);
4462 let observing_model = cx.add_model(|_| Model);
4463 let observed_model = cx.add_model(|_| Model);
4464
4465 observing_view.update(cx, |_, cx| {
4466 cx.subscribe(&emitting_view, |_, _, _, _| {}).detach();
4467 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
4468 });
4469 observing_model.update(cx, |_, cx| {
4470 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
4471 });
4472
4473 cx.update(|_| {
4474 drop(observing_view);
4475 drop(observing_model);
4476 });
4477
4478 emitting_view.update(cx, |_, cx| cx.emit(()));
4479 observed_model.update(cx, |_, cx| cx.emit(()));
4480 }
4481
4482 #[crate::test(self)]
4483 fn test_observe_and_notify_from_view(cx: &mut MutableAppContext) {
4484 #[derive(Default)]
4485 struct View {
4486 events: Vec<usize>,
4487 }
4488
4489 impl Entity for View {
4490 type Event = usize;
4491 }
4492
4493 impl super::View for View {
4494 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4495 Empty::new().boxed()
4496 }
4497
4498 fn ui_name() -> &'static str {
4499 "View"
4500 }
4501 }
4502
4503 #[derive(Default)]
4504 struct Model {
4505 count: usize,
4506 }
4507
4508 impl Entity for Model {
4509 type Event = ();
4510 }
4511
4512 let (_, view) = cx.add_window(Default::default(), |_| View::default());
4513 let model = cx.add_model(|_| Model::default());
4514
4515 view.update(cx, |_, c| {
4516 c.observe(&model, |me, observed, c| {
4517 me.events.push(observed.read(c).count)
4518 })
4519 .detach();
4520 });
4521
4522 model.update(cx, |model, c| {
4523 model.count = 11;
4524 c.notify();
4525 });
4526 assert_eq!(view.read(cx).events, vec![11]);
4527 }
4528
4529 #[crate::test(self)]
4530 fn test_dropping_observers(cx: &mut MutableAppContext) {
4531 struct View;
4532
4533 impl Entity for View {
4534 type Event = ();
4535 }
4536
4537 impl super::View for View {
4538 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4539 Empty::new().boxed()
4540 }
4541
4542 fn ui_name() -> &'static str {
4543 "View"
4544 }
4545 }
4546
4547 struct Model;
4548
4549 impl Entity for Model {
4550 type Event = ();
4551 }
4552
4553 let (window_id, _) = cx.add_window(Default::default(), |_| View);
4554 let observing_view = cx.add_view(window_id, |_| View);
4555 let observing_model = cx.add_model(|_| Model);
4556 let observed_model = cx.add_model(|_| Model);
4557
4558 observing_view.update(cx, |_, cx| {
4559 cx.observe(&observed_model, |_, _, _| {}).detach();
4560 });
4561 observing_model.update(cx, |_, cx| {
4562 cx.observe(&observed_model, |_, _, _| {}).detach();
4563 });
4564
4565 cx.update(|_| {
4566 drop(observing_view);
4567 drop(observing_model);
4568 });
4569
4570 observed_model.update(cx, |_, cx| cx.notify());
4571 }
4572
4573 #[crate::test(self)]
4574 fn test_focus(cx: &mut MutableAppContext) {
4575 struct View {
4576 name: String,
4577 events: Arc<Mutex<Vec<String>>>,
4578 }
4579
4580 impl Entity for View {
4581 type Event = ();
4582 }
4583
4584 impl super::View for View {
4585 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4586 Empty::new().boxed()
4587 }
4588
4589 fn ui_name() -> &'static str {
4590 "View"
4591 }
4592
4593 fn on_focus(&mut self, _: &mut ViewContext<Self>) {
4594 self.events.lock().push(format!("{} focused", &self.name));
4595 }
4596
4597 fn on_blur(&mut self, _: &mut ViewContext<Self>) {
4598 self.events.lock().push(format!("{} blurred", &self.name));
4599 }
4600 }
4601
4602 let events: Arc<Mutex<Vec<String>>> = Default::default();
4603 let (window_id, view_1) = cx.add_window(Default::default(), |_| View {
4604 events: events.clone(),
4605 name: "view 1".to_string(),
4606 });
4607 let view_2 = cx.add_view(window_id, |_| View {
4608 events: events.clone(),
4609 name: "view 2".to_string(),
4610 });
4611
4612 view_1.update(cx, |_, cx| cx.focus(&view_2));
4613 view_1.update(cx, |_, cx| cx.focus(&view_1));
4614 view_1.update(cx, |_, cx| cx.focus(&view_2));
4615 view_1.update(cx, |_, _| drop(view_2));
4616
4617 assert_eq!(
4618 *events.lock(),
4619 [
4620 "view 1 focused".to_string(),
4621 "view 1 blurred".to_string(),
4622 "view 2 focused".to_string(),
4623 "view 2 blurred".to_string(),
4624 "view 1 focused".to_string(),
4625 "view 1 blurred".to_string(),
4626 "view 2 focused".to_string(),
4627 "view 1 focused".to_string(),
4628 ],
4629 );
4630 }
4631
4632 #[crate::test(self)]
4633 fn test_dispatch_action(cx: &mut MutableAppContext) {
4634 struct ViewA {
4635 id: usize,
4636 }
4637
4638 impl Entity for ViewA {
4639 type Event = ();
4640 }
4641
4642 impl View for ViewA {
4643 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4644 Empty::new().boxed()
4645 }
4646
4647 fn ui_name() -> &'static str {
4648 "View"
4649 }
4650 }
4651
4652 struct ViewB {
4653 id: usize,
4654 }
4655
4656 impl Entity for ViewB {
4657 type Event = ();
4658 }
4659
4660 impl View for ViewB {
4661 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4662 Empty::new().boxed()
4663 }
4664
4665 fn ui_name() -> &'static str {
4666 "View"
4667 }
4668 }
4669
4670 action!(Action, &'static str);
4671
4672 let actions = Rc::new(RefCell::new(Vec::new()));
4673
4674 {
4675 let actions = actions.clone();
4676 cx.add_global_action(move |_: &Action, _: &mut MutableAppContext| {
4677 actions.borrow_mut().push("global".to_string());
4678 });
4679 }
4680
4681 {
4682 let actions = actions.clone();
4683 cx.add_action(move |view: &mut ViewA, action: &Action, cx| {
4684 assert_eq!(action.0, "bar");
4685 cx.propagate_action();
4686 actions.borrow_mut().push(format!("{} a", view.id));
4687 });
4688 }
4689
4690 {
4691 let actions = actions.clone();
4692 cx.add_action(move |view: &mut ViewA, _: &Action, cx| {
4693 if view.id != 1 {
4694 cx.add_view(|cx| {
4695 cx.propagate_action(); // Still works on a nested ViewContext
4696 ViewB { id: 5 }
4697 });
4698 }
4699 actions.borrow_mut().push(format!("{} b", view.id));
4700 });
4701 }
4702
4703 {
4704 let actions = actions.clone();
4705 cx.add_action(move |view: &mut ViewB, _: &Action, cx| {
4706 cx.propagate_action();
4707 actions.borrow_mut().push(format!("{} c", view.id));
4708 });
4709 }
4710
4711 {
4712 let actions = actions.clone();
4713 cx.add_action(move |view: &mut ViewB, _: &Action, cx| {
4714 cx.propagate_action();
4715 actions.borrow_mut().push(format!("{} d", view.id));
4716 });
4717 }
4718
4719 {
4720 let actions = actions.clone();
4721 cx.capture_action(move |view: &mut ViewA, _: &Action, cx| {
4722 cx.propagate_action();
4723 actions.borrow_mut().push(format!("{} capture", view.id));
4724 });
4725 }
4726
4727 let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 });
4728 let view_2 = cx.add_view(window_id, |_| ViewB { id: 2 });
4729 let view_3 = cx.add_view(window_id, |_| ViewA { id: 3 });
4730 let view_4 = cx.add_view(window_id, |_| ViewB { id: 4 });
4731
4732 cx.dispatch_action(
4733 window_id,
4734 vec![view_1.id(), view_2.id(), view_3.id(), view_4.id()],
4735 &Action("bar"),
4736 );
4737
4738 assert_eq!(
4739 *actions.borrow(),
4740 vec![
4741 "1 capture",
4742 "3 capture",
4743 "4 d",
4744 "4 c",
4745 "3 b",
4746 "3 a",
4747 "2 d",
4748 "2 c",
4749 "1 b"
4750 ]
4751 );
4752
4753 // Remove view_1, which doesn't propagate the action
4754 actions.borrow_mut().clear();
4755 cx.dispatch_action(
4756 window_id,
4757 vec![view_2.id(), view_3.id(), view_4.id()],
4758 &Action("bar"),
4759 );
4760
4761 assert_eq!(
4762 *actions.borrow(),
4763 vec![
4764 "3 capture",
4765 "4 d",
4766 "4 c",
4767 "3 b",
4768 "3 a",
4769 "2 d",
4770 "2 c",
4771 "global"
4772 ]
4773 );
4774 }
4775
4776 #[crate::test(self)]
4777 fn test_dispatch_keystroke(cx: &mut MutableAppContext) {
4778 action!(Action, &'static str);
4779
4780 struct View {
4781 id: usize,
4782 keymap_context: keymap::Context,
4783 }
4784
4785 impl Entity for View {
4786 type Event = ();
4787 }
4788
4789 impl super::View for View {
4790 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4791 Empty::new().boxed()
4792 }
4793
4794 fn ui_name() -> &'static str {
4795 "View"
4796 }
4797
4798 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
4799 self.keymap_context.clone()
4800 }
4801 }
4802
4803 impl View {
4804 fn new(id: usize) -> Self {
4805 View {
4806 id,
4807 keymap_context: keymap::Context::default(),
4808 }
4809 }
4810 }
4811
4812 let mut view_1 = View::new(1);
4813 let mut view_2 = View::new(2);
4814 let mut view_3 = View::new(3);
4815 view_1.keymap_context.set.insert("a".into());
4816 view_2.keymap_context.set.insert("a".into());
4817 view_2.keymap_context.set.insert("b".into());
4818 view_3.keymap_context.set.insert("a".into());
4819 view_3.keymap_context.set.insert("b".into());
4820 view_3.keymap_context.set.insert("c".into());
4821
4822 let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1);
4823 let view_2 = cx.add_view(window_id, |_| view_2);
4824 let view_3 = cx.add_view(window_id, |_| view_3);
4825
4826 // This keymap's only binding dispatches an action on view 2 because that view will have
4827 // "a" and "b" in its context, but not "c".
4828 cx.add_bindings(vec![keymap::Binding::new(
4829 "a",
4830 Action("a"),
4831 Some("a && b && !c"),
4832 )]);
4833
4834 cx.add_bindings(vec![keymap::Binding::new("b", Action("b"), None)]);
4835
4836 let actions = Rc::new(RefCell::new(Vec::new()));
4837 {
4838 let actions = actions.clone();
4839 cx.add_action(move |view: &mut View, action: &Action, cx| {
4840 if action.0 == "a" {
4841 actions.borrow_mut().push(format!("{} a", view.id));
4842 } else {
4843 actions
4844 .borrow_mut()
4845 .push(format!("{} {}", view.id, action.0));
4846 cx.propagate_action();
4847 }
4848 });
4849 }
4850 {
4851 let actions = actions.clone();
4852 cx.add_global_action(move |action: &Action, _| {
4853 actions.borrow_mut().push(format!("global {}", action.0));
4854 });
4855 }
4856
4857 cx.dispatch_keystroke(
4858 window_id,
4859 vec![view_1.id(), view_2.id(), view_3.id()],
4860 &Keystroke::parse("a").unwrap(),
4861 )
4862 .unwrap();
4863
4864 assert_eq!(&*actions.borrow(), &["2 a"]);
4865
4866 actions.borrow_mut().clear();
4867 cx.dispatch_keystroke(
4868 window_id,
4869 vec![view_1.id(), view_2.id(), view_3.id()],
4870 &Keystroke::parse("b").unwrap(),
4871 )
4872 .unwrap();
4873
4874 assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
4875 }
4876
4877 #[crate::test(self)]
4878 async fn test_model_condition(cx: &mut TestAppContext) {
4879 struct Counter(usize);
4880
4881 impl super::Entity for Counter {
4882 type Event = ();
4883 }
4884
4885 impl Counter {
4886 fn inc(&mut self, cx: &mut ModelContext<Self>) {
4887 self.0 += 1;
4888 cx.notify();
4889 }
4890 }
4891
4892 let model = cx.add_model(|_| Counter(0));
4893
4894 let condition1 = model.condition(&cx, |model, _| model.0 == 2);
4895 let condition2 = model.condition(&cx, |model, _| model.0 == 3);
4896 smol::pin!(condition1, condition2);
4897
4898 model.update(cx, |model, cx| model.inc(cx));
4899 assert_eq!(poll_once(&mut condition1).await, None);
4900 assert_eq!(poll_once(&mut condition2).await, None);
4901
4902 model.update(cx, |model, cx| model.inc(cx));
4903 assert_eq!(poll_once(&mut condition1).await, Some(()));
4904 assert_eq!(poll_once(&mut condition2).await, None);
4905
4906 model.update(cx, |model, cx| model.inc(cx));
4907 assert_eq!(poll_once(&mut condition2).await, Some(()));
4908
4909 model.update(cx, |_, cx| cx.notify());
4910 }
4911
4912 #[crate::test(self)]
4913 #[should_panic]
4914 async fn test_model_condition_timeout(cx: &mut TestAppContext) {
4915 struct Model;
4916
4917 impl super::Entity for Model {
4918 type Event = ();
4919 }
4920
4921 let model = cx.add_model(|_| Model);
4922 model.condition(&cx, |_, _| false).await;
4923 }
4924
4925 #[crate::test(self)]
4926 #[should_panic(expected = "model dropped with pending condition")]
4927 async fn test_model_condition_panic_on_drop(cx: &mut TestAppContext) {
4928 struct Model;
4929
4930 impl super::Entity for Model {
4931 type Event = ();
4932 }
4933
4934 let model = cx.add_model(|_| Model);
4935 let condition = model.condition(&cx, |_, _| false);
4936 cx.update(|_| drop(model));
4937 condition.await;
4938 }
4939
4940 #[crate::test(self)]
4941 async fn test_view_condition(cx: &mut TestAppContext) {
4942 struct Counter(usize);
4943
4944 impl super::Entity for Counter {
4945 type Event = ();
4946 }
4947
4948 impl super::View for Counter {
4949 fn ui_name() -> &'static str {
4950 "test view"
4951 }
4952
4953 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4954 Empty::new().boxed()
4955 }
4956 }
4957
4958 impl Counter {
4959 fn inc(&mut self, cx: &mut ViewContext<Self>) {
4960 self.0 += 1;
4961 cx.notify();
4962 }
4963 }
4964
4965 let (_, view) = cx.add_window(|_| Counter(0));
4966
4967 let condition1 = view.condition(&cx, |view, _| view.0 == 2);
4968 let condition2 = view.condition(&cx, |view, _| view.0 == 3);
4969 smol::pin!(condition1, condition2);
4970
4971 view.update(cx, |view, cx| view.inc(cx));
4972 assert_eq!(poll_once(&mut condition1).await, None);
4973 assert_eq!(poll_once(&mut condition2).await, None);
4974
4975 view.update(cx, |view, cx| view.inc(cx));
4976 assert_eq!(poll_once(&mut condition1).await, Some(()));
4977 assert_eq!(poll_once(&mut condition2).await, None);
4978
4979 view.update(cx, |view, cx| view.inc(cx));
4980 assert_eq!(poll_once(&mut condition2).await, Some(()));
4981 view.update(cx, |_, cx| cx.notify());
4982 }
4983
4984 #[crate::test(self)]
4985 #[should_panic]
4986 async fn test_view_condition_timeout(cx: &mut TestAppContext) {
4987 struct View;
4988
4989 impl super::Entity for View {
4990 type Event = ();
4991 }
4992
4993 impl super::View for View {
4994 fn ui_name() -> &'static str {
4995 "test view"
4996 }
4997
4998 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
4999 Empty::new().boxed()
5000 }
5001 }
5002
5003 let (_, view) = cx.add_window(|_| View);
5004 view.condition(&cx, |_, _| false).await;
5005 }
5006
5007 #[crate::test(self)]
5008 #[should_panic(expected = "view dropped with pending condition")]
5009 async fn test_view_condition_panic_on_drop(cx: &mut TestAppContext) {
5010 struct View;
5011
5012 impl super::Entity for View {
5013 type Event = ();
5014 }
5015
5016 impl super::View for View {
5017 fn ui_name() -> &'static str {
5018 "test view"
5019 }
5020
5021 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5022 Empty::new().boxed()
5023 }
5024 }
5025
5026 let window_id = cx.add_window(|_| View).0;
5027 let view = cx.add_view(window_id, |_| View);
5028
5029 let condition = view.condition(&cx, |_, _| false);
5030 cx.update(|_| drop(view));
5031 condition.await;
5032 }
5033}