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