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