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