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