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(crate) 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 read_root_with<C, F, R>(&self, cx: &C, read: F) -> C::Result<R>
3904 where
3905 C: BorrowWindowContext,
3906 F: FnOnce(&V, &ViewContext<V>) -> R,
3907 {
3908 self.read_with(cx, |cx| {
3909 cx.root_view()
3910 .downcast_ref::<V>()
3911 .unwrap()
3912 .read_with(cx, read)
3913 })
3914 }
3915
3916 pub fn update_root<C, F, R>(&self, cx: &mut C, update: F) -> C::Result<R>
3917 where
3918 C: BorrowWindowContext,
3919 F: FnOnce(&mut V, &mut ViewContext<V>) -> R,
3920 {
3921 cx.update_window(self.window_id, |cx| {
3922 cx.root_view()
3923 .clone()
3924 .downcast::<V>()
3925 .unwrap()
3926 .update(cx, update)
3927 })
3928 }
3929
3930 pub fn add_view<C, U, F>(&self, cx: &mut C, build_view: F) -> C::Result<ViewHandle<U>>
3931 where
3932 C: BorrowWindowContext,
3933 U: View,
3934 F: FnOnce(&mut ViewContext<U>) -> U,
3935 {
3936 self.update(cx, |cx| cx.add_view(build_view))
3937 }
3938
3939 pub(crate) fn replace_root_view<C, F>(
3940 &self,
3941 cx: &mut C,
3942 build_root_view: F,
3943 ) -> C::Result<ViewHandle<V>>
3944 where
3945 C: BorrowWindowContext,
3946 F: FnOnce(&mut ViewContext<V>) -> V,
3947 {
3948 cx.update_window(self.window_id, |cx| {
3949 let root_view = self.add_view(cx, |cx| build_root_view(cx));
3950 cx.window.root_view = Some(root_view.clone().into_any());
3951 cx.window.focused_view_id = Some(root_view.id());
3952 root_view
3953 })
3954 }
3955}
3956
3957#[repr(transparent)]
3958pub struct ViewHandle<T> {
3959 any_handle: AnyViewHandle,
3960 view_type: PhantomData<T>,
3961}
3962
3963impl<T> Deref for ViewHandle<T> {
3964 type Target = AnyViewHandle;
3965
3966 fn deref(&self) -> &Self::Target {
3967 &self.any_handle
3968 }
3969}
3970
3971impl<T: View> ViewHandle<T> {
3972 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
3973 Self {
3974 any_handle: AnyViewHandle::new(
3975 window_id,
3976 view_id,
3977 TypeId::of::<T>(),
3978 ref_counts.clone(),
3979 ),
3980 view_type: PhantomData,
3981 }
3982 }
3983
3984 pub fn downgrade(&self) -> WeakViewHandle<T> {
3985 WeakViewHandle::new(self.window_id, self.view_id)
3986 }
3987
3988 pub fn into_any(self) -> AnyViewHandle {
3989 self.any_handle
3990 }
3991
3992 pub fn window_id(&self) -> usize {
3993 self.window_id
3994 }
3995
3996 pub fn id(&self) -> usize {
3997 self.view_id
3998 }
3999
4000 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
4001 cx.read_view(self)
4002 }
4003
4004 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> C::Result<S>
4005 where
4006 C: BorrowWindowContext,
4007 F: FnOnce(&T, &ViewContext<T>) -> S,
4008 {
4009 cx.read_window_with(self.window_id, |cx| {
4010 let cx = ViewContext::immutable(cx, self.view_id);
4011 read(cx.read_view(self), &cx)
4012 })
4013 }
4014
4015 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> C::Result<S>
4016 where
4017 C: BorrowWindowContext,
4018 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
4019 {
4020 let mut update = Some(update);
4021
4022 cx.update_window(self.window_id, |cx| {
4023 cx.update_view(self, &mut |view, cx| {
4024 let update = update.take().unwrap();
4025 update(view, cx)
4026 })
4027 })
4028 }
4029
4030 pub fn is_focused(&self, cx: &WindowContext) -> bool {
4031 cx.focused_view_id() == Some(self.view_id)
4032 }
4033}
4034
4035impl<T: View> Clone for ViewHandle<T> {
4036 fn clone(&self) -> Self {
4037 ViewHandle::new(self.window_id, self.view_id, &self.ref_counts)
4038 }
4039}
4040
4041impl<T> PartialEq for ViewHandle<T> {
4042 fn eq(&self, other: &Self) -> bool {
4043 self.window_id == other.window_id && self.view_id == other.view_id
4044 }
4045}
4046
4047impl<T> PartialEq<AnyViewHandle> for ViewHandle<T> {
4048 fn eq(&self, other: &AnyViewHandle) -> bool {
4049 self.window_id == other.window_id && self.view_id == other.view_id
4050 }
4051}
4052
4053impl<T> PartialEq<WeakViewHandle<T>> for ViewHandle<T> {
4054 fn eq(&self, other: &WeakViewHandle<T>) -> bool {
4055 self.window_id == other.window_id && self.view_id == other.view_id
4056 }
4057}
4058
4059impl<T> PartialEq<ViewHandle<T>> for WeakViewHandle<T> {
4060 fn eq(&self, other: &ViewHandle<T>) -> bool {
4061 self.window_id == other.window_id && self.view_id == other.view_id
4062 }
4063}
4064
4065impl<T> Eq for ViewHandle<T> {}
4066
4067impl<T> Hash for ViewHandle<T> {
4068 fn hash<H: Hasher>(&self, state: &mut H) {
4069 self.window_id.hash(state);
4070 self.view_id.hash(state);
4071 }
4072}
4073
4074impl<T> Debug for ViewHandle<T> {
4075 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4076 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
4077 .field("window_id", &self.window_id)
4078 .field("view_id", &self.view_id)
4079 .finish()
4080 }
4081}
4082
4083impl<T: View> Handle<T> for ViewHandle<T> {
4084 type Weak = WeakViewHandle<T>;
4085
4086 fn id(&self) -> usize {
4087 self.view_id
4088 }
4089
4090 fn location(&self) -> EntityLocation {
4091 EntityLocation::View(self.window_id, self.view_id)
4092 }
4093
4094 fn downgrade(&self) -> Self::Weak {
4095 self.downgrade()
4096 }
4097
4098 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4099 where
4100 Self: Sized,
4101 {
4102 weak.upgrade(cx)
4103 }
4104}
4105
4106pub struct AnyViewHandle {
4107 window_id: usize,
4108 view_id: usize,
4109 view_type: TypeId,
4110 ref_counts: Arc<Mutex<RefCounts>>,
4111
4112 #[cfg(any(test, feature = "test-support"))]
4113 handle_id: usize,
4114}
4115
4116impl AnyViewHandle {
4117 fn new(
4118 window_id: usize,
4119 view_id: usize,
4120 view_type: TypeId,
4121 ref_counts: Arc<Mutex<RefCounts>>,
4122 ) -> Self {
4123 ref_counts.lock().inc_view(window_id, view_id);
4124
4125 #[cfg(any(test, feature = "test-support"))]
4126 let handle_id = ref_counts
4127 .lock()
4128 .leak_detector
4129 .lock()
4130 .handle_created(None, view_id);
4131
4132 Self {
4133 window_id,
4134 view_id,
4135 view_type,
4136 ref_counts,
4137 #[cfg(any(test, feature = "test-support"))]
4138 handle_id,
4139 }
4140 }
4141
4142 pub fn window_id(&self) -> usize {
4143 self.window_id
4144 }
4145
4146 pub fn id(&self) -> usize {
4147 self.view_id
4148 }
4149
4150 pub fn is<T: 'static>(&self) -> bool {
4151 TypeId::of::<T>() == self.view_type
4152 }
4153
4154 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
4155 if self.is::<T>() {
4156 Some(ViewHandle {
4157 any_handle: self,
4158 view_type: PhantomData,
4159 })
4160 } else {
4161 None
4162 }
4163 }
4164
4165 pub fn downcast_ref<T: View>(&self) -> Option<&ViewHandle<T>> {
4166 if self.is::<T>() {
4167 Some(unsafe { mem::transmute(self) })
4168 } else {
4169 None
4170 }
4171 }
4172
4173 pub fn downgrade(&self) -> AnyWeakViewHandle {
4174 AnyWeakViewHandle {
4175 window_id: self.window_id,
4176 view_id: self.view_id,
4177 view_type: self.view_type,
4178 }
4179 }
4180
4181 pub fn view_type(&self) -> TypeId {
4182 self.view_type
4183 }
4184
4185 pub fn debug_json<'a, 'b>(&self, cx: &'b WindowContext<'a>) -> serde_json::Value {
4186 cx.views
4187 .get(&(self.window_id, self.view_id))
4188 .map_or_else(|| serde_json::Value::Null, |view| view.debug_json(cx))
4189 }
4190}
4191
4192impl Clone for AnyViewHandle {
4193 fn clone(&self) -> Self {
4194 Self::new(
4195 self.window_id,
4196 self.view_id,
4197 self.view_type,
4198 self.ref_counts.clone(),
4199 )
4200 }
4201}
4202
4203impl PartialEq for AnyViewHandle {
4204 fn eq(&self, other: &Self) -> bool {
4205 self.window_id == other.window_id && self.view_id == other.view_id
4206 }
4207}
4208
4209impl<T> PartialEq<ViewHandle<T>> for AnyViewHandle {
4210 fn eq(&self, other: &ViewHandle<T>) -> bool {
4211 self.window_id == other.window_id && self.view_id == other.view_id
4212 }
4213}
4214
4215impl Drop for AnyViewHandle {
4216 fn drop(&mut self) {
4217 self.ref_counts
4218 .lock()
4219 .dec_view(self.window_id, self.view_id);
4220 #[cfg(any(test, feature = "test-support"))]
4221 self.ref_counts
4222 .lock()
4223 .leak_detector
4224 .lock()
4225 .handle_dropped(self.view_id, self.handle_id);
4226 }
4227}
4228
4229impl Debug for AnyViewHandle {
4230 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4231 f.debug_struct("AnyViewHandle")
4232 .field("window_id", &self.window_id)
4233 .field("view_id", &self.view_id)
4234 .finish()
4235 }
4236}
4237
4238pub struct AnyModelHandle {
4239 model_id: usize,
4240 model_type: TypeId,
4241 ref_counts: Arc<Mutex<RefCounts>>,
4242
4243 #[cfg(any(test, feature = "test-support"))]
4244 handle_id: usize,
4245}
4246
4247impl AnyModelHandle {
4248 fn new(model_id: usize, model_type: TypeId, ref_counts: Arc<Mutex<RefCounts>>) -> Self {
4249 ref_counts.lock().inc_model(model_id);
4250
4251 #[cfg(any(test, feature = "test-support"))]
4252 let handle_id = ref_counts
4253 .lock()
4254 .leak_detector
4255 .lock()
4256 .handle_created(None, model_id);
4257
4258 Self {
4259 model_id,
4260 model_type,
4261 ref_counts,
4262
4263 #[cfg(any(test, feature = "test-support"))]
4264 handle_id,
4265 }
4266 }
4267
4268 pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> {
4269 if self.is::<T>() {
4270 Some(ModelHandle {
4271 any_handle: self,
4272 model_type: PhantomData,
4273 })
4274 } else {
4275 None
4276 }
4277 }
4278
4279 pub fn downgrade(&self) -> AnyWeakModelHandle {
4280 AnyWeakModelHandle {
4281 model_id: self.model_id,
4282 model_type: self.model_type,
4283 }
4284 }
4285
4286 pub fn is<T: Entity>(&self) -> bool {
4287 self.model_type == TypeId::of::<T>()
4288 }
4289
4290 pub fn model_type(&self) -> TypeId {
4291 self.model_type
4292 }
4293}
4294
4295impl Clone for AnyModelHandle {
4296 fn clone(&self) -> Self {
4297 Self::new(self.model_id, self.model_type, self.ref_counts.clone())
4298 }
4299}
4300
4301impl Drop for AnyModelHandle {
4302 fn drop(&mut self) {
4303 let mut ref_counts = self.ref_counts.lock();
4304 ref_counts.dec_model(self.model_id);
4305
4306 #[cfg(any(test, feature = "test-support"))]
4307 ref_counts
4308 .leak_detector
4309 .lock()
4310 .handle_dropped(self.model_id, self.handle_id);
4311 }
4312}
4313
4314#[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)]
4315pub struct AnyWeakModelHandle {
4316 model_id: usize,
4317 model_type: TypeId,
4318}
4319
4320impl AnyWeakModelHandle {
4321 pub fn upgrade(&self, cx: &impl BorrowAppContext) -> Option<AnyModelHandle> {
4322 cx.read_with(|cx| cx.upgrade_any_model_handle(self))
4323 }
4324
4325 pub fn model_type(&self) -> TypeId {
4326 self.model_type
4327 }
4328
4329 fn is<T: 'static>(&self) -> bool {
4330 TypeId::of::<T>() == self.model_type
4331 }
4332
4333 pub fn downcast<T: Entity>(self) -> Option<WeakModelHandle<T>> {
4334 if self.is::<T>() {
4335 let result = Some(WeakModelHandle {
4336 any_handle: self,
4337 model_type: PhantomData,
4338 });
4339
4340 result
4341 } else {
4342 None
4343 }
4344 }
4345}
4346
4347#[derive(Copy)]
4348pub struct WeakViewHandle<T> {
4349 any_handle: AnyWeakViewHandle,
4350 view_type: PhantomData<T>,
4351}
4352
4353impl<T> Debug for WeakViewHandle<T> {
4354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4355 f.debug_struct(&format!("WeakViewHandle<{}>", type_name::<T>()))
4356 .field("any_handle", &self.any_handle)
4357 .finish()
4358 }
4359}
4360
4361impl<T> WeakHandle for WeakViewHandle<T> {
4362 fn id(&self) -> usize {
4363 self.view_id
4364 }
4365}
4366
4367impl<V: View> WeakViewHandle<V> {
4368 fn new(window_id: usize, view_id: usize) -> Self {
4369 Self {
4370 any_handle: AnyWeakViewHandle {
4371 window_id,
4372 view_id,
4373 view_type: TypeId::of::<V>(),
4374 },
4375 view_type: PhantomData,
4376 }
4377 }
4378
4379 pub fn id(&self) -> usize {
4380 self.view_id
4381 }
4382
4383 pub fn window_id(&self) -> usize {
4384 self.window_id
4385 }
4386
4387 pub fn into_any(self) -> AnyWeakViewHandle {
4388 self.any_handle
4389 }
4390
4391 pub fn upgrade(&self, cx: &impl BorrowAppContext) -> Option<ViewHandle<V>> {
4392 cx.read_with(|cx| cx.upgrade_view_handle(self))
4393 }
4394
4395 pub fn read_with<T>(
4396 &self,
4397 cx: &AsyncAppContext,
4398 read: impl FnOnce(&V, &ViewContext<V>) -> T,
4399 ) -> Result<T> {
4400 cx.read(|cx| {
4401 let handle = cx
4402 .upgrade_view_handle(self)
4403 .ok_or_else(|| anyhow!("view {} was dropped", V::ui_name()))?;
4404 cx.read_window(self.window_id, |cx| handle.read_with(cx, read))
4405 .ok_or_else(|| anyhow!("window was removed"))
4406 })
4407 }
4408
4409 pub fn update<T>(
4410 &self,
4411 cx: &mut AsyncAppContext,
4412 update: impl FnOnce(&mut V, &mut ViewContext<V>) -> T,
4413 ) -> Result<T> {
4414 cx.update(|cx| {
4415 let handle = cx
4416 .upgrade_view_handle(self)
4417 .ok_or_else(|| anyhow!("view {} was dropped", V::ui_name()))?;
4418 cx.update_window(self.window_id, |cx| handle.update(cx, update))
4419 .ok_or_else(|| anyhow!("window was removed"))
4420 })
4421 }
4422}
4423
4424impl<T> Deref for WeakViewHandle<T> {
4425 type Target = AnyWeakViewHandle;
4426
4427 fn deref(&self) -> &Self::Target {
4428 &self.any_handle
4429 }
4430}
4431
4432impl<T> Clone for WeakViewHandle<T> {
4433 fn clone(&self) -> Self {
4434 Self {
4435 any_handle: self.any_handle.clone(),
4436 view_type: PhantomData,
4437 }
4438 }
4439}
4440
4441impl<T> PartialEq for WeakViewHandle<T> {
4442 fn eq(&self, other: &Self) -> bool {
4443 self.window_id == other.window_id && self.view_id == other.view_id
4444 }
4445}
4446
4447impl<T> Eq for WeakViewHandle<T> {}
4448
4449impl<T> Hash for WeakViewHandle<T> {
4450 fn hash<H: Hasher>(&self, state: &mut H) {
4451 self.any_handle.hash(state);
4452 }
4453}
4454
4455#[derive(Debug, Clone, Copy, Eq, PartialEq)]
4456pub struct AnyWeakViewHandle {
4457 window_id: usize,
4458 view_id: usize,
4459 view_type: TypeId,
4460}
4461
4462impl AnyWeakViewHandle {
4463 pub fn id(&self) -> usize {
4464 self.view_id
4465 }
4466
4467 fn is<T: 'static>(&self) -> bool {
4468 TypeId::of::<T>() == self.view_type
4469 }
4470
4471 pub fn upgrade(&self, cx: &impl BorrowAppContext) -> Option<AnyViewHandle> {
4472 cx.read_with(|cx| cx.upgrade_any_view_handle(self))
4473 }
4474
4475 pub fn downcast<T: View>(self) -> Option<WeakViewHandle<T>> {
4476 if self.is::<T>() {
4477 Some(WeakViewHandle {
4478 any_handle: self,
4479 view_type: PhantomData,
4480 })
4481 } else {
4482 None
4483 }
4484 }
4485}
4486
4487impl Hash for AnyWeakViewHandle {
4488 fn hash<H: Hasher>(&self, state: &mut H) {
4489 self.window_id.hash(state);
4490 self.view_id.hash(state);
4491 self.view_type.hash(state);
4492 }
4493}
4494
4495#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4496pub struct ElementStateId {
4497 view_id: usize,
4498 element_id: usize,
4499 tag: TypeId,
4500}
4501
4502pub struct ElementStateHandle<T> {
4503 value_type: PhantomData<T>,
4504 id: ElementStateId,
4505 ref_counts: Weak<Mutex<RefCounts>>,
4506}
4507
4508impl<T: 'static> ElementStateHandle<T> {
4509 fn new(id: ElementStateId, frame_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4510 ref_counts.lock().inc_element_state(id, frame_id);
4511 Self {
4512 value_type: PhantomData,
4513 id,
4514 ref_counts: Arc::downgrade(ref_counts),
4515 }
4516 }
4517
4518 pub fn id(&self) -> ElementStateId {
4519 self.id
4520 }
4521
4522 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
4523 cx.element_states
4524 .get(&self.id)
4525 .unwrap()
4526 .downcast_ref()
4527 .unwrap()
4528 }
4529
4530 pub fn update<C, D, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R
4531 where
4532 C: DerefMut<Target = D>,
4533 D: DerefMut<Target = AppContext>,
4534 {
4535 let mut element_state = cx.deref_mut().element_states.remove(&self.id).unwrap();
4536 let result = f(element_state.downcast_mut().unwrap(), cx);
4537 cx.deref_mut().element_states.insert(self.id, element_state);
4538 result
4539 }
4540}
4541
4542impl<T> Drop for ElementStateHandle<T> {
4543 fn drop(&mut self) {
4544 if let Some(ref_counts) = self.ref_counts.upgrade() {
4545 ref_counts.lock().dec_element_state(self.id);
4546 }
4547 }
4548}
4549
4550#[must_use]
4551pub enum Subscription {
4552 Subscription(callback_collection::Subscription<usize, SubscriptionCallback>),
4553 Observation(callback_collection::Subscription<usize, ObservationCallback>),
4554 GlobalSubscription(callback_collection::Subscription<TypeId, GlobalSubscriptionCallback>),
4555 GlobalObservation(callback_collection::Subscription<TypeId, GlobalObservationCallback>),
4556 FocusObservation(callback_collection::Subscription<usize, FocusObservationCallback>),
4557 WindowActivationObservation(callback_collection::Subscription<usize, WindowActivationCallback>),
4558 WindowFullscreenObservation(callback_collection::Subscription<usize, WindowFullscreenCallback>),
4559 WindowBoundsObservation(callback_collection::Subscription<usize, WindowBoundsCallback>),
4560 KeystrokeObservation(callback_collection::Subscription<usize, KeystrokeCallback>),
4561 ReleaseObservation(callback_collection::Subscription<usize, ReleaseObservationCallback>),
4562 ActionObservation(callback_collection::Subscription<(), ActionObservationCallback>),
4563 ActiveLabeledTasksObservation(
4564 callback_collection::Subscription<(), ActiveLabeledTasksCallback>,
4565 ),
4566}
4567
4568impl Subscription {
4569 pub fn id(&self) -> usize {
4570 match self {
4571 Subscription::Subscription(subscription) => subscription.id(),
4572 Subscription::Observation(subscription) => subscription.id(),
4573 Subscription::GlobalSubscription(subscription) => subscription.id(),
4574 Subscription::GlobalObservation(subscription) => subscription.id(),
4575 Subscription::FocusObservation(subscription) => subscription.id(),
4576 Subscription::WindowActivationObservation(subscription) => subscription.id(),
4577 Subscription::WindowFullscreenObservation(subscription) => subscription.id(),
4578 Subscription::WindowBoundsObservation(subscription) => subscription.id(),
4579 Subscription::KeystrokeObservation(subscription) => subscription.id(),
4580 Subscription::ReleaseObservation(subscription) => subscription.id(),
4581 Subscription::ActionObservation(subscription) => subscription.id(),
4582 Subscription::ActiveLabeledTasksObservation(subscription) => subscription.id(),
4583 }
4584 }
4585
4586 pub fn detach(&mut self) {
4587 match self {
4588 Subscription::Subscription(subscription) => subscription.detach(),
4589 Subscription::GlobalSubscription(subscription) => subscription.detach(),
4590 Subscription::Observation(subscription) => subscription.detach(),
4591 Subscription::GlobalObservation(subscription) => subscription.detach(),
4592 Subscription::FocusObservation(subscription) => subscription.detach(),
4593 Subscription::KeystrokeObservation(subscription) => subscription.detach(),
4594 Subscription::WindowActivationObservation(subscription) => subscription.detach(),
4595 Subscription::WindowFullscreenObservation(subscription) => subscription.detach(),
4596 Subscription::WindowBoundsObservation(subscription) => subscription.detach(),
4597 Subscription::ReleaseObservation(subscription) => subscription.detach(),
4598 Subscription::ActionObservation(subscription) => subscription.detach(),
4599 Subscription::ActiveLabeledTasksObservation(subscription) => subscription.detach(),
4600 }
4601 }
4602}
4603
4604#[cfg(test)]
4605mod tests {
4606 use super::*;
4607 use crate::{
4608 actions,
4609 elements::*,
4610 impl_actions,
4611 platform::{MouseButton, MouseButtonEvent},
4612 window::ChildView,
4613 };
4614 use itertools::Itertools;
4615 use postage::{sink::Sink, stream::Stream};
4616 use serde::Deserialize;
4617 use smol::future::poll_once;
4618 use std::{
4619 cell::Cell,
4620 sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
4621 };
4622
4623 #[crate::test(self)]
4624 fn test_model_handles(cx: &mut AppContext) {
4625 struct Model {
4626 other: Option<ModelHandle<Model>>,
4627 events: Vec<String>,
4628 }
4629
4630 impl Entity for Model {
4631 type Event = usize;
4632 }
4633
4634 impl Model {
4635 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
4636 if let Some(other) = other.as_ref() {
4637 cx.observe(other, |me, _, _| {
4638 me.events.push("notified".into());
4639 })
4640 .detach();
4641 cx.subscribe(other, |me, _, event, _| {
4642 me.events.push(format!("observed event {}", event));
4643 })
4644 .detach();
4645 }
4646
4647 Self {
4648 other,
4649 events: Vec::new(),
4650 }
4651 }
4652 }
4653
4654 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
4655 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
4656 assert_eq!(cx.models.len(), 2);
4657
4658 handle_1.update(cx, |model, cx| {
4659 model.events.push("updated".into());
4660 cx.emit(1);
4661 cx.notify();
4662 cx.emit(2);
4663 });
4664 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
4665 assert_eq!(
4666 handle_2.read(cx).events,
4667 vec![
4668 "observed event 1".to_string(),
4669 "notified".to_string(),
4670 "observed event 2".to_string(),
4671 ]
4672 );
4673
4674 handle_2.update(cx, |model, _| {
4675 drop(handle_1);
4676 model.other.take();
4677 });
4678
4679 assert_eq!(cx.models.len(), 1);
4680 assert!(cx.subscriptions.is_empty());
4681 assert!(cx.observations.is_empty());
4682 }
4683
4684 #[crate::test(self)]
4685 fn test_model_events(cx: &mut AppContext) {
4686 #[derive(Default)]
4687 struct Model {
4688 events: Vec<usize>,
4689 }
4690
4691 impl Entity for Model {
4692 type Event = usize;
4693 }
4694
4695 let handle_1 = cx.add_model(|_| Model::default());
4696 let handle_2 = cx.add_model(|_| Model::default());
4697
4698 handle_1.update(cx, |_, cx| {
4699 cx.subscribe(&handle_2, move |model: &mut Model, emitter, event, cx| {
4700 model.events.push(*event);
4701
4702 cx.subscribe(&emitter, |model, _, event, _| {
4703 model.events.push(*event * 2);
4704 })
4705 .detach();
4706 })
4707 .detach();
4708 });
4709
4710 handle_2.update(cx, |_, c| c.emit(7));
4711 assert_eq!(handle_1.read(cx).events, vec![7]);
4712
4713 handle_2.update(cx, |_, c| c.emit(5));
4714 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
4715 }
4716
4717 #[crate::test(self)]
4718 fn test_model_emit_before_subscribe_in_same_update_cycle(cx: &mut AppContext) {
4719 #[derive(Default)]
4720 struct Model;
4721
4722 impl Entity for Model {
4723 type Event = ();
4724 }
4725
4726 let events = Rc::new(RefCell::new(Vec::new()));
4727 cx.add_model(|cx| {
4728 drop(cx.subscribe(&cx.handle(), {
4729 let events = events.clone();
4730 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
4731 }));
4732 cx.subscribe(&cx.handle(), {
4733 let events = events.clone();
4734 move |_, _, _, _| events.borrow_mut().push("before emit")
4735 })
4736 .detach();
4737 cx.emit(());
4738 cx.subscribe(&cx.handle(), {
4739 let events = events.clone();
4740 move |_, _, _, _| events.borrow_mut().push("after emit")
4741 })
4742 .detach();
4743 Model
4744 });
4745 assert_eq!(*events.borrow(), ["before emit"]);
4746 }
4747
4748 #[crate::test(self)]
4749 fn test_observe_and_notify_from_model(cx: &mut AppContext) {
4750 #[derive(Default)]
4751 struct Model {
4752 count: usize,
4753 events: Vec<usize>,
4754 }
4755
4756 impl Entity for Model {
4757 type Event = ();
4758 }
4759
4760 let handle_1 = cx.add_model(|_| Model::default());
4761 let handle_2 = cx.add_model(|_| Model::default());
4762
4763 handle_1.update(cx, |_, c| {
4764 c.observe(&handle_2, move |model, observed, c| {
4765 model.events.push(observed.read(c).count);
4766 c.observe(&observed, |model, observed, c| {
4767 model.events.push(observed.read(c).count * 2);
4768 })
4769 .detach();
4770 })
4771 .detach();
4772 });
4773
4774 handle_2.update(cx, |model, c| {
4775 model.count = 7;
4776 c.notify()
4777 });
4778 assert_eq!(handle_1.read(cx).events, vec![7]);
4779
4780 handle_2.update(cx, |model, c| {
4781 model.count = 5;
4782 c.notify()
4783 });
4784 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10])
4785 }
4786
4787 #[crate::test(self)]
4788 fn test_model_notify_before_observe_in_same_update_cycle(cx: &mut AppContext) {
4789 #[derive(Default)]
4790 struct Model;
4791
4792 impl Entity for Model {
4793 type Event = ();
4794 }
4795
4796 let events = Rc::new(RefCell::new(Vec::new()));
4797 cx.add_model(|cx| {
4798 drop(cx.observe(&cx.handle(), {
4799 let events = events.clone();
4800 move |_, _, _| events.borrow_mut().push("dropped before flush")
4801 }));
4802 cx.observe(&cx.handle(), {
4803 let events = events.clone();
4804 move |_, _, _| events.borrow_mut().push("before notify")
4805 })
4806 .detach();
4807 cx.notify();
4808 cx.observe(&cx.handle(), {
4809 let events = events.clone();
4810 move |_, _, _| events.borrow_mut().push("after notify")
4811 })
4812 .detach();
4813 Model
4814 });
4815 assert_eq!(*events.borrow(), ["before notify"]);
4816 }
4817
4818 #[crate::test(self)]
4819 fn test_defer_and_after_window_update(cx: &mut TestAppContext) {
4820 struct View {
4821 render_count: usize,
4822 }
4823
4824 impl Entity for View {
4825 type Event = usize;
4826 }
4827
4828 impl super::View for View {
4829 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
4830 post_inc(&mut self.render_count);
4831 Empty::new().into_any()
4832 }
4833
4834 fn ui_name() -> &'static str {
4835 "View"
4836 }
4837 }
4838
4839 let window = cx.add_window(|_| View { render_count: 0 });
4840 let called_defer = Rc::new(AtomicBool::new(false));
4841 let called_after_window_update = Rc::new(AtomicBool::new(false));
4842
4843 window.root(cx).update(cx, |this, cx| {
4844 assert_eq!(this.render_count, 1);
4845 cx.defer({
4846 let called_defer = called_defer.clone();
4847 move |this, _| {
4848 assert_eq!(this.render_count, 1);
4849 called_defer.store(true, SeqCst);
4850 }
4851 });
4852 cx.after_window_update({
4853 let called_after_window_update = called_after_window_update.clone();
4854 move |this, cx| {
4855 assert_eq!(this.render_count, 2);
4856 called_after_window_update.store(true, SeqCst);
4857 cx.notify();
4858 }
4859 });
4860 assert!(!called_defer.load(SeqCst));
4861 assert!(!called_after_window_update.load(SeqCst));
4862 cx.notify();
4863 });
4864
4865 assert!(called_defer.load(SeqCst));
4866 assert!(called_after_window_update.load(SeqCst));
4867 assert_eq!(window.read_root_with(cx, |view, _| view.render_count), 3);
4868 }
4869
4870 #[crate::test(self)]
4871 fn test_view_handles(cx: &mut TestAppContext) {
4872 struct View {
4873 other: Option<ViewHandle<View>>,
4874 events: Vec<String>,
4875 }
4876
4877 impl Entity for View {
4878 type Event = usize;
4879 }
4880
4881 impl super::View for View {
4882 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
4883 Empty::new().into_any()
4884 }
4885
4886 fn ui_name() -> &'static str {
4887 "View"
4888 }
4889 }
4890
4891 impl View {
4892 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
4893 if let Some(other) = other.as_ref() {
4894 cx.subscribe(other, |me, _, event, _| {
4895 me.events.push(format!("observed event {}", event));
4896 })
4897 .detach();
4898 }
4899 Self {
4900 other,
4901 events: Vec::new(),
4902 }
4903 }
4904 }
4905
4906 let window = cx.add_window(|cx| View::new(None, cx));
4907 let handle_1 = window.add_view(cx, |cx| View::new(None, cx));
4908 let handle_2 = window.add_view(cx, |cx| View::new(Some(handle_1.clone()), cx));
4909 assert_eq!(cx.read(|cx| cx.views.len()), 3);
4910
4911 handle_1.update(cx, |view, cx| {
4912 view.events.push("updated".into());
4913 cx.emit(1);
4914 cx.emit(2);
4915 });
4916 handle_1.read_with(cx, |view, _| {
4917 assert_eq!(view.events, vec!["updated".to_string()]);
4918 });
4919 handle_2.read_with(cx, |view, _| {
4920 assert_eq!(
4921 view.events,
4922 vec![
4923 "observed event 1".to_string(),
4924 "observed event 2".to_string(),
4925 ]
4926 );
4927 });
4928
4929 handle_2.update(cx, |view, _| {
4930 drop(handle_1);
4931 view.other.take();
4932 });
4933
4934 cx.read(|cx| {
4935 assert_eq!(cx.views.len(), 2);
4936 assert!(cx.subscriptions.is_empty());
4937 assert!(cx.observations.is_empty());
4938 });
4939 }
4940
4941 #[crate::test(self)]
4942 fn test_add_window(cx: &mut AppContext) {
4943 struct View {
4944 mouse_down_count: Arc<AtomicUsize>,
4945 }
4946
4947 impl Entity for View {
4948 type Event = ();
4949 }
4950
4951 impl super::View for View {
4952 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
4953 enum Handler {}
4954 let mouse_down_count = self.mouse_down_count.clone();
4955 MouseEventHandler::<Handler, _>::new(0, cx, |_, _| Empty::new())
4956 .on_down(MouseButton::Left, move |_, _, _| {
4957 mouse_down_count.fetch_add(1, SeqCst);
4958 })
4959 .into_any()
4960 }
4961
4962 fn ui_name() -> &'static str {
4963 "View"
4964 }
4965 }
4966
4967 let mouse_down_count = Arc::new(AtomicUsize::new(0));
4968 let window = cx.add_window(Default::default(), |_| View {
4969 mouse_down_count: mouse_down_count.clone(),
4970 });
4971
4972 window.update(cx, |cx| {
4973 // Ensure window's root element is in a valid lifecycle state.
4974 cx.dispatch_event(
4975 Event::MouseDown(MouseButtonEvent {
4976 position: Default::default(),
4977 button: MouseButton::Left,
4978 modifiers: Default::default(),
4979 click_count: 1,
4980 }),
4981 false,
4982 );
4983 assert_eq!(mouse_down_count.load(SeqCst), 1);
4984 });
4985 }
4986
4987 #[crate::test(self)]
4988 fn test_entity_release_hooks(cx: &mut TestAppContext) {
4989 struct Model {
4990 released: Rc<Cell<bool>>,
4991 }
4992
4993 struct View {
4994 released: Rc<Cell<bool>>,
4995 }
4996
4997 impl Entity for Model {
4998 type Event = ();
4999
5000 fn release(&mut self, _: &mut AppContext) {
5001 self.released.set(true);
5002 }
5003 }
5004
5005 impl Entity for View {
5006 type Event = ();
5007
5008 fn release(&mut self, _: &mut AppContext) {
5009 self.released.set(true);
5010 }
5011 }
5012
5013 impl super::View for View {
5014 fn ui_name() -> &'static str {
5015 "View"
5016 }
5017
5018 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
5019 Empty::new().into_any()
5020 }
5021 }
5022
5023 let model_released = Rc::new(Cell::new(false));
5024 let model_release_observed = Rc::new(Cell::new(false));
5025 let view_released = Rc::new(Cell::new(false));
5026 let view_release_observed = Rc::new(Cell::new(false));
5027
5028 let model = cx.add_model(|_| Model {
5029 released: model_released.clone(),
5030 });
5031 let window = cx.add_window(|_| View {
5032 released: view_released.clone(),
5033 });
5034 let view = window.root(cx);
5035
5036 assert!(!model_released.get());
5037 assert!(!view_released.get());
5038
5039 cx.update(|cx| {
5040 cx.observe_release(&model, {
5041 let model_release_observed = model_release_observed.clone();
5042 move |_, _| model_release_observed.set(true)
5043 })
5044 .detach();
5045 cx.observe_release(&view, {
5046 let view_release_observed = view_release_observed.clone();
5047 move |_, _| view_release_observed.set(true)
5048 })
5049 .detach();
5050 });
5051
5052 cx.update(move |_| {
5053 drop(model);
5054 });
5055 assert!(model_released.get());
5056 assert!(model_release_observed.get());
5057
5058 drop(view);
5059 window.update(cx, |cx| cx.remove_window());
5060 assert!(view_released.get());
5061 assert!(view_release_observed.get());
5062 }
5063
5064 #[crate::test(self)]
5065 fn test_view_events(cx: &mut TestAppContext) {
5066 struct Model;
5067
5068 impl Entity for Model {
5069 type Event = String;
5070 }
5071
5072 let window = cx.add_window(|_| TestView::default());
5073 let handle_1 = window.root(cx);
5074 let handle_2 = window.add_view(cx, |_| TestView::default());
5075 let handle_3 = cx.add_model(|_| Model);
5076
5077 handle_1.update(cx, |_, cx| {
5078 cx.subscribe(&handle_2, move |me, emitter, event, cx| {
5079 me.events.push(event.clone());
5080
5081 cx.subscribe(&emitter, |me, _, event, _| {
5082 me.events.push(format!("{event} from inner"));
5083 })
5084 .detach();
5085 })
5086 .detach();
5087
5088 cx.subscribe(&handle_3, |me, _, event, _| {
5089 me.events.push(event.clone());
5090 })
5091 .detach();
5092 });
5093
5094 handle_2.update(cx, |_, c| c.emit("7".into()));
5095 handle_1.read_with(cx, |view, _| assert_eq!(view.events, ["7"]));
5096
5097 handle_2.update(cx, |_, c| c.emit("5".into()));
5098 handle_1.read_with(cx, |view, _| {
5099 assert_eq!(view.events, ["7", "5", "5 from inner"])
5100 });
5101
5102 handle_3.update(cx, |_, c| c.emit("9".into()));
5103 handle_1.read_with(cx, |view, _| {
5104 assert_eq!(view.events, ["7", "5", "5 from inner", "9"])
5105 });
5106 }
5107
5108 #[crate::test(self)]
5109 fn test_global_events(cx: &mut AppContext) {
5110 #[derive(Clone, Debug, Eq, PartialEq)]
5111 struct GlobalEvent(u64);
5112
5113 let events = Rc::new(RefCell::new(Vec::new()));
5114 let first_subscription;
5115 let second_subscription;
5116
5117 {
5118 let events = events.clone();
5119 first_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
5120 events.borrow_mut().push(("First", e.clone()));
5121 });
5122 }
5123
5124 {
5125 let events = events.clone();
5126 second_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
5127 events.borrow_mut().push(("Second", e.clone()));
5128 });
5129 }
5130
5131 cx.update(|cx| {
5132 cx.emit_global(GlobalEvent(1));
5133 cx.emit_global(GlobalEvent(2));
5134 });
5135
5136 drop(first_subscription);
5137
5138 cx.update(|cx| {
5139 cx.emit_global(GlobalEvent(3));
5140 });
5141
5142 drop(second_subscription);
5143
5144 cx.update(|cx| {
5145 cx.emit_global(GlobalEvent(4));
5146 });
5147
5148 assert_eq!(
5149 &*events.borrow(),
5150 &[
5151 ("First", GlobalEvent(1)),
5152 ("Second", GlobalEvent(1)),
5153 ("First", GlobalEvent(2)),
5154 ("Second", GlobalEvent(2)),
5155 ("Second", GlobalEvent(3)),
5156 ]
5157 );
5158 }
5159
5160 #[crate::test(self)]
5161 fn test_global_events_emitted_before_subscription_in_same_update_cycle(cx: &mut AppContext) {
5162 let events = Rc::new(RefCell::new(Vec::new()));
5163 cx.update(|cx| {
5164 {
5165 let events = events.clone();
5166 drop(cx.subscribe_global(move |_: &(), _| {
5167 events.borrow_mut().push("dropped before emit");
5168 }));
5169 }
5170
5171 {
5172 let events = events.clone();
5173 cx.subscribe_global(move |_: &(), _| {
5174 events.borrow_mut().push("before emit");
5175 })
5176 .detach();
5177 }
5178
5179 cx.emit_global(());
5180
5181 {
5182 let events = events.clone();
5183 cx.subscribe_global(move |_: &(), _| {
5184 events.borrow_mut().push("after emit");
5185 })
5186 .detach();
5187 }
5188 });
5189
5190 assert_eq!(*events.borrow(), ["before emit"]);
5191 }
5192
5193 #[crate::test(self)]
5194 fn test_global_nested_events(cx: &mut AppContext) {
5195 #[derive(Clone, Debug, Eq, PartialEq)]
5196 struct GlobalEvent(u64);
5197
5198 let events = Rc::new(RefCell::new(Vec::new()));
5199
5200 {
5201 let events = events.clone();
5202 cx.subscribe_global(move |e: &GlobalEvent, cx| {
5203 events.borrow_mut().push(("Outer", e.clone()));
5204
5205 if e.0 == 1 {
5206 let events = events.clone();
5207 cx.subscribe_global(move |e: &GlobalEvent, _| {
5208 events.borrow_mut().push(("Inner", e.clone()));
5209 })
5210 .detach();
5211 }
5212 })
5213 .detach();
5214 }
5215
5216 cx.update(|cx| {
5217 cx.emit_global(GlobalEvent(1));
5218 cx.emit_global(GlobalEvent(2));
5219 cx.emit_global(GlobalEvent(3));
5220 });
5221 cx.update(|cx| {
5222 cx.emit_global(GlobalEvent(4));
5223 });
5224
5225 assert_eq!(
5226 &*events.borrow(),
5227 &[
5228 ("Outer", GlobalEvent(1)),
5229 ("Outer", GlobalEvent(2)),
5230 ("Outer", GlobalEvent(3)),
5231 ("Outer", GlobalEvent(4)),
5232 ("Inner", GlobalEvent(4)),
5233 ]
5234 );
5235 }
5236
5237 #[crate::test(self)]
5238 fn test_global(cx: &mut AppContext) {
5239 type Global = usize;
5240
5241 let observation_count = Rc::new(RefCell::new(0));
5242 let subscription = cx.observe_global::<Global, _>({
5243 let observation_count = observation_count.clone();
5244 move |_| {
5245 *observation_count.borrow_mut() += 1;
5246 }
5247 });
5248
5249 assert!(!cx.has_global::<Global>());
5250 assert_eq!(cx.default_global::<Global>(), &0);
5251 assert_eq!(*observation_count.borrow(), 1);
5252 assert!(cx.has_global::<Global>());
5253 assert_eq!(
5254 cx.update_global::<Global, _, _>(|global, _| {
5255 *global = 1;
5256 "Update Result"
5257 }),
5258 "Update Result"
5259 );
5260 assert_eq!(*observation_count.borrow(), 2);
5261 assert_eq!(cx.global::<Global>(), &1);
5262
5263 drop(subscription);
5264 cx.update_global::<Global, _, _>(|global, _| {
5265 *global = 2;
5266 });
5267 assert_eq!(*observation_count.borrow(), 2);
5268
5269 type OtherGlobal = f32;
5270
5271 let observation_count = Rc::new(RefCell::new(0));
5272 cx.observe_global::<OtherGlobal, _>({
5273 let observation_count = observation_count.clone();
5274 move |_| {
5275 *observation_count.borrow_mut() += 1;
5276 }
5277 })
5278 .detach();
5279
5280 assert_eq!(
5281 cx.update_default_global::<OtherGlobal, _, _>(|global, _| {
5282 assert_eq!(global, &0.0);
5283 *global = 2.0;
5284 "Default update result"
5285 }),
5286 "Default update result"
5287 );
5288 assert_eq!(cx.global::<OtherGlobal>(), &2.0);
5289 assert_eq!(*observation_count.borrow(), 1);
5290 }
5291
5292 #[crate::test(self)]
5293 fn test_dropping_subscribers(cx: &mut TestAppContext) {
5294 struct Model;
5295
5296 impl Entity for Model {
5297 type Event = ();
5298 }
5299
5300 let window = cx.add_window(|_| TestView::default());
5301 let observing_view = window.add_view(cx, |_| TestView::default());
5302 let emitting_view = window.add_view(cx, |_| TestView::default());
5303 let observing_model = cx.add_model(|_| Model);
5304 let observed_model = cx.add_model(|_| Model);
5305
5306 observing_view.update(cx, |_, cx| {
5307 cx.subscribe(&emitting_view, |_, _, _, _| {}).detach();
5308 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
5309 });
5310 observing_model.update(cx, |_, cx| {
5311 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
5312 });
5313
5314 cx.update(|_| {
5315 drop(observing_view);
5316 drop(observing_model);
5317 });
5318
5319 emitting_view.update(cx, |_, cx| cx.emit(Default::default()));
5320 observed_model.update(cx, |_, cx| cx.emit(()));
5321 }
5322
5323 #[crate::test(self)]
5324 fn test_view_emit_before_subscribe_in_same_update_cycle(cx: &mut AppContext) {
5325 let window = cx.add_window::<TestView, _>(Default::default(), |cx| {
5326 drop(cx.subscribe(&cx.handle(), {
5327 move |this, _, _, _| this.events.push("dropped before flush".into())
5328 }));
5329 cx.subscribe(&cx.handle(), {
5330 move |this, _, _, _| this.events.push("before emit".into())
5331 })
5332 .detach();
5333 cx.emit("the event".into());
5334 cx.subscribe(&cx.handle(), {
5335 move |this, _, _, _| this.events.push("after emit".into())
5336 })
5337 .detach();
5338 TestView { events: Vec::new() }
5339 });
5340
5341 window.read_root_with(cx, |view, _| assert_eq!(view.events, ["before emit"]));
5342 }
5343
5344 #[crate::test(self)]
5345 fn test_observe_and_notify_from_view(cx: &mut TestAppContext) {
5346 #[derive(Default)]
5347 struct Model {
5348 state: String,
5349 }
5350
5351 impl Entity for Model {
5352 type Event = ();
5353 }
5354
5355 let window = cx.add_window(|_| TestView::default());
5356 let view = window.root(cx);
5357 let model = cx.add_model(|_| Model {
5358 state: "old-state".into(),
5359 });
5360
5361 view.update(cx, |_, c| {
5362 c.observe(&model, |me, observed, cx| {
5363 me.events.push(observed.read(cx).state.clone())
5364 })
5365 .detach();
5366 });
5367
5368 model.update(cx, |model, cx| {
5369 model.state = "new-state".into();
5370 cx.notify();
5371 });
5372 view.read_with(cx, |view, _| assert_eq!(view.events, ["new-state"]));
5373 }
5374
5375 #[crate::test(self)]
5376 fn test_view_notify_before_observe_in_same_update_cycle(cx: &mut AppContext) {
5377 let window = cx.add_window::<TestView, _>(Default::default(), |cx| {
5378 drop(cx.observe(&cx.handle(), {
5379 move |this, _, _| this.events.push("dropped before flush".into())
5380 }));
5381 cx.observe(&cx.handle(), {
5382 move |this, _, _| this.events.push("before notify".into())
5383 })
5384 .detach();
5385 cx.notify();
5386 cx.observe(&cx.handle(), {
5387 move |this, _, _| this.events.push("after notify".into())
5388 })
5389 .detach();
5390 TestView { events: Vec::new() }
5391 });
5392
5393 assert_eq!(window.read_root_with(cx, |view, _| assert_eq!(view.events, ["before notify"])));
5394 }
5395
5396 #[crate::test(self)]
5397 fn test_notify_and_drop_observe_subscription_in_same_update_cycle(cx: &mut TestAppContext) {
5398 struct Model;
5399 impl Entity for Model {
5400 type Event = ();
5401 }
5402
5403 let model = cx.add_model(|_| Model);
5404 let window = cx.add_window(|_| TestView::default());
5405 let view = window.root(cx);
5406
5407 view.update(cx, |_, cx| {
5408 model.update(cx, |_, cx| cx.notify());
5409 drop(cx.observe(&model, move |this, _, _| {
5410 this.events.push("model notified".into());
5411 }));
5412 model.update(cx, |_, cx| cx.notify());
5413 });
5414
5415 for _ in 0..3 {
5416 model.update(cx, |_, cx| cx.notify());
5417 }
5418 view.read_with(cx, |view, _| assert_eq!(view.events, Vec::<&str>::new()));
5419 }
5420
5421 #[crate::test(self)]
5422 fn test_dropping_observers(cx: &mut TestAppContext) {
5423 struct Model;
5424
5425 impl Entity for Model {
5426 type Event = ();
5427 }
5428
5429 let window = cx.add_window(|_| TestView::default());
5430 let observing_view = window.add_view(cx, |_| TestView::default());
5431 let observing_model = cx.add_model(|_| Model);
5432 let observed_model = cx.add_model(|_| Model);
5433
5434 observing_view.update(cx, |_, cx| {
5435 cx.observe(&observed_model, |_, _, _| {}).detach();
5436 });
5437 observing_model.update(cx, |_, cx| {
5438 cx.observe(&observed_model, |_, _, _| {}).detach();
5439 });
5440
5441 cx.update(|_| {
5442 drop(observing_view);
5443 drop(observing_model);
5444 });
5445
5446 observed_model.update(cx, |_, cx| cx.notify());
5447 }
5448
5449 #[crate::test(self)]
5450 fn test_dropping_subscriptions_during_callback(cx: &mut TestAppContext) {
5451 struct Model;
5452
5453 impl Entity for Model {
5454 type Event = u64;
5455 }
5456
5457 // Events
5458 let observing_model = cx.add_model(|_| Model);
5459 let observed_model = cx.add_model(|_| Model);
5460
5461 let events = Rc::new(RefCell::new(Vec::new()));
5462
5463 observing_model.update(cx, |_, cx| {
5464 let events = events.clone();
5465 let subscription = Rc::new(RefCell::new(None));
5466 *subscription.borrow_mut() = Some(cx.subscribe(&observed_model, {
5467 let subscription = subscription.clone();
5468 move |_, _, e, _| {
5469 subscription.borrow_mut().take();
5470 events.borrow_mut().push(*e);
5471 }
5472 }));
5473 });
5474
5475 observed_model.update(cx, |_, cx| {
5476 cx.emit(1);
5477 cx.emit(2);
5478 });
5479
5480 assert_eq!(*events.borrow(), [1]);
5481
5482 // Global Events
5483 #[derive(Clone, Debug, Eq, PartialEq)]
5484 struct GlobalEvent(u64);
5485
5486 let events = Rc::new(RefCell::new(Vec::new()));
5487
5488 {
5489 let events = events.clone();
5490 let subscription = Rc::new(RefCell::new(None));
5491 *subscription.borrow_mut() = Some(cx.subscribe_global({
5492 let subscription = subscription.clone();
5493 move |e: &GlobalEvent, _| {
5494 subscription.borrow_mut().take();
5495 events.borrow_mut().push(e.clone());
5496 }
5497 }));
5498 }
5499
5500 cx.update(|cx| {
5501 cx.emit_global(GlobalEvent(1));
5502 cx.emit_global(GlobalEvent(2));
5503 });
5504
5505 assert_eq!(*events.borrow(), [GlobalEvent(1)]);
5506
5507 // Model Observation
5508 let observing_model = cx.add_model(|_| Model);
5509 let observed_model = cx.add_model(|_| Model);
5510
5511 let observation_count = Rc::new(RefCell::new(0));
5512
5513 observing_model.update(cx, |_, cx| {
5514 let observation_count = observation_count.clone();
5515 let subscription = Rc::new(RefCell::new(None));
5516 *subscription.borrow_mut() = Some(cx.observe(&observed_model, {
5517 let subscription = subscription.clone();
5518 move |_, _, _| {
5519 subscription.borrow_mut().take();
5520 *observation_count.borrow_mut() += 1;
5521 }
5522 }));
5523 });
5524
5525 observed_model.update(cx, |_, cx| {
5526 cx.notify();
5527 });
5528
5529 observed_model.update(cx, |_, cx| {
5530 cx.notify();
5531 });
5532
5533 assert_eq!(*observation_count.borrow(), 1);
5534
5535 // View Observation
5536 struct View;
5537
5538 impl Entity for View {
5539 type Event = ();
5540 }
5541
5542 impl super::View for View {
5543 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
5544 Empty::new().into_any()
5545 }
5546
5547 fn ui_name() -> &'static str {
5548 "View"
5549 }
5550 }
5551
5552 let window = cx.add_window(|_| View);
5553 let observing_view = window.add_view(cx, |_| View);
5554 let observed_view = window.add_view(cx, |_| View);
5555
5556 let observation_count = Rc::new(RefCell::new(0));
5557 observing_view.update(cx, |_, cx| {
5558 let observation_count = observation_count.clone();
5559 let subscription = Rc::new(RefCell::new(None));
5560 *subscription.borrow_mut() = Some(cx.observe(&observed_view, {
5561 let subscription = subscription.clone();
5562 move |_, _, _| {
5563 subscription.borrow_mut().take();
5564 *observation_count.borrow_mut() += 1;
5565 }
5566 }));
5567 });
5568
5569 observed_view.update(cx, |_, cx| {
5570 cx.notify();
5571 });
5572
5573 observed_view.update(cx, |_, cx| {
5574 cx.notify();
5575 });
5576
5577 assert_eq!(*observation_count.borrow(), 1);
5578
5579 // Global Observation
5580 let observation_count = Rc::new(RefCell::new(0));
5581 let subscription = Rc::new(RefCell::new(None));
5582 *subscription.borrow_mut() = Some(cx.observe_global::<(), _>({
5583 let observation_count = observation_count.clone();
5584 let subscription = subscription.clone();
5585 move |_| {
5586 subscription.borrow_mut().take();
5587 *observation_count.borrow_mut() += 1;
5588 }
5589 }));
5590
5591 cx.update(|cx| {
5592 cx.default_global::<()>();
5593 cx.set_global(());
5594 });
5595 assert_eq!(*observation_count.borrow(), 1);
5596 }
5597
5598 #[crate::test(self)]
5599 fn test_focus(cx: &mut TestAppContext) {
5600 struct View {
5601 name: String,
5602 events: Arc<Mutex<Vec<String>>>,
5603 child: Option<AnyViewHandle>,
5604 }
5605
5606 impl Entity for View {
5607 type Event = ();
5608 }
5609
5610 impl super::View for View {
5611 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
5612 self.child
5613 .as_ref()
5614 .map(|child| ChildView::new(child, cx).into_any())
5615 .unwrap_or(Empty::new().into_any())
5616 }
5617
5618 fn ui_name() -> &'static str {
5619 "View"
5620 }
5621
5622 fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
5623 if cx.handle().id() == focused.id() {
5624 self.events.lock().push(format!("{} focused", &self.name));
5625 }
5626 }
5627
5628 fn focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
5629 if cx.handle().id() == blurred.id() {
5630 self.events.lock().push(format!("{} blurred", &self.name));
5631 }
5632 }
5633 }
5634
5635 let view_events: Arc<Mutex<Vec<String>>> = Default::default();
5636 let window = cx.add_window(|_| View {
5637 events: view_events.clone(),
5638 name: "view 1".to_string(),
5639 child: None,
5640 });
5641 let view_1 = window.root(cx);
5642 let view_2 = window.update(cx, |cx| {
5643 let view_2 = cx.add_view(|_| View {
5644 events: view_events.clone(),
5645 name: "view 2".to_string(),
5646 child: None,
5647 });
5648 view_1.update(cx, |view_1, cx| {
5649 view_1.child = Some(view_2.clone().into_any());
5650 cx.notify();
5651 });
5652 view_2
5653 });
5654
5655 let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
5656 view_1.update(cx, |_, cx| {
5657 cx.observe_focus(&view_2, {
5658 let observed_events = observed_events.clone();
5659 move |this, view, focused, cx| {
5660 let label = if focused { "focus" } else { "blur" };
5661 observed_events.lock().push(format!(
5662 "{} observed {}'s {}",
5663 this.name,
5664 view.read(cx).name,
5665 label
5666 ))
5667 }
5668 })
5669 .detach();
5670 });
5671 view_2.update(cx, |_, cx| {
5672 cx.observe_focus(&view_1, {
5673 let observed_events = observed_events.clone();
5674 move |this, view, focused, cx| {
5675 let label = if focused { "focus" } else { "blur" };
5676 observed_events.lock().push(format!(
5677 "{} observed {}'s {}",
5678 this.name,
5679 view.read(cx).name,
5680 label
5681 ))
5682 }
5683 })
5684 .detach();
5685 });
5686 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
5687 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
5688
5689 view_1.update(cx, |_, cx| {
5690 // Ensure only the last focus event is honored.
5691 cx.focus(&view_2);
5692 cx.focus(&view_1);
5693 cx.focus(&view_2);
5694 });
5695
5696 assert_eq!(
5697 mem::take(&mut *view_events.lock()),
5698 ["view 1 blurred", "view 2 focused"],
5699 );
5700 assert_eq!(
5701 mem::take(&mut *observed_events.lock()),
5702 [
5703 "view 2 observed view 1's blur",
5704 "view 1 observed view 2's focus"
5705 ]
5706 );
5707
5708 view_1.update(cx, |_, cx| cx.focus(&view_1));
5709 assert_eq!(
5710 mem::take(&mut *view_events.lock()),
5711 ["view 2 blurred", "view 1 focused"],
5712 );
5713 assert_eq!(
5714 mem::take(&mut *observed_events.lock()),
5715 [
5716 "view 1 observed view 2's blur",
5717 "view 2 observed view 1's focus"
5718 ]
5719 );
5720
5721 view_1.update(cx, |_, cx| cx.focus(&view_2));
5722 assert_eq!(
5723 mem::take(&mut *view_events.lock()),
5724 ["view 1 blurred", "view 2 focused"],
5725 );
5726 assert_eq!(
5727 mem::take(&mut *observed_events.lock()),
5728 [
5729 "view 2 observed view 1's blur",
5730 "view 1 observed view 2's focus"
5731 ]
5732 );
5733
5734 println!("=====================");
5735 view_1.update(cx, |view, _| {
5736 drop(view_2);
5737 view.child = None;
5738 });
5739 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
5740 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
5741 }
5742
5743 #[crate::test(self)]
5744 fn test_deserialize_actions(cx: &mut AppContext) {
5745 #[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
5746 pub struct ComplexAction {
5747 arg: String,
5748 count: usize,
5749 }
5750
5751 actions!(test::something, [SimpleAction]);
5752 impl_actions!(test::something, [ComplexAction]);
5753
5754 cx.add_global_action(move |_: &SimpleAction, _: &mut AppContext| {});
5755 cx.add_global_action(move |_: &ComplexAction, _: &mut AppContext| {});
5756
5757 let action1 = cx
5758 .deserialize_action(
5759 "test::something::ComplexAction",
5760 Some(serde_json::from_str(r#"{"arg": "a", "count": 5}"#).unwrap()),
5761 )
5762 .unwrap();
5763 let action2 = cx
5764 .deserialize_action("test::something::SimpleAction", None)
5765 .unwrap();
5766 assert_eq!(
5767 action1.as_any().downcast_ref::<ComplexAction>().unwrap(),
5768 &ComplexAction {
5769 arg: "a".to_string(),
5770 count: 5,
5771 }
5772 );
5773 assert_eq!(
5774 action2.as_any().downcast_ref::<SimpleAction>().unwrap(),
5775 &SimpleAction
5776 );
5777 }
5778
5779 #[crate::test(self)]
5780 fn test_dispatch_action(cx: &mut TestAppContext) {
5781 struct ViewA {
5782 id: usize,
5783 child: Option<AnyViewHandle>,
5784 }
5785
5786 impl Entity for ViewA {
5787 type Event = ();
5788 }
5789
5790 impl View for ViewA {
5791 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
5792 self.child
5793 .as_ref()
5794 .map(|child| ChildView::new(child, cx).into_any())
5795 .unwrap_or(Empty::new().into_any())
5796 }
5797
5798 fn ui_name() -> &'static str {
5799 "View"
5800 }
5801 }
5802
5803 struct ViewB {
5804 id: usize,
5805 child: Option<AnyViewHandle>,
5806 }
5807
5808 impl Entity for ViewB {
5809 type Event = ();
5810 }
5811
5812 impl View for ViewB {
5813 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
5814 self.child
5815 .as_ref()
5816 .map(|child| ChildView::new(child, cx).into_any())
5817 .unwrap_or(Empty::new().into_any())
5818 }
5819
5820 fn ui_name() -> &'static str {
5821 "View"
5822 }
5823 }
5824
5825 #[derive(Clone, Default, Deserialize, PartialEq)]
5826 pub struct Action(pub String);
5827
5828 impl_actions!(test, [Action]);
5829
5830 let actions = Rc::new(RefCell::new(Vec::new()));
5831 let observed_actions = Rc::new(RefCell::new(Vec::new()));
5832
5833 cx.update(|cx| {
5834 cx.add_global_action({
5835 let actions = actions.clone();
5836 move |_: &Action, _: &mut AppContext| {
5837 actions.borrow_mut().push("global".to_string());
5838 }
5839 });
5840
5841 cx.add_action({
5842 let actions = actions.clone();
5843 move |view: &mut ViewA, action: &Action, cx| {
5844 assert_eq!(action.0, "bar");
5845 cx.propagate_action();
5846 actions.borrow_mut().push(format!("{} a", view.id));
5847 }
5848 });
5849
5850 cx.add_action({
5851 let actions = actions.clone();
5852 move |view: &mut ViewA, _: &Action, cx| {
5853 if view.id != 1 {
5854 cx.add_view(|cx| {
5855 cx.propagate_action(); // Still works on a nested ViewContext
5856 ViewB { id: 5, child: None }
5857 });
5858 }
5859 actions.borrow_mut().push(format!("{} b", view.id));
5860 }
5861 });
5862
5863 cx.add_action({
5864 let actions = actions.clone();
5865 move |view: &mut ViewB, _: &Action, cx| {
5866 cx.propagate_action();
5867 actions.borrow_mut().push(format!("{} c", view.id));
5868 }
5869 });
5870
5871 cx.add_action({
5872 let actions = actions.clone();
5873 move |view: &mut ViewB, _: &Action, cx| {
5874 cx.propagate_action();
5875 actions.borrow_mut().push(format!("{} d", view.id));
5876 }
5877 });
5878
5879 cx.capture_action({
5880 let actions = actions.clone();
5881 move |view: &mut ViewA, _: &Action, cx| {
5882 cx.propagate_action();
5883 actions.borrow_mut().push(format!("{} capture", view.id));
5884 }
5885 });
5886
5887 cx.observe_actions({
5888 let observed_actions = observed_actions.clone();
5889 move |action_id, _| observed_actions.borrow_mut().push(action_id)
5890 })
5891 .detach();
5892 });
5893
5894 let window = cx.add_window(|_| ViewA { id: 1, child: None });
5895 let view_1 = window.root(cx);
5896 let view_2 = window.update(cx, |cx| {
5897 let child = cx.add_view(|_| ViewB { id: 2, child: None });
5898 view_1.update(cx, |view, cx| {
5899 view.child = Some(child.clone().into_any());
5900 cx.notify();
5901 });
5902 child
5903 });
5904 let view_3 = window.update(cx, |cx| {
5905 let child = cx.add_view(|_| ViewA { id: 3, child: None });
5906 view_2.update(cx, |view, cx| {
5907 view.child = Some(child.clone().into_any());
5908 cx.notify();
5909 });
5910 child
5911 });
5912 let view_4 = window.update(cx, |cx| {
5913 let child = cx.add_view(|_| ViewB { id: 4, child: None });
5914 view_3.update(cx, |view, cx| {
5915 view.child = Some(child.clone().into_any());
5916 cx.notify();
5917 });
5918 child
5919 });
5920
5921 window.update(cx, |cx| {
5922 cx.dispatch_action(Some(view_4.id()), &Action("bar".to_string()))
5923 });
5924
5925 assert_eq!(
5926 *actions.borrow(),
5927 vec![
5928 "1 capture",
5929 "3 capture",
5930 "4 d",
5931 "4 c",
5932 "3 b",
5933 "3 a",
5934 "2 d",
5935 "2 c",
5936 "1 b"
5937 ]
5938 );
5939 assert_eq!(*observed_actions.borrow(), [Action::default().id()]);
5940
5941 // Remove view_1, which doesn't propagate the action
5942
5943 let window = cx.add_window(|_| ViewB { id: 2, child: None });
5944 let view_2 = window.root(cx);
5945 let view_3 = window.update(cx, |cx| {
5946 let child = cx.add_view(|_| ViewA { id: 3, child: None });
5947 view_2.update(cx, |view, cx| {
5948 view.child = Some(child.clone().into_any());
5949 cx.notify();
5950 });
5951 child
5952 });
5953 let view_4 = window.update(cx, |cx| {
5954 let child = cx.add_view(|_| ViewB { id: 4, child: None });
5955 view_3.update(cx, |view, cx| {
5956 view.child = Some(child.clone().into_any());
5957 cx.notify();
5958 });
5959 child
5960 });
5961
5962 actions.borrow_mut().clear();
5963 window.update(cx, |cx| {
5964 cx.dispatch_action(Some(view_4.id()), &Action("bar".to_string()))
5965 });
5966
5967 assert_eq!(
5968 *actions.borrow(),
5969 vec![
5970 "3 capture",
5971 "4 d",
5972 "4 c",
5973 "3 b",
5974 "3 a",
5975 "2 d",
5976 "2 c",
5977 "global"
5978 ]
5979 );
5980 assert_eq!(
5981 *observed_actions.borrow(),
5982 [Action::default().id(), Action::default().id()]
5983 );
5984 }
5985
5986 #[crate::test(self)]
5987 fn test_dispatch_keystroke(cx: &mut AppContext) {
5988 #[derive(Clone, Deserialize, PartialEq)]
5989 pub struct Action(String);
5990
5991 impl_actions!(test, [Action]);
5992
5993 struct View {
5994 id: usize,
5995 keymap_context: KeymapContext,
5996 child: Option<AnyViewHandle>,
5997 }
5998
5999 impl Entity for View {
6000 type Event = ();
6001 }
6002
6003 impl super::View for View {
6004 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
6005 self.child
6006 .as_ref()
6007 .map(|child| ChildView::new(child, cx).into_any())
6008 .unwrap_or(Empty::new().into_any())
6009 }
6010
6011 fn ui_name() -> &'static str {
6012 "View"
6013 }
6014
6015 fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
6016 *keymap = self.keymap_context.clone();
6017 }
6018 }
6019
6020 impl View {
6021 fn new(id: usize) -> Self {
6022 View {
6023 id,
6024 keymap_context: KeymapContext::default(),
6025 child: None,
6026 }
6027 }
6028 }
6029
6030 let mut view_1 = View::new(1);
6031 let mut view_2 = View::new(2);
6032 let mut view_3 = View::new(3);
6033 view_1.keymap_context.add_identifier("a");
6034 view_2.keymap_context.add_identifier("a");
6035 view_2.keymap_context.add_identifier("b");
6036 view_3.keymap_context.add_identifier("a");
6037 view_3.keymap_context.add_identifier("b");
6038 view_3.keymap_context.add_identifier("c");
6039
6040 let window = cx.add_window(Default::default(), |cx| {
6041 let view_2 = cx.add_view(|cx| {
6042 let view_3 = cx.add_view(|cx| {
6043 cx.focus_self();
6044 view_3
6045 });
6046 view_2.child = Some(view_3.into_any());
6047 view_2
6048 });
6049 view_1.child = Some(view_2.into_any());
6050 view_1
6051 });
6052
6053 // This binding only dispatches an action on view 2 because that view will have
6054 // "a" and "b" in its context, but not "c".
6055 cx.add_bindings(vec![Binding::new(
6056 "a",
6057 Action("a".to_string()),
6058 Some("a && b && !c"),
6059 )]);
6060
6061 cx.add_bindings(vec![Binding::new("b", Action("b".to_string()), None)]);
6062
6063 // This binding only dispatches an action on views 2 and 3, because they have
6064 // a parent view with a in its context
6065 cx.add_bindings(vec![Binding::new(
6066 "c",
6067 Action("c".to_string()),
6068 Some("b > c"),
6069 )]);
6070
6071 // This binding only dispatches an action on view 2, because they have
6072 // a parent view with a in its context
6073 cx.add_bindings(vec![Binding::new(
6074 "d",
6075 Action("d".to_string()),
6076 Some("a && !b > b"),
6077 )]);
6078
6079 let actions = Rc::new(RefCell::new(Vec::new()));
6080 cx.add_action({
6081 let actions = actions.clone();
6082 move |view: &mut View, action: &Action, cx| {
6083 actions
6084 .borrow_mut()
6085 .push(format!("{} {}", view.id, action.0));
6086
6087 if action.0 == "b" {
6088 cx.propagate_action();
6089 }
6090 }
6091 });
6092
6093 cx.add_global_action({
6094 let actions = actions.clone();
6095 move |action: &Action, _| {
6096 actions.borrow_mut().push(format!("global {}", action.0));
6097 }
6098 });
6099
6100 window.update(cx, |cx| {
6101 cx.dispatch_keystroke(&Keystroke::parse("a").unwrap())
6102 });
6103 assert_eq!(&*actions.borrow(), &["2 a"]);
6104 actions.borrow_mut().clear();
6105
6106 window.update(cx, |cx| {
6107 cx.dispatch_keystroke(&Keystroke::parse("b").unwrap());
6108 });
6109
6110 assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
6111 actions.borrow_mut().clear();
6112
6113 window.update(cx, |cx| {
6114 cx.dispatch_keystroke(&Keystroke::parse("c").unwrap());
6115 });
6116 assert_eq!(&*actions.borrow(), &["3 c"]);
6117 actions.borrow_mut().clear();
6118
6119 window.update(cx, |cx| {
6120 cx.dispatch_keystroke(&Keystroke::parse("d").unwrap());
6121 });
6122 assert_eq!(&*actions.borrow(), &["2 d"]);
6123 actions.borrow_mut().clear();
6124 }
6125
6126 #[crate::test(self)]
6127 fn test_keystrokes_for_action(cx: &mut TestAppContext) {
6128 actions!(test, [Action1, Action2, GlobalAction]);
6129
6130 struct View1 {
6131 child: ViewHandle<View2>,
6132 }
6133 struct View2 {}
6134
6135 impl Entity for View1 {
6136 type Event = ();
6137 }
6138 impl Entity for View2 {
6139 type Event = ();
6140 }
6141
6142 impl super::View for View1 {
6143 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
6144 ChildView::new(&self.child, cx).into_any()
6145 }
6146 fn ui_name() -> &'static str {
6147 "View1"
6148 }
6149 }
6150 impl super::View for View2 {
6151 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6152 Empty::new().into_any()
6153 }
6154 fn ui_name() -> &'static str {
6155 "View2"
6156 }
6157 }
6158
6159 let window = cx.add_window(|cx| {
6160 let view_2 = cx.add_view(|cx| {
6161 cx.focus_self();
6162 View2 {}
6163 });
6164 View1 { child: view_2 }
6165 });
6166 let view_1 = window.root(cx);
6167 let view_2 = view_1.read_with(cx, |view, _| view.child.clone());
6168
6169 cx.update(|cx| {
6170 cx.add_action(|_: &mut View1, _: &Action1, _cx| {});
6171 cx.add_action(|_: &mut View2, _: &Action2, _cx| {});
6172 cx.add_global_action(|_: &GlobalAction, _| {});
6173 cx.add_bindings(vec![
6174 Binding::new("a", Action1, Some("View1")),
6175 Binding::new("b", Action2, Some("View1 > View2")),
6176 Binding::new("c", GlobalAction, Some("View3")), // View 3 does not exist
6177 ]);
6178 });
6179
6180 let view_1_id = view_1.id();
6181 view_1.update(cx, |_, cx| {
6182 view_2.update(cx, |_, cx| {
6183 // Sanity check
6184 let mut new_parents = Default::default();
6185 let mut notify_views_if_parents_change = Default::default();
6186 let mut layout_cx = LayoutContext::new(
6187 cx,
6188 &mut new_parents,
6189 &mut notify_views_if_parents_change,
6190 false,
6191 );
6192 assert_eq!(
6193 layout_cx
6194 .keystrokes_for_action(view_1_id, &Action1)
6195 .unwrap()
6196 .as_slice(),
6197 &[Keystroke::parse("a").unwrap()]
6198 );
6199 assert_eq!(
6200 layout_cx
6201 .keystrokes_for_action(view_2.id(), &Action2)
6202 .unwrap()
6203 .as_slice(),
6204 &[Keystroke::parse("b").unwrap()]
6205 );
6206
6207 // The 'a' keystroke propagates up the view tree from view_2
6208 // to view_1. The action, Action1, is handled by view_1.
6209 assert_eq!(
6210 layout_cx
6211 .keystrokes_for_action(view_2.id(), &Action1)
6212 .unwrap()
6213 .as_slice(),
6214 &[Keystroke::parse("a").unwrap()]
6215 );
6216
6217 // Actions that are handled below the current view don't have bindings
6218 assert_eq!(layout_cx.keystrokes_for_action(view_1_id, &Action2), None);
6219
6220 // Actions that are handled in other branches of the tree should not have a binding
6221 assert_eq!(
6222 layout_cx.keystrokes_for_action(view_2.id(), &GlobalAction),
6223 None
6224 );
6225 });
6226 });
6227
6228 // Check that global actions do not have a binding, even if a binding does exist in another view
6229 assert_eq!(
6230 &available_actions(window.window_id(), view_1.id(), cx),
6231 &[
6232 ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
6233 ("test::GlobalAction", vec![])
6234 ],
6235 );
6236
6237 // Check that view 1 actions and bindings are available even when called from view 2
6238 assert_eq!(
6239 &available_actions(window.window_id(), view_2.id(), cx),
6240 &[
6241 ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
6242 ("test::Action2", vec![Keystroke::parse("b").unwrap()]),
6243 ("test::GlobalAction", vec![]),
6244 ],
6245 );
6246
6247 // Produces a list of actions and key bindings
6248 fn available_actions(
6249 window_id: usize,
6250 view_id: usize,
6251 cx: &TestAppContext,
6252 ) -> Vec<(&'static str, Vec<Keystroke>)> {
6253 cx.available_actions(window_id, view_id)
6254 .into_iter()
6255 .map(|(action_name, _, bindings)| {
6256 (
6257 action_name,
6258 bindings
6259 .iter()
6260 .map(|binding| binding.keystrokes()[0].clone())
6261 .collect::<Vec<_>>(),
6262 )
6263 })
6264 .sorted_by(|(name1, _), (name2, _)| name1.cmp(name2))
6265 .collect()
6266 }
6267 }
6268
6269 #[crate::test(self)]
6270 fn test_keystrokes_for_action_with_data(cx: &mut TestAppContext) {
6271 #[derive(Clone, Debug, Deserialize, PartialEq)]
6272 struct ActionWithArg {
6273 #[serde(default)]
6274 arg: bool,
6275 }
6276
6277 struct View;
6278 impl super::Entity for View {
6279 type Event = ();
6280 }
6281 impl super::View for View {
6282 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6283 Empty::new().into_any()
6284 }
6285 fn ui_name() -> &'static str {
6286 "View"
6287 }
6288 }
6289
6290 impl_actions!(test, [ActionWithArg]);
6291
6292 let window = cx.add_window(|_| View);
6293 let view = window.root(cx);
6294 cx.update(|cx| {
6295 cx.add_global_action(|_: &ActionWithArg, _| {});
6296 cx.add_bindings(vec![
6297 Binding::new("a", ActionWithArg { arg: false }, None),
6298 Binding::new("shift-a", ActionWithArg { arg: true }, None),
6299 ]);
6300 });
6301
6302 let actions = cx.available_actions(window.window_id(), view.id());
6303 assert_eq!(
6304 actions[0].1.as_any().downcast_ref::<ActionWithArg>(),
6305 Some(&ActionWithArg { arg: false })
6306 );
6307 assert_eq!(
6308 actions[0]
6309 .2
6310 .iter()
6311 .map(|b| b.keystrokes()[0].clone())
6312 .collect::<Vec<_>>(),
6313 vec![Keystroke::parse("a").unwrap()],
6314 );
6315 }
6316
6317 #[crate::test(self)]
6318 async fn test_model_condition(cx: &mut TestAppContext) {
6319 struct Counter(usize);
6320
6321 impl super::Entity for Counter {
6322 type Event = ();
6323 }
6324
6325 impl Counter {
6326 fn inc(&mut self, cx: &mut ModelContext<Self>) {
6327 self.0 += 1;
6328 cx.notify();
6329 }
6330 }
6331
6332 let model = cx.add_model(|_| Counter(0));
6333
6334 let condition1 = model.condition(cx, |model, _| model.0 == 2);
6335 let condition2 = model.condition(cx, |model, _| model.0 == 3);
6336 smol::pin!(condition1, condition2);
6337
6338 model.update(cx, |model, cx| model.inc(cx));
6339 assert_eq!(poll_once(&mut condition1).await, None);
6340 assert_eq!(poll_once(&mut condition2).await, None);
6341
6342 model.update(cx, |model, cx| model.inc(cx));
6343 assert_eq!(poll_once(&mut condition1).await, Some(()));
6344 assert_eq!(poll_once(&mut condition2).await, None);
6345
6346 model.update(cx, |model, cx| model.inc(cx));
6347 assert_eq!(poll_once(&mut condition2).await, Some(()));
6348
6349 model.update(cx, |_, cx| cx.notify());
6350 }
6351
6352 #[crate::test(self)]
6353 #[should_panic]
6354 async fn test_model_condition_timeout(cx: &mut TestAppContext) {
6355 struct Model;
6356
6357 impl super::Entity for Model {
6358 type Event = ();
6359 }
6360
6361 let model = cx.add_model(|_| Model);
6362 model.condition(cx, |_, _| false).await;
6363 }
6364
6365 #[crate::test(self)]
6366 #[should_panic(expected = "model dropped with pending condition")]
6367 async fn test_model_condition_panic_on_drop(cx: &mut TestAppContext) {
6368 struct Model;
6369
6370 impl super::Entity for Model {
6371 type Event = ();
6372 }
6373
6374 let model = cx.add_model(|_| Model);
6375 let condition = model.condition(cx, |_, _| false);
6376 cx.update(|_| drop(model));
6377 condition.await;
6378 }
6379
6380 #[crate::test(self)]
6381 async fn test_view_condition(cx: &mut TestAppContext) {
6382 struct Counter(usize);
6383
6384 impl super::Entity for Counter {
6385 type Event = ();
6386 }
6387
6388 impl super::View for Counter {
6389 fn ui_name() -> &'static str {
6390 "test view"
6391 }
6392
6393 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6394 Empty::new().into_any()
6395 }
6396 }
6397
6398 impl Counter {
6399 fn inc(&mut self, cx: &mut ViewContext<Self>) {
6400 self.0 += 1;
6401 cx.notify();
6402 }
6403 }
6404
6405 let window = cx.add_window(|_| Counter(0));
6406 let view = window.root(cx);
6407
6408 let condition1 = view.condition(cx, |view, _| view.0 == 2);
6409 let condition2 = view.condition(cx, |view, _| view.0 == 3);
6410 smol::pin!(condition1, condition2);
6411
6412 view.update(cx, |view, cx| view.inc(cx));
6413 assert_eq!(poll_once(&mut condition1).await, None);
6414 assert_eq!(poll_once(&mut condition2).await, None);
6415
6416 view.update(cx, |view, cx| view.inc(cx));
6417 assert_eq!(poll_once(&mut condition1).await, Some(()));
6418 assert_eq!(poll_once(&mut condition2).await, None);
6419
6420 view.update(cx, |view, cx| view.inc(cx));
6421 assert_eq!(poll_once(&mut condition2).await, Some(()));
6422 view.update(cx, |_, cx| cx.notify());
6423 }
6424
6425 #[crate::test(self)]
6426 #[should_panic]
6427 async fn test_view_condition_timeout(cx: &mut TestAppContext) {
6428 let window = cx.add_window(|_| TestView::default());
6429 window.root(cx).condition(cx, |_, _| false).await;
6430 }
6431
6432 #[crate::test(self)]
6433 #[should_panic(expected = "view dropped with pending condition")]
6434 async fn test_view_condition_panic_on_drop(cx: &mut TestAppContext) {
6435 let window = cx.add_window(|_| TestView::default());
6436 let view = window.add_view(cx, |_| TestView::default());
6437
6438 let condition = view.condition(cx, |_, _| false);
6439 cx.update(|_| drop(view));
6440 condition.await;
6441 }
6442
6443 #[crate::test(self)]
6444 fn test_refresh_windows(cx: &mut TestAppContext) {
6445 struct View(usize);
6446
6447 impl super::Entity for View {
6448 type Event = ();
6449 }
6450
6451 impl super::View for View {
6452 fn ui_name() -> &'static str {
6453 "test view"
6454 }
6455
6456 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6457 Empty::new().into_any_named(format!("render count: {}", post_inc(&mut self.0)))
6458 }
6459 }
6460
6461 let window = cx.add_window(|_| View(0));
6462 let root_view = window.root(cx);
6463 window.update(cx, |cx| {
6464 assert_eq!(
6465 cx.window.rendered_views[&root_view.id()].name(),
6466 Some("render count: 0")
6467 );
6468 });
6469
6470 let view = window.update(cx, |cx| {
6471 cx.refresh_windows();
6472 cx.add_view(|_| View(0))
6473 });
6474
6475 window.update(cx, |cx| {
6476 assert_eq!(
6477 cx.window.rendered_views[&root_view.id()].name(),
6478 Some("render count: 1")
6479 );
6480 assert_eq!(
6481 cx.window.rendered_views[&view.id()].name(),
6482 Some("render count: 0")
6483 );
6484 });
6485
6486 cx.update(|cx| cx.refresh_windows());
6487
6488 window.update(cx, |cx| {
6489 assert_eq!(
6490 cx.window.rendered_views[&root_view.id()].name(),
6491 Some("render count: 2")
6492 );
6493 assert_eq!(
6494 cx.window.rendered_views[&view.id()].name(),
6495 Some("render count: 1")
6496 );
6497 });
6498
6499 cx.update(|cx| {
6500 cx.refresh_windows();
6501 drop(view);
6502 });
6503
6504 window.update(cx, |cx| {
6505 assert_eq!(
6506 cx.window.rendered_views[&root_view.id()].name(),
6507 Some("render count: 3")
6508 );
6509 assert_eq!(cx.window.rendered_views.len(), 1);
6510 });
6511 }
6512
6513 #[crate::test(self)]
6514 async fn test_labeled_tasks(cx: &mut TestAppContext) {
6515 assert_eq!(None, cx.update(|cx| cx.active_labeled_tasks().next()));
6516 let (mut sender, mut receiver) = postage::oneshot::channel::<()>();
6517 let task = cx
6518 .update(|cx| cx.spawn_labeled("Test Label", |_| async move { receiver.recv().await }));
6519
6520 assert_eq!(
6521 Some("Test Label"),
6522 cx.update(|cx| cx.active_labeled_tasks().next())
6523 );
6524 sender
6525 .send(())
6526 .await
6527 .expect("Could not send message to complete task");
6528 task.await;
6529
6530 assert_eq!(None, cx.update(|cx| cx.active_labeled_tasks().next()));
6531 }
6532
6533 #[crate::test(self)]
6534 async fn test_window_activation(cx: &mut TestAppContext) {
6535 struct View(&'static str);
6536
6537 impl super::Entity for View {
6538 type Event = ();
6539 }
6540
6541 impl super::View for View {
6542 fn ui_name() -> &'static str {
6543 "test view"
6544 }
6545
6546 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6547 Empty::new().into_any()
6548 }
6549 }
6550
6551 let events = Rc::new(RefCell::new(Vec::new()));
6552 let window_1 = cx.add_window(|cx: &mut ViewContext<View>| {
6553 cx.observe_window_activation({
6554 let events = events.clone();
6555 move |this, active, _| events.borrow_mut().push((this.0, active))
6556 })
6557 .detach();
6558 View("window 1")
6559 });
6560 assert_eq!(mem::take(&mut *events.borrow_mut()), [("window 1", true)]);
6561
6562 let window_2 = cx.add_window(|cx: &mut ViewContext<View>| {
6563 cx.observe_window_activation({
6564 let events = events.clone();
6565 move |this, active, _| events.borrow_mut().push((this.0, active))
6566 })
6567 .detach();
6568 View("window 2")
6569 });
6570 assert_eq!(
6571 mem::take(&mut *events.borrow_mut()),
6572 [("window 1", false), ("window 2", true)]
6573 );
6574
6575 let window_3 = cx.add_window(|cx: &mut ViewContext<View>| {
6576 cx.observe_window_activation({
6577 let events = events.clone();
6578 move |this, active, _| events.borrow_mut().push((this.0, active))
6579 })
6580 .detach();
6581 View("window 3")
6582 });
6583 assert_eq!(
6584 mem::take(&mut *events.borrow_mut()),
6585 [("window 2", false), ("window 3", true)]
6586 );
6587
6588 cx.simulate_window_activation(Some(window_2.window_id()));
6589 assert_eq!(
6590 mem::take(&mut *events.borrow_mut()),
6591 [("window 3", false), ("window 2", true)]
6592 );
6593
6594 cx.simulate_window_activation(Some(window_1.window_id()));
6595 assert_eq!(
6596 mem::take(&mut *events.borrow_mut()),
6597 [("window 2", false), ("window 1", true)]
6598 );
6599
6600 cx.simulate_window_activation(Some(window_3.window_id()));
6601 assert_eq!(
6602 mem::take(&mut *events.borrow_mut()),
6603 [("window 1", false), ("window 3", true)]
6604 );
6605
6606 cx.simulate_window_activation(Some(window_3.window_id()));
6607 assert_eq!(mem::take(&mut *events.borrow_mut()), []);
6608 }
6609
6610 #[crate::test(self)]
6611 fn test_child_view(cx: &mut TestAppContext) {
6612 struct Child {
6613 rendered: Rc<Cell<bool>>,
6614 dropped: Rc<Cell<bool>>,
6615 }
6616
6617 impl super::Entity for Child {
6618 type Event = ();
6619 }
6620
6621 impl super::View for Child {
6622 fn ui_name() -> &'static str {
6623 "child view"
6624 }
6625
6626 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6627 self.rendered.set(true);
6628 Empty::new().into_any()
6629 }
6630 }
6631
6632 impl Drop for Child {
6633 fn drop(&mut self) {
6634 self.dropped.set(true);
6635 }
6636 }
6637
6638 struct Parent {
6639 child: Option<ViewHandle<Child>>,
6640 }
6641
6642 impl super::Entity for Parent {
6643 type Event = ();
6644 }
6645
6646 impl super::View for Parent {
6647 fn ui_name() -> &'static str {
6648 "parent view"
6649 }
6650
6651 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
6652 if let Some(child) = self.child.as_ref() {
6653 ChildView::new(child, cx).into_any()
6654 } else {
6655 Empty::new().into_any()
6656 }
6657 }
6658 }
6659
6660 let child_rendered = Rc::new(Cell::new(false));
6661 let child_dropped = Rc::new(Cell::new(false));
6662 let window = cx.add_window(|cx| Parent {
6663 child: Some(cx.add_view(|_| Child {
6664 rendered: child_rendered.clone(),
6665 dropped: child_dropped.clone(),
6666 })),
6667 });
6668 let root_view = window.root(cx);
6669 assert!(child_rendered.take());
6670 assert!(!child_dropped.take());
6671
6672 root_view.update(cx, |view, cx| {
6673 view.child.take();
6674 cx.notify();
6675 });
6676 assert!(!child_rendered.take());
6677 assert!(child_dropped.take());
6678 }
6679
6680 #[derive(Default)]
6681 struct TestView {
6682 events: Vec<String>,
6683 }
6684
6685 impl Entity for TestView {
6686 type Event = String;
6687 }
6688
6689 impl View for TestView {
6690 fn ui_name() -> &'static str {
6691 "TestView"
6692 }
6693
6694 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6695 Empty::new().into_any()
6696 }
6697 }
6698}