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