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