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