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