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