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