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