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