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