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