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 if let Some(window) = self.windows.get_mut(&window_id) {
1455 window.parents.remove(&view_id);
1456 window
1457 .invalidation
1458 .get_or_insert_with(Default::default)
1459 .removed
1460 .push(view_id);
1461 }
1462
1463 self.pending_effects
1464 .push_back(Effect::ViewRelease { view_id, view });
1465 }
1466
1467 for key in dropped_element_states {
1468 self.element_states.remove(&key);
1469 }
1470 }
1471 }
1472
1473 fn flush_effects(&mut self) {
1474 self.pending_flushes = self.pending_flushes.saturating_sub(1);
1475 let mut after_window_update_callbacks = Vec::new();
1476
1477 if !self.flushing_effects && self.pending_flushes == 0 {
1478 self.flushing_effects = true;
1479
1480 let mut refreshing = false;
1481 let mut updated_windows = HashSet::default();
1482 let mut focus_effects = HashMap::<usize, FocusEffect>::default();
1483 loop {
1484 self.remove_dropped_entities();
1485 if let Some(effect) = self.pending_effects.pop_front() {
1486 match effect {
1487 Effect::Subscription {
1488 entity_id,
1489 subscription_id,
1490 callback,
1491 } => self
1492 .subscriptions
1493 .add_callback(entity_id, subscription_id, callback),
1494
1495 Effect::Event { entity_id, payload } => {
1496 let mut subscriptions = self.subscriptions.clone();
1497 subscriptions
1498 .emit(entity_id, |callback| callback(payload.as_ref(), self))
1499 }
1500
1501 Effect::GlobalSubscription {
1502 type_id,
1503 subscription_id,
1504 callback,
1505 } => self.global_subscriptions.add_callback(
1506 type_id,
1507 subscription_id,
1508 callback,
1509 ),
1510
1511 Effect::GlobalEvent { payload } => self.emit_global_event(payload),
1512
1513 Effect::Observation {
1514 entity_id,
1515 subscription_id,
1516 callback,
1517 } => self
1518 .observations
1519 .add_callback(entity_id, subscription_id, callback),
1520
1521 Effect::ModelNotification { model_id } => {
1522 let mut observations = self.observations.clone();
1523 observations.emit(model_id, |callback| callback(self));
1524 }
1525
1526 Effect::ViewNotification { window_id, view_id } => {
1527 self.handle_view_notification_effect(window_id, view_id)
1528 }
1529
1530 Effect::GlobalNotification { type_id } => {
1531 let mut subscriptions = self.global_observations.clone();
1532 subscriptions.emit(type_id, |callback| {
1533 callback(self);
1534 true
1535 });
1536 }
1537
1538 Effect::Deferred {
1539 callback,
1540 after_window_update,
1541 } => {
1542 if after_window_update {
1543 after_window_update_callbacks.push(callback);
1544 } else {
1545 callback(self)
1546 }
1547 }
1548
1549 Effect::ModelRelease { model_id, model } => {
1550 self.handle_entity_release_effect(model_id, model.as_any())
1551 }
1552
1553 Effect::ViewRelease { view_id, view } => {
1554 self.handle_entity_release_effect(view_id, view.as_any())
1555 }
1556
1557 Effect::Focus(mut effect) => {
1558 if focus_effects
1559 .get(&effect.window_id())
1560 .map_or(false, |prev_effect| prev_effect.is_forced())
1561 {
1562 effect.force();
1563 }
1564
1565 focus_effects.insert(effect.window_id(), effect);
1566 }
1567
1568 Effect::FocusObservation {
1569 view_id,
1570 subscription_id,
1571 callback,
1572 } => {
1573 self.focus_observations.add_callback(
1574 view_id,
1575 subscription_id,
1576 callback,
1577 );
1578 }
1579
1580 Effect::ResizeWindow { window_id } => {
1581 if let Some(window) = self.windows.get_mut(&window_id) {
1582 window
1583 .invalidation
1584 .get_or_insert(WindowInvalidation::default());
1585 }
1586 self.handle_window_moved(window_id);
1587 }
1588
1589 Effect::MoveWindow { window_id } => {
1590 self.handle_window_moved(window_id);
1591 }
1592
1593 Effect::WindowActivationObservation {
1594 window_id,
1595 subscription_id,
1596 callback,
1597 } => self.window_activation_observations.add_callback(
1598 window_id,
1599 subscription_id,
1600 callback,
1601 ),
1602
1603 Effect::ActivateWindow {
1604 window_id,
1605 is_active,
1606 } => {
1607 if self.handle_window_activation_effect(window_id, is_active)
1608 && is_active
1609 {
1610 focus_effects
1611 .entry(window_id)
1612 .or_insert_with(|| FocusEffect::View {
1613 window_id,
1614 view_id: self
1615 .read_window(window_id, |cx| cx.focused_view_id())
1616 .flatten(),
1617 is_forced: true,
1618 })
1619 .force();
1620 }
1621 }
1622
1623 Effect::WindowFullscreenObservation {
1624 window_id,
1625 subscription_id,
1626 callback,
1627 } => self.window_fullscreen_observations.add_callback(
1628 window_id,
1629 subscription_id,
1630 callback,
1631 ),
1632
1633 Effect::FullscreenWindow {
1634 window_id,
1635 is_fullscreen,
1636 } => self.handle_fullscreen_effect(window_id, is_fullscreen),
1637
1638 Effect::WindowBoundsObservation {
1639 window_id,
1640 subscription_id,
1641 callback,
1642 } => self.window_bounds_observations.add_callback(
1643 window_id,
1644 subscription_id,
1645 callback,
1646 ),
1647
1648 Effect::RefreshWindows => {
1649 refreshing = true;
1650 }
1651
1652 Effect::ActionDispatchNotification { action_id } => {
1653 self.handle_action_dispatch_notification_effect(action_id)
1654 }
1655 Effect::WindowShouldCloseSubscription {
1656 window_id,
1657 callback,
1658 } => {
1659 self.handle_window_should_close_subscription_effect(window_id, callback)
1660 }
1661 Effect::Keystroke {
1662 window_id,
1663 keystroke,
1664 handled_by,
1665 result,
1666 } => self.handle_keystroke_effect(window_id, keystroke, handled_by, result),
1667 Effect::ActiveLabeledTasksChanged => {
1668 self.handle_active_labeled_tasks_changed_effect()
1669 }
1670 Effect::ActiveLabeledTasksObservation {
1671 subscription_id,
1672 callback,
1673 } => self.active_labeled_task_observations.add_callback(
1674 (),
1675 subscription_id,
1676 callback,
1677 ),
1678 }
1679 self.pending_notifications.clear();
1680 } else {
1681 for window_id in self.windows.keys().cloned().collect::<Vec<_>>() {
1682 self.update_window(window_id, |cx| {
1683 let invalidation = if refreshing {
1684 let mut invalidation =
1685 cx.window.invalidation.take().unwrap_or_default();
1686 invalidation
1687 .updated
1688 .extend(cx.window.rendered_views.keys().copied());
1689 Some(invalidation)
1690 } else {
1691 cx.window.invalidation.take()
1692 };
1693
1694 if let Some(invalidation) = invalidation {
1695 let appearance = cx.window.platform_window.appearance();
1696 cx.invalidate(invalidation, appearance);
1697 if cx.layout(refreshing).log_err().is_some() {
1698 updated_windows.insert(window_id);
1699
1700 // When the previously-focused view isn't rendered and
1701 // there isn't any pending focus, focus the root view.
1702 if let Some(focused_view_id) = cx.focused_view_id() {
1703 let root_view_id = cx.window.root_view().id();
1704 if focused_view_id != root_view_id
1705 && !cx.window.parents.contains_key(&focused_view_id)
1706 && !focus_effects.contains_key(&window_id)
1707 {
1708 focus_effects.insert(
1709 window_id,
1710 FocusEffect::View {
1711 window_id,
1712 view_id: Some(root_view_id),
1713 is_forced: false,
1714 },
1715 );
1716 }
1717 }
1718 }
1719 }
1720 });
1721 }
1722
1723 for (_, effect) in focus_effects.drain() {
1724 self.handle_focus_effect(effect);
1725 }
1726
1727 if self.pending_effects.is_empty() {
1728 for callback in after_window_update_callbacks.drain(..) {
1729 callback(self);
1730 }
1731
1732 for window_id in updated_windows.drain() {
1733 self.update_window(window_id, |cx| {
1734 if let Some(scene) = cx.paint().log_err() {
1735 cx.window.platform_window.present_scene(scene);
1736 }
1737 });
1738 }
1739
1740 if self.pending_effects.is_empty() {
1741 self.flushing_effects = false;
1742 self.pending_notifications.clear();
1743 self.pending_global_notifications.clear();
1744 break;
1745 }
1746 }
1747
1748 refreshing = false;
1749 }
1750 }
1751 }
1752 }
1753
1754 fn window_was_resized(&mut self, window_id: usize) {
1755 self.pending_effects
1756 .push_back(Effect::ResizeWindow { window_id });
1757 }
1758
1759 fn window_was_moved(&mut self, window_id: usize) {
1760 self.pending_effects
1761 .push_back(Effect::MoveWindow { window_id });
1762 }
1763
1764 fn window_was_fullscreen_changed(&mut self, window_id: usize, is_fullscreen: bool) {
1765 self.pending_effects.push_back(Effect::FullscreenWindow {
1766 window_id,
1767 is_fullscreen,
1768 });
1769 }
1770
1771 fn window_changed_active_status(&mut self, window_id: usize, is_active: bool) {
1772 self.pending_effects.push_back(Effect::ActivateWindow {
1773 window_id,
1774 is_active,
1775 });
1776 }
1777
1778 fn keystroke(
1779 &mut self,
1780 window_id: usize,
1781 keystroke: Keystroke,
1782 handled_by: Option<Box<dyn Action>>,
1783 result: MatchResult,
1784 ) {
1785 self.pending_effects.push_back(Effect::Keystroke {
1786 window_id,
1787 keystroke,
1788 handled_by,
1789 result,
1790 });
1791 }
1792
1793 pub fn refresh_windows(&mut self) {
1794 self.pending_effects.push_back(Effect::RefreshWindows);
1795 }
1796
1797 fn emit_global_event(&mut self, payload: Box<dyn Any>) {
1798 let type_id = (&*payload).type_id();
1799
1800 let mut subscriptions = self.global_subscriptions.clone();
1801 subscriptions.emit(type_id, |callback| {
1802 callback(payload.as_ref(), self);
1803 true //Always alive
1804 });
1805 }
1806
1807 fn handle_view_notification_effect(
1808 &mut self,
1809 observed_window_id: usize,
1810 observed_view_id: usize,
1811 ) {
1812 let view_key = (observed_window_id, observed_view_id);
1813 if let Some((view, mut view_metadata)) = self
1814 .views
1815 .remove(&view_key)
1816 .zip(self.views_metadata.remove(&view_key))
1817 {
1818 if let Some(window) = self.windows.get_mut(&observed_window_id) {
1819 window
1820 .invalidation
1821 .get_or_insert_with(Default::default)
1822 .updated
1823 .insert(observed_view_id);
1824 }
1825
1826 view.update_keymap_context(&mut view_metadata.keymap_context, self);
1827 self.views.insert(view_key, view);
1828 self.views_metadata.insert(view_key, view_metadata);
1829
1830 let mut observations = self.observations.clone();
1831 observations.emit(observed_view_id, |callback| callback(self));
1832 }
1833 }
1834
1835 fn handle_entity_release_effect(&mut self, entity_id: usize, entity: &dyn Any) {
1836 self.release_observations
1837 .clone()
1838 .emit(entity_id, |callback| {
1839 callback(entity, self);
1840 // Release observations happen one time. So clear the callback by returning false
1841 false
1842 })
1843 }
1844
1845 fn handle_fullscreen_effect(&mut self, window_id: usize, is_fullscreen: bool) {
1846 self.update_window(window_id, |cx| {
1847 cx.window.is_fullscreen = is_fullscreen;
1848
1849 let mut fullscreen_observations = cx.window_fullscreen_observations.clone();
1850 fullscreen_observations.emit(window_id, |callback| callback(is_fullscreen, cx));
1851
1852 if let Some(uuid) = cx.window_display_uuid() {
1853 let bounds = cx.window_bounds();
1854 let mut bounds_observations = cx.window_bounds_observations.clone();
1855 bounds_observations.emit(window_id, |callback| callback(bounds, uuid, cx));
1856 }
1857
1858 Some(())
1859 });
1860 }
1861
1862 fn handle_keystroke_effect(
1863 &mut self,
1864 window_id: usize,
1865 keystroke: Keystroke,
1866 handled_by: Option<Box<dyn Action>>,
1867 result: MatchResult,
1868 ) {
1869 self.update_window(window_id, |cx| {
1870 let mut observations = cx.keystroke_observations.clone();
1871 observations.emit(window_id, move |callback| {
1872 callback(&keystroke, &result, handled_by.as_ref(), cx)
1873 });
1874 });
1875 }
1876
1877 fn handle_window_activation_effect(&mut self, window_id: usize, active: bool) -> bool {
1878 self.update_window(window_id, |cx| {
1879 if cx.window.is_active == active {
1880 return false;
1881 }
1882 cx.window.is_active = active;
1883
1884 let mut observations = cx.window_activation_observations.clone();
1885 observations.emit(window_id, |callback| callback(active, cx));
1886 true
1887 })
1888 .unwrap_or(false)
1889 }
1890
1891 fn handle_focus_effect(&mut self, effect: FocusEffect) {
1892 let window_id = effect.window_id();
1893 self.update_window(window_id, |cx| {
1894 // Ensure the newly-focused view has been rendered, otherwise focus
1895 // the root view instead.
1896 let focused_id = match effect {
1897 FocusEffect::View { view_id, .. } => {
1898 if let Some(view_id) = view_id {
1899 if cx.window.parents.contains_key(&view_id) {
1900 Some(view_id)
1901 } else {
1902 Some(cx.root_view().id())
1903 }
1904 } else {
1905 None
1906 }
1907 }
1908 FocusEffect::ViewParent { view_id, .. } => Some(
1909 cx.window
1910 .parents
1911 .get(&view_id)
1912 .copied()
1913 .unwrap_or(cx.root_view().id()),
1914 ),
1915 };
1916
1917 let focus_changed = cx.window.focused_view_id != focused_id;
1918 let blurred_id = cx.window.focused_view_id;
1919 cx.window.focused_view_id = focused_id;
1920
1921 if focus_changed {
1922 if let Some(blurred_id) = blurred_id {
1923 for view_id in cx.ancestors(blurred_id).collect::<Vec<_>>() {
1924 if let Some(mut view) = cx.views.remove(&(window_id, view_id)) {
1925 view.focus_out(blurred_id, cx, view_id);
1926 cx.views.insert((window_id, view_id), view);
1927 }
1928 }
1929
1930 let mut subscriptions = cx.focus_observations.clone();
1931 subscriptions.emit(blurred_id, |callback| callback(false, cx));
1932 }
1933 }
1934
1935 if focus_changed || effect.is_forced() {
1936 if let Some(focused_id) = focused_id {
1937 for view_id in cx.ancestors(focused_id).collect::<Vec<_>>() {
1938 if let Some(mut view) = cx.views.remove(&(window_id, view_id)) {
1939 view.focus_in(focused_id, cx, view_id);
1940 cx.views.insert((window_id, view_id), view);
1941 }
1942 }
1943
1944 let mut subscriptions = cx.focus_observations.clone();
1945 subscriptions.emit(focused_id, |callback| callback(true, cx));
1946 }
1947 }
1948 });
1949 }
1950
1951 fn handle_action_dispatch_notification_effect(&mut self, action_id: TypeId) {
1952 self.action_dispatch_observations
1953 .clone()
1954 .emit((), |callback| {
1955 callback(action_id, self);
1956 true
1957 });
1958 }
1959
1960 fn handle_window_should_close_subscription_effect(
1961 &mut self,
1962 window_id: usize,
1963 mut callback: WindowShouldCloseSubscriptionCallback,
1964 ) {
1965 let mut app = self.upgrade();
1966 if let Some(window) = self.windows.get_mut(&window_id) {
1967 window
1968 .platform_window
1969 .on_should_close(Box::new(move || app.update(|cx| callback(cx))))
1970 }
1971 }
1972
1973 fn handle_window_moved(&mut self, window_id: usize) {
1974 self.update_window(window_id, |cx| {
1975 if let Some(display) = cx.window_display_uuid() {
1976 let bounds = cx.window_bounds();
1977 cx.window_bounds_observations
1978 .clone()
1979 .emit(window_id, move |callback| {
1980 callback(bounds, display, cx);
1981 true
1982 });
1983 }
1984 });
1985 }
1986
1987 fn handle_active_labeled_tasks_changed_effect(&mut self) {
1988 self.active_labeled_task_observations
1989 .clone()
1990 .emit((), move |callback| {
1991 callback(self);
1992 true
1993 });
1994 }
1995
1996 pub fn focus(&mut self, window_id: usize, view_id: Option<usize>) {
1997 self.pending_effects
1998 .push_back(Effect::Focus(FocusEffect::View {
1999 window_id,
2000 view_id,
2001 is_forced: false,
2002 }));
2003 }
2004
2005 fn spawn_internal<F, Fut, T>(&mut self, task_name: Option<&'static str>, f: F) -> Task<T>
2006 where
2007 F: FnOnce(AsyncAppContext) -> Fut,
2008 Fut: 'static + Future<Output = T>,
2009 T: 'static,
2010 {
2011 let label_id = task_name.map(|task_name| {
2012 let id = post_inc(&mut self.next_labeled_task_id);
2013 self.active_labeled_tasks.insert(id, task_name);
2014 self.pending_effects
2015 .push_back(Effect::ActiveLabeledTasksChanged);
2016 id
2017 });
2018
2019 let future = f(self.to_async());
2020 let cx = self.to_async();
2021 self.foreground.spawn(async move {
2022 let result = future.await;
2023 let mut cx = cx.0.borrow_mut();
2024
2025 if let Some(completed_label_id) = label_id {
2026 cx.active_labeled_tasks.remove(&completed_label_id);
2027 cx.pending_effects
2028 .push_back(Effect::ActiveLabeledTasksChanged);
2029 }
2030 cx.flush_effects();
2031 result
2032 })
2033 }
2034
2035 pub fn spawn_labeled<F, Fut, T>(&mut self, task_name: &'static str, f: F) -> Task<T>
2036 where
2037 F: FnOnce(AsyncAppContext) -> Fut,
2038 Fut: 'static + Future<Output = T>,
2039 T: 'static,
2040 {
2041 self.spawn_internal(Some(task_name), f)
2042 }
2043
2044 pub fn spawn<F, Fut, T>(&mut self, f: F) -> Task<T>
2045 where
2046 F: FnOnce(AsyncAppContext) -> Fut,
2047 Fut: 'static + Future<Output = T>,
2048 T: 'static,
2049 {
2050 self.spawn_internal(None, f)
2051 }
2052
2053 pub fn to_async(&self) -> AsyncAppContext {
2054 AsyncAppContext(self.weak_self.as_ref().unwrap().upgrade().unwrap())
2055 }
2056
2057 pub fn write_to_clipboard(&self, item: ClipboardItem) {
2058 self.platform.write_to_clipboard(item);
2059 }
2060
2061 pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {
2062 self.platform.read_from_clipboard()
2063 }
2064
2065 #[cfg(any(test, feature = "test-support"))]
2066 pub fn leak_detector(&self) -> Arc<Mutex<LeakDetector>> {
2067 self.ref_counts.lock().leak_detector.clone()
2068 }
2069}
2070
2071impl BorrowAppContext for AppContext {
2072 fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T {
2073 f(self)
2074 }
2075
2076 fn update<T, F: FnOnce(&mut AppContext) -> T>(&mut self, f: F) -> T {
2077 f(self)
2078 }
2079}
2080
2081#[derive(Debug)]
2082pub enum ParentId {
2083 View(usize),
2084 Root,
2085}
2086
2087struct ViewMetadata {
2088 type_id: TypeId,
2089 keymap_context: KeymapContext,
2090}
2091
2092#[derive(Default, Clone)]
2093pub struct WindowInvalidation {
2094 pub updated: HashSet<usize>,
2095 pub removed: Vec<usize>,
2096}
2097
2098#[derive(Debug)]
2099pub enum FocusEffect {
2100 View {
2101 window_id: usize,
2102 view_id: Option<usize>,
2103 is_forced: bool,
2104 },
2105 ViewParent {
2106 window_id: usize,
2107 view_id: usize,
2108 is_forced: bool,
2109 },
2110}
2111
2112impl FocusEffect {
2113 fn window_id(&self) -> usize {
2114 match self {
2115 FocusEffect::View { window_id, .. } => *window_id,
2116 FocusEffect::ViewParent { window_id, .. } => *window_id,
2117 }
2118 }
2119
2120 fn is_forced(&self) -> bool {
2121 match self {
2122 FocusEffect::View { is_forced, .. } => *is_forced,
2123 FocusEffect::ViewParent { is_forced, .. } => *is_forced,
2124 }
2125 }
2126
2127 fn force(&mut self) {
2128 match self {
2129 FocusEffect::View { is_forced, .. } => *is_forced = true,
2130 FocusEffect::ViewParent { is_forced, .. } => *is_forced = true,
2131 }
2132 }
2133}
2134
2135pub enum Effect {
2136 Subscription {
2137 entity_id: usize,
2138 subscription_id: usize,
2139 callback: SubscriptionCallback,
2140 },
2141 Event {
2142 entity_id: usize,
2143 payload: Box<dyn Any>,
2144 },
2145 GlobalSubscription {
2146 type_id: TypeId,
2147 subscription_id: usize,
2148 callback: GlobalSubscriptionCallback,
2149 },
2150 GlobalEvent {
2151 payload: Box<dyn Any>,
2152 },
2153 Observation {
2154 entity_id: usize,
2155 subscription_id: usize,
2156 callback: ObservationCallback,
2157 },
2158 ModelNotification {
2159 model_id: usize,
2160 },
2161 ViewNotification {
2162 window_id: usize,
2163 view_id: usize,
2164 },
2165 Deferred {
2166 callback: Box<dyn FnOnce(&mut AppContext)>,
2167 after_window_update: bool,
2168 },
2169 GlobalNotification {
2170 type_id: TypeId,
2171 },
2172 ModelRelease {
2173 model_id: usize,
2174 model: Box<dyn AnyModel>,
2175 },
2176 ViewRelease {
2177 view_id: usize,
2178 view: Box<dyn AnyView>,
2179 },
2180 Focus(FocusEffect),
2181 FocusObservation {
2182 view_id: usize,
2183 subscription_id: usize,
2184 callback: FocusObservationCallback,
2185 },
2186 ResizeWindow {
2187 window_id: usize,
2188 },
2189 MoveWindow {
2190 window_id: usize,
2191 },
2192 ActivateWindow {
2193 window_id: usize,
2194 is_active: bool,
2195 },
2196 WindowActivationObservation {
2197 window_id: usize,
2198 subscription_id: usize,
2199 callback: WindowActivationCallback,
2200 },
2201 FullscreenWindow {
2202 window_id: usize,
2203 is_fullscreen: bool,
2204 },
2205 WindowFullscreenObservation {
2206 window_id: usize,
2207 subscription_id: usize,
2208 callback: WindowFullscreenCallback,
2209 },
2210 WindowBoundsObservation {
2211 window_id: usize,
2212 subscription_id: usize,
2213 callback: WindowBoundsCallback,
2214 },
2215 Keystroke {
2216 window_id: usize,
2217 keystroke: Keystroke,
2218 handled_by: Option<Box<dyn Action>>,
2219 result: MatchResult,
2220 },
2221 RefreshWindows,
2222 ActionDispatchNotification {
2223 action_id: TypeId,
2224 },
2225 WindowShouldCloseSubscription {
2226 window_id: usize,
2227 callback: WindowShouldCloseSubscriptionCallback,
2228 },
2229 ActiveLabeledTasksChanged,
2230 ActiveLabeledTasksObservation {
2231 subscription_id: usize,
2232 callback: ActiveLabeledTasksCallback,
2233 },
2234}
2235
2236impl Debug for Effect {
2237 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2238 match self {
2239 Effect::Subscription {
2240 entity_id,
2241 subscription_id,
2242 ..
2243 } => f
2244 .debug_struct("Effect::Subscribe")
2245 .field("entity_id", entity_id)
2246 .field("subscription_id", subscription_id)
2247 .finish(),
2248 Effect::Event { entity_id, .. } => f
2249 .debug_struct("Effect::Event")
2250 .field("entity_id", entity_id)
2251 .finish(),
2252 Effect::GlobalSubscription {
2253 type_id,
2254 subscription_id,
2255 ..
2256 } => f
2257 .debug_struct("Effect::Subscribe")
2258 .field("type_id", type_id)
2259 .field("subscription_id", subscription_id)
2260 .finish(),
2261 Effect::GlobalEvent { payload, .. } => f
2262 .debug_struct("Effect::GlobalEvent")
2263 .field("type_id", &(&*payload).type_id())
2264 .finish(),
2265 Effect::Observation {
2266 entity_id,
2267 subscription_id,
2268 ..
2269 } => f
2270 .debug_struct("Effect::Observation")
2271 .field("entity_id", entity_id)
2272 .field("subscription_id", subscription_id)
2273 .finish(),
2274 Effect::ModelNotification { model_id } => f
2275 .debug_struct("Effect::ModelNotification")
2276 .field("model_id", model_id)
2277 .finish(),
2278 Effect::ViewNotification { window_id, view_id } => f
2279 .debug_struct("Effect::ViewNotification")
2280 .field("window_id", window_id)
2281 .field("view_id", view_id)
2282 .finish(),
2283 Effect::GlobalNotification { type_id } => f
2284 .debug_struct("Effect::GlobalNotification")
2285 .field("type_id", type_id)
2286 .finish(),
2287 Effect::Deferred { .. } => f.debug_struct("Effect::Deferred").finish(),
2288 Effect::ModelRelease { model_id, .. } => f
2289 .debug_struct("Effect::ModelRelease")
2290 .field("model_id", model_id)
2291 .finish(),
2292 Effect::ViewRelease { view_id, .. } => f
2293 .debug_struct("Effect::ViewRelease")
2294 .field("view_id", view_id)
2295 .finish(),
2296 Effect::Focus(focus) => f.debug_tuple("Effect::Focus").field(focus).finish(),
2297 Effect::FocusObservation {
2298 view_id,
2299 subscription_id,
2300 ..
2301 } => f
2302 .debug_struct("Effect::FocusObservation")
2303 .field("view_id", view_id)
2304 .field("subscription_id", subscription_id)
2305 .finish(),
2306 Effect::ActionDispatchNotification { action_id, .. } => f
2307 .debug_struct("Effect::ActionDispatchNotification")
2308 .field("action_id", action_id)
2309 .finish(),
2310 Effect::ResizeWindow { window_id } => f
2311 .debug_struct("Effect::RefreshWindow")
2312 .field("window_id", window_id)
2313 .finish(),
2314 Effect::MoveWindow { window_id } => f
2315 .debug_struct("Effect::MoveWindow")
2316 .field("window_id", window_id)
2317 .finish(),
2318 Effect::WindowActivationObservation {
2319 window_id,
2320 subscription_id,
2321 ..
2322 } => f
2323 .debug_struct("Effect::WindowActivationObservation")
2324 .field("window_id", window_id)
2325 .field("subscription_id", subscription_id)
2326 .finish(),
2327 Effect::ActivateWindow {
2328 window_id,
2329 is_active,
2330 } => f
2331 .debug_struct("Effect::ActivateWindow")
2332 .field("window_id", window_id)
2333 .field("is_active", is_active)
2334 .finish(),
2335 Effect::FullscreenWindow {
2336 window_id,
2337 is_fullscreen,
2338 } => f
2339 .debug_struct("Effect::FullscreenWindow")
2340 .field("window_id", window_id)
2341 .field("is_fullscreen", is_fullscreen)
2342 .finish(),
2343 Effect::WindowFullscreenObservation {
2344 window_id,
2345 subscription_id,
2346 callback: _,
2347 } => f
2348 .debug_struct("Effect::WindowFullscreenObservation")
2349 .field("window_id", window_id)
2350 .field("subscription_id", subscription_id)
2351 .finish(),
2352
2353 Effect::WindowBoundsObservation {
2354 window_id,
2355 subscription_id,
2356 callback: _,
2357 } => f
2358 .debug_struct("Effect::WindowBoundsObservation")
2359 .field("window_id", window_id)
2360 .field("subscription_id", subscription_id)
2361 .finish(),
2362 Effect::RefreshWindows => f.debug_struct("Effect::FullViewRefresh").finish(),
2363 Effect::WindowShouldCloseSubscription { window_id, .. } => f
2364 .debug_struct("Effect::WindowShouldCloseSubscription")
2365 .field("window_id", window_id)
2366 .finish(),
2367 Effect::Keystroke {
2368 window_id,
2369 keystroke,
2370 handled_by,
2371 result,
2372 } => f
2373 .debug_struct("Effect::Keystroke")
2374 .field("window_id", window_id)
2375 .field("keystroke", keystroke)
2376 .field(
2377 "keystroke",
2378 &handled_by.as_ref().map(|handled_by| handled_by.name()),
2379 )
2380 .field("result", result)
2381 .finish(),
2382 Effect::ActiveLabeledTasksChanged => {
2383 f.debug_struct("Effect::ActiveLabeledTasksChanged").finish()
2384 }
2385 Effect::ActiveLabeledTasksObservation {
2386 subscription_id,
2387 callback: _,
2388 } => f
2389 .debug_struct("Effect::ActiveLabeledTasksObservation")
2390 .field("subscription_id", subscription_id)
2391 .finish(),
2392 }
2393 }
2394}
2395
2396pub trait AnyModel {
2397 fn as_any(&self) -> &dyn Any;
2398 fn as_any_mut(&mut self) -> &mut dyn Any;
2399 fn release(&mut self, cx: &mut AppContext);
2400 fn app_will_quit(
2401 &mut self,
2402 cx: &mut AppContext,
2403 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
2404}
2405
2406impl<T> AnyModel for T
2407where
2408 T: Entity,
2409{
2410 fn as_any(&self) -> &dyn Any {
2411 self
2412 }
2413
2414 fn as_any_mut(&mut self) -> &mut dyn Any {
2415 self
2416 }
2417
2418 fn release(&mut self, cx: &mut AppContext) {
2419 self.release(cx);
2420 }
2421
2422 fn app_will_quit(
2423 &mut self,
2424 cx: &mut AppContext,
2425 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
2426 self.app_will_quit(cx)
2427 }
2428}
2429
2430pub trait AnyView {
2431 fn as_any(&self) -> &dyn Any;
2432 fn as_any_mut(&mut self) -> &mut dyn Any;
2433 fn release(&mut self, cx: &mut AppContext);
2434 fn app_will_quit(
2435 &mut self,
2436 cx: &mut AppContext,
2437 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
2438 fn ui_name(&self) -> &'static str;
2439 fn render(&mut self, cx: &mut WindowContext, view_id: usize) -> Box<dyn AnyRootElement>;
2440 fn focus_in<'a, 'b>(&mut self, focused_id: usize, cx: &mut WindowContext<'a>, view_id: usize);
2441 fn focus_out(&mut self, focused_id: usize, cx: &mut WindowContext, view_id: usize);
2442 fn key_down(&mut self, event: &KeyDownEvent, cx: &mut WindowContext, view_id: usize) -> bool;
2443 fn key_up(&mut self, event: &KeyUpEvent, cx: &mut WindowContext, view_id: usize) -> bool;
2444 fn modifiers_changed(
2445 &mut self,
2446 event: &ModifiersChangedEvent,
2447 cx: &mut WindowContext,
2448 view_id: usize,
2449 ) -> bool;
2450 fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext);
2451 fn debug_json(&self, cx: &WindowContext) -> serde_json::Value;
2452
2453 fn text_for_range(&self, range: Range<usize>, cx: &WindowContext) -> Option<String>;
2454 fn selected_text_range(&self, cx: &WindowContext) -> Option<Range<usize>>;
2455 fn marked_text_range(&self, cx: &WindowContext) -> Option<Range<usize>>;
2456 fn unmark_text(&mut self, cx: &mut WindowContext, view_id: usize);
2457 fn replace_text_in_range(
2458 &mut self,
2459 range: Option<Range<usize>>,
2460 text: &str,
2461 cx: &mut WindowContext,
2462 view_id: usize,
2463 );
2464 fn replace_and_mark_text_in_range(
2465 &mut self,
2466 range: Option<Range<usize>>,
2467 new_text: &str,
2468 new_selected_range: Option<Range<usize>>,
2469 cx: &mut WindowContext,
2470 view_id: usize,
2471 );
2472 fn any_handle(&self, window_id: usize, view_id: usize, cx: &AppContext) -> AnyViewHandle {
2473 AnyViewHandle::new(
2474 window_id,
2475 view_id,
2476 self.as_any().type_id(),
2477 cx.ref_counts.clone(),
2478 )
2479 }
2480}
2481
2482impl<V> AnyView for V
2483where
2484 V: View,
2485{
2486 fn as_any(&self) -> &dyn Any {
2487 self
2488 }
2489
2490 fn as_any_mut(&mut self) -> &mut dyn Any {
2491 self
2492 }
2493
2494 fn release(&mut self, cx: &mut AppContext) {
2495 self.release(cx);
2496 }
2497
2498 fn app_will_quit(
2499 &mut self,
2500 cx: &mut AppContext,
2501 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
2502 self.app_will_quit(cx)
2503 }
2504
2505 fn ui_name(&self) -> &'static str {
2506 V::ui_name()
2507 }
2508
2509 fn render(&mut self, cx: &mut WindowContext, view_id: usize) -> Box<dyn AnyRootElement> {
2510 let mut view_context = ViewContext::mutable(cx, view_id);
2511 let element = V::render(self, &mut view_context);
2512 let view = WeakViewHandle::new(cx.window_id, view_id);
2513 Box::new(RootElement::new(element, view))
2514 }
2515
2516 fn focus_in(&mut self, focused_id: usize, cx: &mut WindowContext, view_id: usize) {
2517 let mut cx = ViewContext::mutable(cx, view_id);
2518 let focused_view_handle: AnyViewHandle = if view_id == focused_id {
2519 cx.handle().into_any()
2520 } else {
2521 let focused_type = cx
2522 .views_metadata
2523 .get(&(cx.window_id, focused_id))
2524 .unwrap()
2525 .type_id;
2526 AnyViewHandle::new(
2527 cx.window_id,
2528 focused_id,
2529 focused_type,
2530 cx.ref_counts.clone(),
2531 )
2532 };
2533 View::focus_in(self, focused_view_handle, &mut cx);
2534 }
2535
2536 fn focus_out(&mut self, blurred_id: usize, cx: &mut WindowContext, view_id: usize) {
2537 let mut cx = ViewContext::mutable(cx, view_id);
2538 let blurred_view_handle: AnyViewHandle = if view_id == blurred_id {
2539 cx.handle().into_any()
2540 } else {
2541 let blurred_type = cx
2542 .views_metadata
2543 .get(&(cx.window_id, blurred_id))
2544 .unwrap()
2545 .type_id;
2546 AnyViewHandle::new(
2547 cx.window_id,
2548 blurred_id,
2549 blurred_type,
2550 cx.ref_counts.clone(),
2551 )
2552 };
2553 View::focus_out(self, blurred_view_handle, &mut cx);
2554 }
2555
2556 fn key_down(&mut self, event: &KeyDownEvent, cx: &mut WindowContext, view_id: usize) -> bool {
2557 let mut cx = ViewContext::mutable(cx, view_id);
2558 View::key_down(self, event, &mut cx)
2559 }
2560
2561 fn key_up(&mut self, event: &KeyUpEvent, cx: &mut WindowContext, view_id: usize) -> bool {
2562 let mut cx = ViewContext::mutable(cx, view_id);
2563 View::key_up(self, event, &mut cx)
2564 }
2565
2566 fn modifiers_changed(
2567 &mut self,
2568 event: &ModifiersChangedEvent,
2569 cx: &mut WindowContext,
2570 view_id: usize,
2571 ) -> bool {
2572 let mut cx = ViewContext::mutable(cx, view_id);
2573 View::modifiers_changed(self, event, &mut cx)
2574 }
2575
2576 fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
2577 View::update_keymap_context(self, keymap, cx)
2578 }
2579
2580 fn debug_json(&self, cx: &WindowContext) -> serde_json::Value {
2581 View::debug_json(self, cx)
2582 }
2583
2584 fn text_for_range(&self, range: Range<usize>, cx: &WindowContext) -> Option<String> {
2585 View::text_for_range(self, range, cx)
2586 }
2587
2588 fn selected_text_range(&self, cx: &WindowContext) -> Option<Range<usize>> {
2589 View::selected_text_range(self, cx)
2590 }
2591
2592 fn marked_text_range(&self, cx: &WindowContext) -> Option<Range<usize>> {
2593 View::marked_text_range(self, cx)
2594 }
2595
2596 fn unmark_text(&mut self, cx: &mut WindowContext, view_id: usize) {
2597 let mut cx = ViewContext::mutable(cx, view_id);
2598 View::unmark_text(self, &mut cx)
2599 }
2600
2601 fn replace_text_in_range(
2602 &mut self,
2603 range: Option<Range<usize>>,
2604 text: &str,
2605 cx: &mut WindowContext,
2606 view_id: usize,
2607 ) {
2608 let mut cx = ViewContext::mutable(cx, view_id);
2609 View::replace_text_in_range(self, range, text, &mut cx)
2610 }
2611
2612 fn replace_and_mark_text_in_range(
2613 &mut self,
2614 range: Option<Range<usize>>,
2615 new_text: &str,
2616 new_selected_range: Option<Range<usize>>,
2617 cx: &mut WindowContext,
2618 view_id: usize,
2619 ) {
2620 let mut cx = ViewContext::mutable(cx, view_id);
2621 View::replace_and_mark_text_in_range(self, range, new_text, new_selected_range, &mut cx)
2622 }
2623}
2624
2625pub struct ModelContext<'a, T: ?Sized> {
2626 app: &'a mut AppContext,
2627 model_id: usize,
2628 model_type: PhantomData<T>,
2629 halt_stream: bool,
2630}
2631
2632impl<'a, T: Entity> ModelContext<'a, T> {
2633 fn new(app: &'a mut AppContext, model_id: usize) -> Self {
2634 Self {
2635 app,
2636 model_id,
2637 model_type: PhantomData,
2638 halt_stream: false,
2639 }
2640 }
2641
2642 pub fn background(&self) -> &Arc<executor::Background> {
2643 &self.app.background
2644 }
2645
2646 pub fn halt_stream(&mut self) {
2647 self.halt_stream = true;
2648 }
2649
2650 pub fn model_id(&self) -> usize {
2651 self.model_id
2652 }
2653
2654 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
2655 where
2656 S: Entity,
2657 F: FnOnce(&mut ModelContext<S>) -> S,
2658 {
2659 self.app.add_model(build_model)
2660 }
2661
2662 pub fn emit(&mut self, payload: T::Event) {
2663 self.app.pending_effects.push_back(Effect::Event {
2664 entity_id: self.model_id,
2665 payload: Box::new(payload),
2666 });
2667 }
2668
2669 pub fn notify(&mut self) {
2670 self.app.notify_model(self.model_id);
2671 }
2672
2673 pub fn subscribe<S: Entity, F>(
2674 &mut self,
2675 handle: &ModelHandle<S>,
2676 mut callback: F,
2677 ) -> Subscription
2678 where
2679 S::Event: 'static,
2680 F: 'static + FnMut(&mut T, ModelHandle<S>, &S::Event, &mut ModelContext<T>),
2681 {
2682 let subscriber = self.weak_handle();
2683 self.app
2684 .subscribe_internal(handle, move |emitter, event, cx| {
2685 if let Some(subscriber) = subscriber.upgrade(cx) {
2686 subscriber.update(cx, |subscriber, cx| {
2687 callback(subscriber, emitter, event, cx);
2688 });
2689 true
2690 } else {
2691 false
2692 }
2693 })
2694 }
2695
2696 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F) -> Subscription
2697 where
2698 S: Entity,
2699 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ModelContext<T>),
2700 {
2701 let observer = self.weak_handle();
2702 self.app.observe_internal(handle, move |observed, cx| {
2703 if let Some(observer) = observer.upgrade(cx) {
2704 observer.update(cx, |observer, cx| {
2705 callback(observer, observed, cx);
2706 });
2707 true
2708 } else {
2709 false
2710 }
2711 })
2712 }
2713
2714 pub fn observe_global<G, F>(&mut self, mut callback: F) -> Subscription
2715 where
2716 G: Any,
2717 F: 'static + FnMut(&mut T, &mut ModelContext<T>),
2718 {
2719 let observer = self.weak_handle();
2720 self.app.observe_global::<G, _>(move |cx| {
2721 if let Some(observer) = observer.upgrade(cx) {
2722 observer.update(cx, |observer, cx| callback(observer, cx));
2723 }
2724 })
2725 }
2726
2727 pub fn observe_release<S, F>(
2728 &mut self,
2729 handle: &ModelHandle<S>,
2730 mut callback: F,
2731 ) -> Subscription
2732 where
2733 S: Entity,
2734 F: 'static + FnMut(&mut T, &S, &mut ModelContext<T>),
2735 {
2736 let observer = self.weak_handle();
2737 self.app.observe_release(handle, move |released, cx| {
2738 if let Some(observer) = observer.upgrade(cx) {
2739 observer.update(cx, |observer, cx| {
2740 callback(observer, released, cx);
2741 });
2742 }
2743 })
2744 }
2745
2746 pub fn handle(&self) -> ModelHandle<T> {
2747 ModelHandle::new(self.model_id, &self.app.ref_counts)
2748 }
2749
2750 pub fn weak_handle(&self) -> WeakModelHandle<T> {
2751 WeakModelHandle::new(self.model_id)
2752 }
2753
2754 pub fn spawn<F, Fut, S>(&mut self, f: F) -> Task<S>
2755 where
2756 F: FnOnce(ModelHandle<T>, AsyncAppContext) -> Fut,
2757 Fut: 'static + Future<Output = S>,
2758 S: 'static,
2759 {
2760 let handle = self.handle();
2761 self.app.spawn(|cx| f(handle, cx))
2762 }
2763
2764 pub fn spawn_weak<F, Fut, S>(&mut self, f: F) -> Task<S>
2765 where
2766 F: FnOnce(WeakModelHandle<T>, AsyncAppContext) -> Fut,
2767 Fut: 'static + Future<Output = S>,
2768 S: 'static,
2769 {
2770 let handle = self.weak_handle();
2771 self.app.spawn(|cx| f(handle, cx))
2772 }
2773}
2774
2775impl<M> AsRef<AppContext> for ModelContext<'_, M> {
2776 fn as_ref(&self) -> &AppContext {
2777 &self.app
2778 }
2779}
2780
2781impl<M> AsMut<AppContext> for ModelContext<'_, M> {
2782 fn as_mut(&mut self) -> &mut AppContext {
2783 self.app
2784 }
2785}
2786
2787impl<M> BorrowAppContext for ModelContext<'_, M> {
2788 fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T {
2789 self.app.read_with(f)
2790 }
2791
2792 fn update<T, F: FnOnce(&mut AppContext) -> T>(&mut self, f: F) -> T {
2793 self.app.update(f)
2794 }
2795}
2796
2797impl<M> Deref for ModelContext<'_, M> {
2798 type Target = AppContext;
2799
2800 fn deref(&self) -> &Self::Target {
2801 self.app
2802 }
2803}
2804
2805impl<M> DerefMut for ModelContext<'_, M> {
2806 fn deref_mut(&mut self) -> &mut Self::Target {
2807 &mut self.app
2808 }
2809}
2810
2811pub struct ViewContext<'a, 'b, T: ?Sized> {
2812 window_context: Reference<'b, WindowContext<'a>>,
2813 view_id: usize,
2814 view_type: PhantomData<T>,
2815}
2816
2817impl<'a, 'b, T: View> Deref for ViewContext<'a, 'b, T> {
2818 type Target = WindowContext<'a>;
2819
2820 fn deref(&self) -> &Self::Target {
2821 &self.window_context
2822 }
2823}
2824
2825impl<T: View> DerefMut for ViewContext<'_, '_, T> {
2826 fn deref_mut(&mut self) -> &mut Self::Target {
2827 &mut self.window_context
2828 }
2829}
2830
2831impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
2832 pub(crate) fn mutable(window_context: &'b mut WindowContext<'a>, view_id: usize) -> Self {
2833 Self {
2834 window_context: Reference::Mutable(window_context),
2835 view_id,
2836 view_type: PhantomData,
2837 }
2838 }
2839
2840 pub(crate) fn immutable(window_context: &'b WindowContext<'a>, view_id: usize) -> Self {
2841 Self {
2842 window_context: Reference::Immutable(window_context),
2843 view_id,
2844 view_type: PhantomData,
2845 }
2846 }
2847
2848 pub fn window_context(&mut self) -> &mut WindowContext<'a> {
2849 &mut self.window_context
2850 }
2851
2852 pub fn handle(&self) -> ViewHandle<V> {
2853 ViewHandle::new(
2854 self.window_id,
2855 self.view_id,
2856 &self.window_context.ref_counts,
2857 )
2858 }
2859
2860 pub fn weak_handle(&self) -> WeakViewHandle<V> {
2861 WeakViewHandle::new(self.window_id, self.view_id)
2862 }
2863
2864 pub fn window_id(&self) -> usize {
2865 self.window_id
2866 }
2867
2868 pub fn view_id(&self) -> usize {
2869 self.view_id
2870 }
2871
2872 pub fn foreground(&self) -> &Rc<executor::Foreground> {
2873 self.window_context.foreground()
2874 }
2875
2876 pub fn background_executor(&self) -> &Arc<executor::Background> {
2877 &self.window_context.background
2878 }
2879
2880 pub fn platform(&self) -> &Arc<dyn Platform> {
2881 self.window_context.platform()
2882 }
2883
2884 pub fn prompt_for_paths(
2885 &self,
2886 options: PathPromptOptions,
2887 ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
2888 self.window_context.prompt_for_paths(options)
2889 }
2890
2891 pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
2892 self.window_context.prompt_for_new_path(directory)
2893 }
2894
2895 pub fn reveal_path(&self, path: &Path) {
2896 self.window_context.reveal_path(path)
2897 }
2898
2899 pub fn focus(&mut self, handle: &AnyViewHandle) {
2900 self.window_context
2901 .focus(handle.window_id, Some(handle.view_id));
2902 }
2903
2904 pub fn focus_self(&mut self) {
2905 let window_id = self.window_id;
2906 let view_id = self.view_id;
2907 self.window_context.focus(window_id, Some(view_id));
2908 }
2909
2910 pub fn is_self_focused(&self) -> bool {
2911 self.window.focused_view_id == Some(self.view_id)
2912 }
2913
2914 pub fn focus_parent(&mut self) {
2915 let window_id = self.window_id;
2916 let view_id = self.view_id;
2917 self.pending_effects
2918 .push_back(Effect::Focus(FocusEffect::ViewParent {
2919 window_id,
2920 view_id,
2921 is_forced: false,
2922 }));
2923 }
2924
2925 pub fn blur(&mut self) {
2926 let window_id = self.window_id;
2927 self.window_context.focus(window_id, None);
2928 }
2929
2930 pub fn on_window_should_close<F>(&mut self, mut callback: F)
2931 where
2932 F: 'static + FnMut(&mut V, &mut ViewContext<V>) -> bool,
2933 {
2934 let window_id = self.window_id;
2935 let view = self.weak_handle();
2936 self.pending_effects
2937 .push_back(Effect::WindowShouldCloseSubscription {
2938 window_id,
2939 callback: Box::new(move |cx| {
2940 cx.update_window(window_id, |cx| {
2941 if let Some(view) = view.upgrade(cx) {
2942 view.update(cx, |view, cx| callback(view, cx))
2943 } else {
2944 true
2945 }
2946 })
2947 .unwrap_or(true)
2948 }),
2949 });
2950 }
2951
2952 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
2953 where
2954 E: Entity,
2955 E::Event: 'static,
2956 H: Handle<E>,
2957 F: 'static + FnMut(&mut V, H, &E::Event, &mut ViewContext<V>),
2958 {
2959 let subscriber = self.weak_handle();
2960 self.window_context
2961 .subscribe_internal(handle, move |emitter, event, cx| {
2962 if let Some(subscriber) = subscriber.upgrade(cx) {
2963 subscriber.update(cx, |subscriber, cx| {
2964 callback(subscriber, emitter, event, cx);
2965 });
2966 true
2967 } else {
2968 false
2969 }
2970 })
2971 }
2972
2973 pub fn observe<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
2974 where
2975 E: Entity,
2976 H: Handle<E>,
2977 F: 'static + FnMut(&mut V, H, &mut ViewContext<V>),
2978 {
2979 let window_id = self.window_id;
2980 let observer = self.weak_handle();
2981 self.window_context
2982 .observe_internal(handle, move |observed, cx| {
2983 cx.update_window(window_id, |cx| {
2984 if let Some(observer) = observer.upgrade(cx) {
2985 observer.update(cx, |observer, cx| {
2986 callback(observer, observed, cx);
2987 });
2988 true
2989 } else {
2990 false
2991 }
2992 })
2993 .unwrap_or(false)
2994 })
2995 }
2996
2997 pub fn observe_global<G, F>(&mut self, mut callback: F) -> Subscription
2998 where
2999 G: Any,
3000 F: 'static + FnMut(&mut V, &mut ViewContext<V>),
3001 {
3002 let window_id = self.window_id;
3003 let observer = self.weak_handle();
3004 self.window_context.observe_global::<G, _>(move |cx| {
3005 cx.update_window(window_id, |cx| {
3006 if let Some(observer) = observer.upgrade(cx) {
3007 observer.update(cx, |observer, cx| callback(observer, cx));
3008 }
3009 });
3010 })
3011 }
3012
3013 pub fn observe_focus<F, W>(&mut self, handle: &ViewHandle<W>, mut callback: F) -> Subscription
3014 where
3015 F: 'static + FnMut(&mut V, ViewHandle<W>, bool, &mut ViewContext<V>),
3016 W: View,
3017 {
3018 let observer = self.weak_handle();
3019 self.window_context
3020 .observe_focus(handle, move |observed, focused, cx| {
3021 if let Some(observer) = observer.upgrade(cx) {
3022 observer.update(cx, |observer, cx| {
3023 callback(observer, observed, focused, cx);
3024 });
3025 true
3026 } else {
3027 false
3028 }
3029 })
3030 }
3031
3032 pub fn observe_release<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
3033 where
3034 E: Entity,
3035 H: Handle<E>,
3036 F: 'static + FnMut(&mut V, &E, &mut ViewContext<V>),
3037 {
3038 let window_id = self.window_id;
3039 let observer = self.weak_handle();
3040 self.window_context
3041 .observe_release(handle, move |released, cx| {
3042 cx.update_window(window_id, |cx| {
3043 if let Some(observer) = observer.upgrade(cx) {
3044 observer.update(cx, |observer, cx| {
3045 callback(observer, released, cx);
3046 });
3047 }
3048 });
3049 })
3050 }
3051
3052 pub fn observe_actions<F>(&mut self, mut callback: F) -> Subscription
3053 where
3054 F: 'static + FnMut(&mut V, TypeId, &mut ViewContext<V>),
3055 {
3056 let window_id = self.window_id;
3057 let observer = self.weak_handle();
3058 self.window_context.observe_actions(move |action_id, cx| {
3059 cx.update_window(window_id, |cx| {
3060 if let Some(observer) = observer.upgrade(cx) {
3061 observer.update(cx, |observer, cx| {
3062 callback(observer, action_id, cx);
3063 });
3064 }
3065 });
3066 })
3067 }
3068
3069 pub fn observe_window_activation<F>(&mut self, mut callback: F) -> Subscription
3070 where
3071 F: 'static + FnMut(&mut V, bool, &mut ViewContext<V>),
3072 {
3073 let observer = self.weak_handle();
3074 self.window_context
3075 .observe_window_activation(move |active, cx| {
3076 if let Some(observer) = observer.upgrade(cx) {
3077 observer.update(cx, |observer, cx| {
3078 callback(observer, active, cx);
3079 });
3080 true
3081 } else {
3082 false
3083 }
3084 })
3085 }
3086
3087 pub fn observe_fullscreen<F>(&mut self, mut callback: F) -> Subscription
3088 where
3089 F: 'static + FnMut(&mut V, bool, &mut ViewContext<V>),
3090 {
3091 let observer = self.weak_handle();
3092 self.window_context.observe_fullscreen(move |active, cx| {
3093 if let Some(observer) = observer.upgrade(cx) {
3094 observer.update(cx, |observer, cx| {
3095 callback(observer, active, cx);
3096 });
3097 true
3098 } else {
3099 false
3100 }
3101 })
3102 }
3103
3104 pub fn observe_keystrokes<F>(&mut self, mut callback: F) -> Subscription
3105 where
3106 F: 'static
3107 + FnMut(
3108 &mut V,
3109 &Keystroke,
3110 Option<&Box<dyn Action>>,
3111 &MatchResult,
3112 &mut ViewContext<V>,
3113 ) -> bool,
3114 {
3115 let observer = self.weak_handle();
3116 self.window_context
3117 .observe_keystrokes(move |keystroke, result, handled_by, cx| {
3118 if let Some(observer) = observer.upgrade(cx) {
3119 observer.update(cx, |observer, cx| {
3120 callback(observer, keystroke, handled_by, result, cx);
3121 });
3122 true
3123 } else {
3124 false
3125 }
3126 })
3127 }
3128
3129 pub fn observe_window_bounds<F>(&mut self, mut callback: F) -> Subscription
3130 where
3131 F: 'static + FnMut(&mut V, WindowBounds, Uuid, &mut ViewContext<V>),
3132 {
3133 let observer = self.weak_handle();
3134 self.window_context
3135 .observe_window_bounds(move |bounds, display, cx| {
3136 if let Some(observer) = observer.upgrade(cx) {
3137 observer.update(cx, |observer, cx| {
3138 callback(observer, bounds, display, cx);
3139 });
3140 true
3141 } else {
3142 false
3143 }
3144 })
3145 }
3146
3147 pub fn observe_active_labeled_tasks<F>(&mut self, mut callback: F) -> Subscription
3148 where
3149 F: 'static + FnMut(&mut V, &mut ViewContext<V>),
3150 {
3151 let window_id = self.window_id;
3152 let observer = self.weak_handle();
3153 self.window_context.observe_active_labeled_tasks(move |cx| {
3154 cx.update_window(window_id, |cx| {
3155 if let Some(observer) = observer.upgrade(cx) {
3156 observer.update(cx, |observer, cx| {
3157 callback(observer, cx);
3158 });
3159 true
3160 } else {
3161 false
3162 }
3163 })
3164 .unwrap_or(false)
3165 })
3166 }
3167
3168 pub fn emit(&mut self, payload: V::Event) {
3169 self.window_context
3170 .pending_effects
3171 .push_back(Effect::Event {
3172 entity_id: self.view_id,
3173 payload: Box::new(payload),
3174 });
3175 }
3176
3177 pub fn notify(&mut self) {
3178 let window_id = self.window_id;
3179 let view_id = self.view_id;
3180 self.window_context.notify_view(window_id, view_id);
3181 }
3182
3183 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut V, &mut ViewContext<V>)) {
3184 let handle = self.handle();
3185 self.window_context
3186 .defer(move |cx| handle.update(cx, |view, cx| callback(view, cx)))
3187 }
3188
3189 pub fn after_window_update(
3190 &mut self,
3191 callback: impl 'static + FnOnce(&mut V, &mut ViewContext<V>),
3192 ) {
3193 let window_id = self.window_id;
3194 let handle = self.handle();
3195 self.window_context.after_window_update(move |cx| {
3196 cx.update_window(window_id, |cx| {
3197 handle.update(cx, |view, cx| {
3198 callback(view, cx);
3199 })
3200 });
3201 })
3202 }
3203
3204 pub fn propagate_action(&mut self) {
3205 self.window_context.halt_action_dispatch = false;
3206 }
3207
3208 pub fn spawn_labeled<F, Fut, S>(&mut self, task_label: &'static str, f: F) -> Task<S>
3209 where
3210 F: FnOnce(WeakViewHandle<V>, AsyncAppContext) -> Fut,
3211 Fut: 'static + Future<Output = S>,
3212 S: 'static,
3213 {
3214 let handle = self.weak_handle();
3215 self.window_context
3216 .spawn_labeled(task_label, |cx| f(handle, cx))
3217 }
3218
3219 pub fn spawn<F, Fut, S>(&mut self, f: F) -> Task<S>
3220 where
3221 F: FnOnce(WeakViewHandle<V>, AsyncAppContext) -> Fut,
3222 Fut: 'static + Future<Output = S>,
3223 S: 'static,
3224 {
3225 let handle = self.weak_handle();
3226 self.window_context.spawn(|cx| f(handle, cx))
3227 }
3228
3229 pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
3230 let region_id = MouseRegionId::new::<Tag>(self.view_id, region_id);
3231 MouseState {
3232 hovered: self.window.hovered_region_ids.contains(®ion_id),
3233 clicked: self
3234 .window
3235 .clicked_region_ids
3236 .get(®ion_id)
3237 .and_then(|_| self.window.clicked_button),
3238 accessed_hovered: false,
3239 accessed_clicked: false,
3240 }
3241 }
3242
3243 pub fn element_state<Tag: 'static, T: 'static>(
3244 &mut self,
3245 element_id: usize,
3246 initial: T,
3247 ) -> ElementStateHandle<T> {
3248 let id = ElementStateId {
3249 view_id: self.view_id(),
3250 element_id,
3251 tag: TypeId::of::<Tag>(),
3252 };
3253 self.element_states
3254 .entry(id)
3255 .or_insert_with(|| Box::new(initial));
3256 ElementStateHandle::new(id, self.frame_count, &self.ref_counts)
3257 }
3258
3259 pub fn default_element_state<Tag: 'static, T: 'static + Default>(
3260 &mut self,
3261 element_id: usize,
3262 ) -> ElementStateHandle<T> {
3263 self.element_state::<Tag, T>(element_id, T::default())
3264 }
3265}
3266
3267impl<V> BorrowAppContext for ViewContext<'_, '_, V> {
3268 fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T {
3269 BorrowAppContext::read_with(&*self.window_context, f)
3270 }
3271
3272 fn update<T, F: FnOnce(&mut AppContext) -> T>(&mut self, f: F) -> T {
3273 BorrowAppContext::update(&mut *self.window_context, f)
3274 }
3275}
3276
3277impl<V> BorrowWindowContext for ViewContext<'_, '_, V> {
3278 fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
3279 BorrowWindowContext::read_with(&*self.window_context, window_id, f)
3280 }
3281
3282 fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
3283 BorrowWindowContext::update(&mut *self.window_context, window_id, f)
3284 }
3285}
3286
3287pub struct LayoutContext<'a, 'b, 'c, V: View> {
3288 view_context: &'c mut ViewContext<'a, 'b, V>,
3289 new_parents: &'c mut HashMap<usize, usize>,
3290 views_to_notify_if_ancestors_change: &'c mut HashMap<usize, SmallVec<[usize; 2]>>,
3291 pub refreshing: bool,
3292}
3293
3294impl<'a, 'b, 'c, V: View> LayoutContext<'a, 'b, 'c, V> {
3295 pub fn new(
3296 view_context: &'c mut ViewContext<'a, 'b, V>,
3297 new_parents: &'c mut HashMap<usize, usize>,
3298 views_to_notify_if_ancestors_change: &'c mut HashMap<usize, SmallVec<[usize; 2]>>,
3299 refreshing: bool,
3300 ) -> Self {
3301 Self {
3302 view_context,
3303 new_parents,
3304 views_to_notify_if_ancestors_change,
3305 refreshing,
3306 }
3307 }
3308
3309 pub fn view_context(&mut self) -> &mut ViewContext<'a, 'b, V> {
3310 self.view_context
3311 }
3312
3313 /// Return keystrokes that would dispatch the given action on the given view.
3314 pub(crate) fn keystrokes_for_action(
3315 &mut self,
3316 view_id: usize,
3317 action: &dyn Action,
3318 ) -> Option<SmallVec<[Keystroke; 2]>> {
3319 self.notify_if_view_ancestors_change(view_id);
3320
3321 let window_id = self.window_id;
3322 let mut contexts = Vec::new();
3323 let mut handler_depth = None;
3324 for (i, view_id) in self.ancestors(view_id).enumerate() {
3325 if let Some(view_metadata) = self.views_metadata.get(&(window_id, view_id)) {
3326 if let Some(actions) = self.actions.get(&view_metadata.type_id) {
3327 if actions.contains_key(&action.as_any().type_id()) {
3328 handler_depth = Some(i);
3329 }
3330 }
3331 contexts.push(view_metadata.keymap_context.clone());
3332 }
3333 }
3334
3335 if self.global_actions.contains_key(&action.as_any().type_id()) {
3336 handler_depth = Some(contexts.len())
3337 }
3338
3339 self.keystroke_matcher
3340 .bindings_for_action_type(action.as_any().type_id())
3341 .find_map(|b| {
3342 handler_depth
3343 .map(|highest_handler| {
3344 if (0..=highest_handler).any(|depth| b.match_context(&contexts[depth..])) {
3345 Some(b.keystrokes().into())
3346 } else {
3347 None
3348 }
3349 })
3350 .flatten()
3351 })
3352 }
3353
3354 fn notify_if_view_ancestors_change(&mut self, view_id: usize) {
3355 let self_view_id = self.view_id;
3356 self.views_to_notify_if_ancestors_change
3357 .entry(view_id)
3358 .or_default()
3359 .push(self_view_id);
3360 }
3361}
3362
3363impl<'a, 'b, 'c, V: View> Deref for LayoutContext<'a, 'b, 'c, V> {
3364 type Target = ViewContext<'a, 'b, V>;
3365
3366 fn deref(&self) -> &Self::Target {
3367 &self.view_context
3368 }
3369}
3370
3371impl<V: View> DerefMut for LayoutContext<'_, '_, '_, V> {
3372 fn deref_mut(&mut self) -> &mut Self::Target {
3373 &mut self.view_context
3374 }
3375}
3376
3377impl<V: View> BorrowAppContext for LayoutContext<'_, '_, '_, V> {
3378 fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T {
3379 BorrowAppContext::read_with(&*self.view_context, f)
3380 }
3381
3382 fn update<T, F: FnOnce(&mut AppContext) -> T>(&mut self, f: F) -> T {
3383 BorrowAppContext::update(&mut *self.view_context, f)
3384 }
3385}
3386
3387impl<V: View> BorrowWindowContext for LayoutContext<'_, '_, '_, V> {
3388 fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
3389 BorrowWindowContext::read_with(&*self.view_context, window_id, f)
3390 }
3391
3392 fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
3393 BorrowWindowContext::update(&mut *self.view_context, window_id, f)
3394 }
3395}
3396
3397pub struct EventContext<'a, 'b, 'c, V: View> {
3398 view_context: &'c mut ViewContext<'a, 'b, V>,
3399 pub(crate) handled: bool,
3400}
3401
3402impl<'a, 'b, 'c, V: View> EventContext<'a, 'b, 'c, V> {
3403 pub(crate) fn new(view_context: &'c mut ViewContext<'a, 'b, V>) -> Self {
3404 EventContext {
3405 view_context,
3406 handled: true,
3407 }
3408 }
3409
3410 pub fn propagate_event(&mut self) {
3411 self.handled = false;
3412 }
3413}
3414
3415impl<'a, 'b, 'c, V: View> Deref for EventContext<'a, 'b, 'c, V> {
3416 type Target = ViewContext<'a, 'b, V>;
3417
3418 fn deref(&self) -> &Self::Target {
3419 &self.view_context
3420 }
3421}
3422
3423impl<V: View> DerefMut for EventContext<'_, '_, '_, V> {
3424 fn deref_mut(&mut self) -> &mut Self::Target {
3425 &mut self.view_context
3426 }
3427}
3428
3429impl<V: View> BorrowAppContext for EventContext<'_, '_, '_, V> {
3430 fn read_with<T, F: FnOnce(&AppContext) -> T>(&self, f: F) -> T {
3431 BorrowAppContext::read_with(&*self.view_context, f)
3432 }
3433
3434 fn update<T, F: FnOnce(&mut AppContext) -> T>(&mut self, f: F) -> T {
3435 BorrowAppContext::update(&mut *self.view_context, f)
3436 }
3437}
3438
3439impl<V: View> BorrowWindowContext for EventContext<'_, '_, '_, V> {
3440 fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
3441 BorrowWindowContext::read_with(&*self.view_context, window_id, f)
3442 }
3443
3444 fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
3445 BorrowWindowContext::update(&mut *self.view_context, window_id, f)
3446 }
3447}
3448
3449pub(crate) enum Reference<'a, T> {
3450 Immutable(&'a T),
3451 Mutable(&'a mut T),
3452}
3453
3454impl<'a, T> Deref for Reference<'a, T> {
3455 type Target = T;
3456
3457 fn deref(&self) -> &Self::Target {
3458 match self {
3459 Reference::Immutable(target) => target,
3460 Reference::Mutable(target) => target,
3461 }
3462 }
3463}
3464
3465impl<'a, T> DerefMut for Reference<'a, T> {
3466 fn deref_mut(&mut self) -> &mut Self::Target {
3467 match self {
3468 Reference::Immutable(_) => {
3469 panic!("cannot mutably deref an immutable reference. this is a bug in GPUI.");
3470 }
3471 Reference::Mutable(target) => target,
3472 }
3473 }
3474}
3475
3476#[derive(Debug, Clone, Default)]
3477pub struct MouseState {
3478 pub(crate) hovered: bool,
3479 pub(crate) clicked: Option<MouseButton>,
3480 pub(crate) accessed_hovered: bool,
3481 pub(crate) accessed_clicked: bool,
3482}
3483
3484impl MouseState {
3485 pub fn hovered(&mut self) -> bool {
3486 self.accessed_hovered = true;
3487 self.hovered
3488 }
3489
3490 pub fn clicked(&mut self) -> Option<MouseButton> {
3491 self.accessed_clicked = true;
3492 self.clicked
3493 }
3494
3495 pub fn accessed_hovered(&self) -> bool {
3496 self.accessed_hovered
3497 }
3498
3499 pub fn accessed_clicked(&self) -> bool {
3500 self.accessed_clicked
3501 }
3502}
3503
3504pub trait Handle<T> {
3505 type Weak: 'static;
3506 fn id(&self) -> usize;
3507 fn location(&self) -> EntityLocation;
3508 fn downgrade(&self) -> Self::Weak;
3509 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
3510 where
3511 Self: Sized;
3512}
3513
3514pub trait WeakHandle {
3515 fn id(&self) -> usize;
3516}
3517
3518#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
3519pub enum EntityLocation {
3520 Model(usize),
3521 View(usize, usize),
3522}
3523
3524pub struct ModelHandle<T: Entity> {
3525 any_handle: AnyModelHandle,
3526 model_type: PhantomData<T>,
3527}
3528
3529impl<T: Entity> Deref for ModelHandle<T> {
3530 type Target = AnyModelHandle;
3531
3532 fn deref(&self) -> &Self::Target {
3533 &self.any_handle
3534 }
3535}
3536
3537impl<T: Entity> ModelHandle<T> {
3538 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
3539 Self {
3540 any_handle: AnyModelHandle::new(model_id, TypeId::of::<T>(), ref_counts.clone()),
3541 model_type: PhantomData,
3542 }
3543 }
3544
3545 pub fn downgrade(&self) -> WeakModelHandle<T> {
3546 WeakModelHandle::new(self.model_id)
3547 }
3548
3549 pub fn id(&self) -> usize {
3550 self.model_id
3551 }
3552
3553 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
3554 cx.read_model(self)
3555 }
3556
3557 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
3558 where
3559 C: BorrowAppContext,
3560 F: FnOnce(&T, &AppContext) -> S,
3561 {
3562 cx.read_with(|cx| read(self.read(cx), cx))
3563 }
3564
3565 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
3566 where
3567 C: BorrowAppContext,
3568 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
3569 {
3570 let mut update = Some(update);
3571 cx.update(|cx| {
3572 cx.update_model(self, &mut |model, cx| {
3573 let update = update.take().unwrap();
3574 update(model, cx)
3575 })
3576 })
3577 }
3578}
3579
3580impl<T: Entity> Clone for ModelHandle<T> {
3581 fn clone(&self) -> Self {
3582 Self::new(self.model_id, &self.ref_counts)
3583 }
3584}
3585
3586impl<T: Entity> PartialEq for ModelHandle<T> {
3587 fn eq(&self, other: &Self) -> bool {
3588 self.model_id == other.model_id
3589 }
3590}
3591
3592impl<T: Entity> Eq for ModelHandle<T> {}
3593
3594impl<T: Entity> PartialEq<WeakModelHandle<T>> for ModelHandle<T> {
3595 fn eq(&self, other: &WeakModelHandle<T>) -> bool {
3596 self.model_id == other.model_id
3597 }
3598}
3599
3600impl<T: Entity> Hash for ModelHandle<T> {
3601 fn hash<H: Hasher>(&self, state: &mut H) {
3602 self.model_id.hash(state);
3603 }
3604}
3605
3606impl<T: Entity> std::borrow::Borrow<usize> for ModelHandle<T> {
3607 fn borrow(&self) -> &usize {
3608 &self.model_id
3609 }
3610}
3611
3612impl<T: Entity> Debug for ModelHandle<T> {
3613 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3614 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
3615 .field(&self.model_id)
3616 .finish()
3617 }
3618}
3619
3620unsafe impl<T: Entity> Send for ModelHandle<T> {}
3621unsafe impl<T: Entity> Sync for ModelHandle<T> {}
3622
3623impl<T: Entity> Handle<T> for ModelHandle<T> {
3624 type Weak = WeakModelHandle<T>;
3625
3626 fn id(&self) -> usize {
3627 self.model_id
3628 }
3629
3630 fn location(&self) -> EntityLocation {
3631 EntityLocation::Model(self.model_id)
3632 }
3633
3634 fn downgrade(&self) -> Self::Weak {
3635 self.downgrade()
3636 }
3637
3638 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
3639 where
3640 Self: Sized,
3641 {
3642 weak.upgrade(cx)
3643 }
3644}
3645
3646pub struct WeakModelHandle<T> {
3647 any_handle: AnyWeakModelHandle,
3648 model_type: PhantomData<T>,
3649}
3650
3651impl<T> WeakModelHandle<T> {
3652 pub fn into_any(self) -> AnyWeakModelHandle {
3653 self.any_handle
3654 }
3655}
3656
3657impl<T> Deref for WeakModelHandle<T> {
3658 type Target = AnyWeakModelHandle;
3659
3660 fn deref(&self) -> &Self::Target {
3661 &self.any_handle
3662 }
3663}
3664
3665impl<T> WeakHandle for WeakModelHandle<T> {
3666 fn id(&self) -> usize {
3667 self.model_id
3668 }
3669}
3670
3671unsafe impl<T> Send for WeakModelHandle<T> {}
3672unsafe impl<T> Sync for WeakModelHandle<T> {}
3673
3674impl<T: Entity> WeakModelHandle<T> {
3675 fn new(model_id: usize) -> Self {
3676 Self {
3677 any_handle: AnyWeakModelHandle {
3678 model_id,
3679 model_type: TypeId::of::<T>(),
3680 },
3681 model_type: PhantomData,
3682 }
3683 }
3684
3685 pub fn id(&self) -> usize {
3686 self.model_id
3687 }
3688
3689 pub fn is_upgradable(&self, cx: &impl BorrowAppContext) -> bool {
3690 cx.read_with(|cx| cx.model_handle_is_upgradable(self))
3691 }
3692
3693 pub fn upgrade(&self, cx: &impl BorrowAppContext) -> Option<ModelHandle<T>> {
3694 cx.read_with(|cx| cx.upgrade_model_handle(self))
3695 }
3696}
3697
3698impl<T> Hash for WeakModelHandle<T> {
3699 fn hash<H: Hasher>(&self, state: &mut H) {
3700 self.model_id.hash(state)
3701 }
3702}
3703
3704impl<T> PartialEq for WeakModelHandle<T> {
3705 fn eq(&self, other: &Self) -> bool {
3706 self.model_id == other.model_id
3707 }
3708}
3709
3710impl<T> Eq for WeakModelHandle<T> {}
3711
3712impl<T: Entity> PartialEq<ModelHandle<T>> for WeakModelHandle<T> {
3713 fn eq(&self, other: &ModelHandle<T>) -> bool {
3714 self.model_id == other.model_id
3715 }
3716}
3717
3718impl<T> Clone for WeakModelHandle<T> {
3719 fn clone(&self) -> Self {
3720 Self {
3721 any_handle: self.any_handle.clone(),
3722 model_type: PhantomData,
3723 }
3724 }
3725}
3726
3727impl<T> Copy for WeakModelHandle<T> {}
3728
3729#[repr(transparent)]
3730pub struct ViewHandle<T> {
3731 any_handle: AnyViewHandle,
3732 view_type: PhantomData<T>,
3733}
3734
3735impl<T> Deref for ViewHandle<T> {
3736 type Target = AnyViewHandle;
3737
3738 fn deref(&self) -> &Self::Target {
3739 &self.any_handle
3740 }
3741}
3742
3743impl<T: View> ViewHandle<T> {
3744 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
3745 Self {
3746 any_handle: AnyViewHandle::new(
3747 window_id,
3748 view_id,
3749 TypeId::of::<T>(),
3750 ref_counts.clone(),
3751 ),
3752 view_type: PhantomData,
3753 }
3754 }
3755
3756 pub fn downgrade(&self) -> WeakViewHandle<T> {
3757 WeakViewHandle::new(self.window_id, self.view_id)
3758 }
3759
3760 pub fn into_any(self) -> AnyViewHandle {
3761 self.any_handle
3762 }
3763
3764 pub fn window_id(&self) -> usize {
3765 self.window_id
3766 }
3767
3768 pub fn id(&self) -> usize {
3769 self.view_id
3770 }
3771
3772 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
3773 cx.read_view(self)
3774 }
3775
3776 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
3777 where
3778 C: BorrowWindowContext,
3779 F: FnOnce(&T, &ViewContext<T>) -> S,
3780 {
3781 cx.read_with(self.window_id, |cx| {
3782 let cx = ViewContext::immutable(cx, self.view_id);
3783 read(cx.read_view(self), &cx)
3784 })
3785 }
3786
3787 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
3788 where
3789 C: BorrowWindowContext,
3790 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
3791 {
3792 let mut update = Some(update);
3793
3794 cx.update(self.window_id, |cx| {
3795 cx.update_view(self, &mut |view, cx| {
3796 let update = update.take().unwrap();
3797 update(view, cx)
3798 })
3799 })
3800 }
3801
3802 pub fn is_focused(&self, cx: &WindowContext) -> bool {
3803 cx.focused_view_id() == Some(self.view_id)
3804 }
3805}
3806
3807impl<T: View> Clone for ViewHandle<T> {
3808 fn clone(&self) -> Self {
3809 ViewHandle::new(self.window_id, self.view_id, &self.ref_counts)
3810 }
3811}
3812
3813impl<T> PartialEq for ViewHandle<T> {
3814 fn eq(&self, other: &Self) -> bool {
3815 self.window_id == other.window_id && self.view_id == other.view_id
3816 }
3817}
3818
3819impl<T> PartialEq<WeakViewHandle<T>> for ViewHandle<T> {
3820 fn eq(&self, other: &WeakViewHandle<T>) -> bool {
3821 self.window_id == other.window_id && self.view_id == other.view_id
3822 }
3823}
3824
3825impl<T> PartialEq<ViewHandle<T>> for WeakViewHandle<T> {
3826 fn eq(&self, other: &ViewHandle<T>) -> bool {
3827 self.window_id == other.window_id && self.view_id == other.view_id
3828 }
3829}
3830
3831impl<T> Eq for ViewHandle<T> {}
3832
3833impl<T> Hash for ViewHandle<T> {
3834 fn hash<H: Hasher>(&self, state: &mut H) {
3835 self.window_id.hash(state);
3836 self.view_id.hash(state);
3837 }
3838}
3839
3840impl<T> Debug for ViewHandle<T> {
3841 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3842 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
3843 .field("window_id", &self.window_id)
3844 .field("view_id", &self.view_id)
3845 .finish()
3846 }
3847}
3848
3849impl<T: View> Handle<T> for ViewHandle<T> {
3850 type Weak = WeakViewHandle<T>;
3851
3852 fn id(&self) -> usize {
3853 self.view_id
3854 }
3855
3856 fn location(&self) -> EntityLocation {
3857 EntityLocation::View(self.window_id, self.view_id)
3858 }
3859
3860 fn downgrade(&self) -> Self::Weak {
3861 self.downgrade()
3862 }
3863
3864 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
3865 where
3866 Self: Sized,
3867 {
3868 weak.upgrade(cx)
3869 }
3870}
3871
3872pub struct AnyViewHandle {
3873 window_id: usize,
3874 view_id: usize,
3875 view_type: TypeId,
3876 ref_counts: Arc<Mutex<RefCounts>>,
3877
3878 #[cfg(any(test, feature = "test-support"))]
3879 handle_id: usize,
3880}
3881
3882impl AnyViewHandle {
3883 fn new(
3884 window_id: usize,
3885 view_id: usize,
3886 view_type: TypeId,
3887 ref_counts: Arc<Mutex<RefCounts>>,
3888 ) -> Self {
3889 ref_counts.lock().inc_view(window_id, view_id);
3890
3891 #[cfg(any(test, feature = "test-support"))]
3892 let handle_id = ref_counts
3893 .lock()
3894 .leak_detector
3895 .lock()
3896 .handle_created(None, view_id);
3897
3898 Self {
3899 window_id,
3900 view_id,
3901 view_type,
3902 ref_counts,
3903 #[cfg(any(test, feature = "test-support"))]
3904 handle_id,
3905 }
3906 }
3907
3908 pub fn window_id(&self) -> usize {
3909 self.window_id
3910 }
3911
3912 pub fn id(&self) -> usize {
3913 self.view_id
3914 }
3915
3916 pub fn is<T: 'static>(&self) -> bool {
3917 TypeId::of::<T>() == self.view_type
3918 }
3919
3920 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
3921 if self.is::<T>() {
3922 Some(ViewHandle {
3923 any_handle: self,
3924 view_type: PhantomData,
3925 })
3926 } else {
3927 None
3928 }
3929 }
3930
3931 pub fn downcast_ref<T: View>(&self) -> Option<&ViewHandle<T>> {
3932 if self.is::<T>() {
3933 Some(unsafe { mem::transmute(self) })
3934 } else {
3935 None
3936 }
3937 }
3938
3939 pub fn downgrade(&self) -> AnyWeakViewHandle {
3940 AnyWeakViewHandle {
3941 window_id: self.window_id,
3942 view_id: self.view_id,
3943 view_type: self.view_type,
3944 }
3945 }
3946
3947 pub fn view_type(&self) -> TypeId {
3948 self.view_type
3949 }
3950
3951 pub fn debug_json<'a, 'b>(&self, cx: &'b WindowContext<'a>) -> serde_json::Value {
3952 cx.views
3953 .get(&(self.window_id, self.view_id))
3954 .map_or_else(|| serde_json::Value::Null, |view| view.debug_json(cx))
3955 }
3956}
3957
3958impl Clone for AnyViewHandle {
3959 fn clone(&self) -> Self {
3960 Self::new(
3961 self.window_id,
3962 self.view_id,
3963 self.view_type,
3964 self.ref_counts.clone(),
3965 )
3966 }
3967}
3968
3969impl<T> PartialEq<ViewHandle<T>> for AnyViewHandle {
3970 fn eq(&self, other: &ViewHandle<T>) -> bool {
3971 self.window_id == other.window_id && self.view_id == other.view_id
3972 }
3973}
3974
3975impl Drop for AnyViewHandle {
3976 fn drop(&mut self) {
3977 self.ref_counts
3978 .lock()
3979 .dec_view(self.window_id, self.view_id);
3980 #[cfg(any(test, feature = "test-support"))]
3981 self.ref_counts
3982 .lock()
3983 .leak_detector
3984 .lock()
3985 .handle_dropped(self.view_id, self.handle_id);
3986 }
3987}
3988
3989impl Debug for AnyViewHandle {
3990 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3991 f.debug_struct("AnyViewHandle")
3992 .field("window_id", &self.window_id)
3993 .field("view_id", &self.view_id)
3994 .finish()
3995 }
3996}
3997
3998pub struct AnyModelHandle {
3999 model_id: usize,
4000 model_type: TypeId,
4001 ref_counts: Arc<Mutex<RefCounts>>,
4002
4003 #[cfg(any(test, feature = "test-support"))]
4004 handle_id: usize,
4005}
4006
4007impl AnyModelHandle {
4008 fn new(model_id: usize, model_type: TypeId, ref_counts: Arc<Mutex<RefCounts>>) -> Self {
4009 ref_counts.lock().inc_model(model_id);
4010
4011 #[cfg(any(test, feature = "test-support"))]
4012 let handle_id = ref_counts
4013 .lock()
4014 .leak_detector
4015 .lock()
4016 .handle_created(None, model_id);
4017
4018 Self {
4019 model_id,
4020 model_type,
4021 ref_counts,
4022
4023 #[cfg(any(test, feature = "test-support"))]
4024 handle_id,
4025 }
4026 }
4027
4028 pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> {
4029 if self.is::<T>() {
4030 Some(ModelHandle {
4031 any_handle: self,
4032 model_type: PhantomData,
4033 })
4034 } else {
4035 None
4036 }
4037 }
4038
4039 pub fn downgrade(&self) -> AnyWeakModelHandle {
4040 AnyWeakModelHandle {
4041 model_id: self.model_id,
4042 model_type: self.model_type,
4043 }
4044 }
4045
4046 pub fn is<T: Entity>(&self) -> bool {
4047 self.model_type == TypeId::of::<T>()
4048 }
4049
4050 pub fn model_type(&self) -> TypeId {
4051 self.model_type
4052 }
4053}
4054
4055impl Clone for AnyModelHandle {
4056 fn clone(&self) -> Self {
4057 Self::new(self.model_id, self.model_type, self.ref_counts.clone())
4058 }
4059}
4060
4061impl Drop for AnyModelHandle {
4062 fn drop(&mut self) {
4063 let mut ref_counts = self.ref_counts.lock();
4064 ref_counts.dec_model(self.model_id);
4065
4066 #[cfg(any(test, feature = "test-support"))]
4067 ref_counts
4068 .leak_detector
4069 .lock()
4070 .handle_dropped(self.model_id, self.handle_id);
4071 }
4072}
4073
4074#[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)]
4075pub struct AnyWeakModelHandle {
4076 model_id: usize,
4077 model_type: TypeId,
4078}
4079
4080impl AnyWeakModelHandle {
4081 pub fn upgrade(&self, cx: &impl BorrowAppContext) -> Option<AnyModelHandle> {
4082 cx.read_with(|cx| cx.upgrade_any_model_handle(self))
4083 }
4084
4085 pub fn model_type(&self) -> TypeId {
4086 self.model_type
4087 }
4088
4089 fn is<T: 'static>(&self) -> bool {
4090 TypeId::of::<T>() == self.model_type
4091 }
4092
4093 pub fn downcast<T: Entity>(self) -> Option<WeakModelHandle<T>> {
4094 if self.is::<T>() {
4095 let result = Some(WeakModelHandle {
4096 any_handle: self,
4097 model_type: PhantomData,
4098 });
4099
4100 result
4101 } else {
4102 None
4103 }
4104 }
4105}
4106
4107#[derive(Copy)]
4108pub struct WeakViewHandle<T> {
4109 any_handle: AnyWeakViewHandle,
4110 view_type: PhantomData<T>,
4111}
4112
4113impl<T> Debug for WeakViewHandle<T> {
4114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4115 f.debug_struct(&format!("WeakViewHandle<{}>", type_name::<T>()))
4116 .field("any_handle", &self.any_handle)
4117 .finish()
4118 }
4119}
4120
4121impl<T> WeakHandle for WeakViewHandle<T> {
4122 fn id(&self) -> usize {
4123 self.view_id
4124 }
4125}
4126
4127impl<V: View> WeakViewHandle<V> {
4128 fn new(window_id: usize, view_id: usize) -> Self {
4129 Self {
4130 any_handle: AnyWeakViewHandle {
4131 window_id,
4132 view_id,
4133 view_type: TypeId::of::<V>(),
4134 },
4135 view_type: PhantomData,
4136 }
4137 }
4138
4139 pub fn id(&self) -> usize {
4140 self.view_id
4141 }
4142
4143 pub fn window_id(&self) -> usize {
4144 self.window_id
4145 }
4146
4147 pub fn into_any(self) -> AnyWeakViewHandle {
4148 self.any_handle
4149 }
4150
4151 pub fn upgrade(&self, cx: &impl BorrowAppContext) -> Option<ViewHandle<V>> {
4152 cx.read_with(|cx| cx.upgrade_view_handle(self))
4153 }
4154
4155 pub fn read_with<T>(
4156 &self,
4157 cx: &AsyncAppContext,
4158 read: impl FnOnce(&V, &ViewContext<V>) -> T,
4159 ) -> Result<T> {
4160 cx.read(|cx| {
4161 let handle = cx
4162 .upgrade_view_handle(self)
4163 .ok_or_else(|| anyhow!("view {} was dropped", V::ui_name()))?;
4164 cx.read_window(self.window_id, |cx| handle.read_with(cx, read))
4165 .ok_or_else(|| anyhow!("window was removed"))
4166 })
4167 }
4168
4169 pub fn update<T>(
4170 &self,
4171 cx: &mut AsyncAppContext,
4172 update: impl FnOnce(&mut V, &mut ViewContext<V>) -> T,
4173 ) -> Result<T> {
4174 cx.update(|cx| {
4175 let handle = cx
4176 .upgrade_view_handle(self)
4177 .ok_or_else(|| anyhow!("view {} was dropped", V::ui_name()))?;
4178 cx.update_window(self.window_id, |cx| handle.update(cx, update))
4179 .ok_or_else(|| anyhow!("window was removed"))
4180 })
4181 }
4182}
4183
4184impl<T> Deref for WeakViewHandle<T> {
4185 type Target = AnyWeakViewHandle;
4186
4187 fn deref(&self) -> &Self::Target {
4188 &self.any_handle
4189 }
4190}
4191
4192impl<T> Clone for WeakViewHandle<T> {
4193 fn clone(&self) -> Self {
4194 Self {
4195 any_handle: self.any_handle.clone(),
4196 view_type: PhantomData,
4197 }
4198 }
4199}
4200
4201impl<T> PartialEq for WeakViewHandle<T> {
4202 fn eq(&self, other: &Self) -> bool {
4203 self.window_id == other.window_id && self.view_id == other.view_id
4204 }
4205}
4206
4207impl<T> Eq for WeakViewHandle<T> {}
4208
4209impl<T> Hash for WeakViewHandle<T> {
4210 fn hash<H: Hasher>(&self, state: &mut H) {
4211 self.any_handle.hash(state);
4212 }
4213}
4214
4215#[derive(Debug, Clone, Copy)]
4216pub struct AnyWeakViewHandle {
4217 window_id: usize,
4218 view_id: usize,
4219 view_type: TypeId,
4220}
4221
4222impl AnyWeakViewHandle {
4223 pub fn id(&self) -> usize {
4224 self.view_id
4225 }
4226
4227 fn is<T: 'static>(&self) -> bool {
4228 TypeId::of::<T>() == self.view_type
4229 }
4230
4231 pub fn upgrade(&self, cx: &impl BorrowAppContext) -> Option<AnyViewHandle> {
4232 cx.read_with(|cx| cx.upgrade_any_view_handle(self))
4233 }
4234
4235 pub fn downcast<T: View>(self) -> Option<WeakViewHandle<T>> {
4236 if self.is::<T>() {
4237 Some(WeakViewHandle {
4238 any_handle: self,
4239 view_type: PhantomData,
4240 })
4241 } else {
4242 None
4243 }
4244 }
4245}
4246
4247impl Hash for AnyWeakViewHandle {
4248 fn hash<H: Hasher>(&self, state: &mut H) {
4249 self.window_id.hash(state);
4250 self.view_id.hash(state);
4251 self.view_type.hash(state);
4252 }
4253}
4254
4255#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4256pub struct ElementStateId {
4257 view_id: usize,
4258 element_id: usize,
4259 tag: TypeId,
4260}
4261
4262pub struct ElementStateHandle<T> {
4263 value_type: PhantomData<T>,
4264 id: ElementStateId,
4265 ref_counts: Weak<Mutex<RefCounts>>,
4266}
4267
4268impl<T: 'static> ElementStateHandle<T> {
4269 fn new(id: ElementStateId, frame_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4270 ref_counts.lock().inc_element_state(id, frame_id);
4271 Self {
4272 value_type: PhantomData,
4273 id,
4274 ref_counts: Arc::downgrade(ref_counts),
4275 }
4276 }
4277
4278 pub fn id(&self) -> ElementStateId {
4279 self.id
4280 }
4281
4282 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
4283 cx.element_states
4284 .get(&self.id)
4285 .unwrap()
4286 .downcast_ref()
4287 .unwrap()
4288 }
4289
4290 pub fn update<C, D, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R
4291 where
4292 C: DerefMut<Target = D>,
4293 D: DerefMut<Target = AppContext>,
4294 {
4295 let mut element_state = cx.deref_mut().element_states.remove(&self.id).unwrap();
4296 let result = f(element_state.downcast_mut().unwrap(), cx);
4297 cx.deref_mut().element_states.insert(self.id, element_state);
4298 result
4299 }
4300}
4301
4302impl<T> Drop for ElementStateHandle<T> {
4303 fn drop(&mut self) {
4304 if let Some(ref_counts) = self.ref_counts.upgrade() {
4305 ref_counts.lock().dec_element_state(self.id);
4306 }
4307 }
4308}
4309
4310#[must_use]
4311pub enum Subscription {
4312 Subscription(callback_collection::Subscription<usize, SubscriptionCallback>),
4313 Observation(callback_collection::Subscription<usize, ObservationCallback>),
4314 GlobalSubscription(callback_collection::Subscription<TypeId, GlobalSubscriptionCallback>),
4315 GlobalObservation(callback_collection::Subscription<TypeId, GlobalObservationCallback>),
4316 FocusObservation(callback_collection::Subscription<usize, FocusObservationCallback>),
4317 WindowActivationObservation(callback_collection::Subscription<usize, WindowActivationCallback>),
4318 WindowFullscreenObservation(callback_collection::Subscription<usize, WindowFullscreenCallback>),
4319 WindowBoundsObservation(callback_collection::Subscription<usize, WindowBoundsCallback>),
4320 KeystrokeObservation(callback_collection::Subscription<usize, KeystrokeCallback>),
4321 ReleaseObservation(callback_collection::Subscription<usize, ReleaseObservationCallback>),
4322 ActionObservation(callback_collection::Subscription<(), ActionObservationCallback>),
4323 ActiveLabeledTasksObservation(
4324 callback_collection::Subscription<(), ActiveLabeledTasksCallback>,
4325 ),
4326}
4327
4328impl Subscription {
4329 pub fn id(&self) -> usize {
4330 match self {
4331 Subscription::Subscription(subscription) => subscription.id(),
4332 Subscription::Observation(subscription) => subscription.id(),
4333 Subscription::GlobalSubscription(subscription) => subscription.id(),
4334 Subscription::GlobalObservation(subscription) => subscription.id(),
4335 Subscription::FocusObservation(subscription) => subscription.id(),
4336 Subscription::WindowActivationObservation(subscription) => subscription.id(),
4337 Subscription::WindowFullscreenObservation(subscription) => subscription.id(),
4338 Subscription::WindowBoundsObservation(subscription) => subscription.id(),
4339 Subscription::KeystrokeObservation(subscription) => subscription.id(),
4340 Subscription::ReleaseObservation(subscription) => subscription.id(),
4341 Subscription::ActionObservation(subscription) => subscription.id(),
4342 Subscription::ActiveLabeledTasksObservation(subscription) => subscription.id(),
4343 }
4344 }
4345
4346 pub fn detach(&mut self) {
4347 match self {
4348 Subscription::Subscription(subscription) => subscription.detach(),
4349 Subscription::GlobalSubscription(subscription) => subscription.detach(),
4350 Subscription::Observation(subscription) => subscription.detach(),
4351 Subscription::GlobalObservation(subscription) => subscription.detach(),
4352 Subscription::FocusObservation(subscription) => subscription.detach(),
4353 Subscription::KeystrokeObservation(subscription) => subscription.detach(),
4354 Subscription::WindowActivationObservation(subscription) => subscription.detach(),
4355 Subscription::WindowFullscreenObservation(subscription) => subscription.detach(),
4356 Subscription::WindowBoundsObservation(subscription) => subscription.detach(),
4357 Subscription::ReleaseObservation(subscription) => subscription.detach(),
4358 Subscription::ActionObservation(subscription) => subscription.detach(),
4359 Subscription::ActiveLabeledTasksObservation(subscription) => subscription.detach(),
4360 }
4361 }
4362}
4363
4364#[cfg(test)]
4365mod tests {
4366 use super::*;
4367 use crate::{
4368 actions,
4369 elements::*,
4370 impl_actions,
4371 platform::{MouseButton, MouseButtonEvent},
4372 window::ChildView,
4373 };
4374 use itertools::Itertools;
4375 use postage::{sink::Sink, stream::Stream};
4376 use serde::Deserialize;
4377 use smol::future::poll_once;
4378 use std::{
4379 cell::Cell,
4380 sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
4381 };
4382
4383 #[crate::test(self)]
4384 fn test_model_handles(cx: &mut AppContext) {
4385 struct Model {
4386 other: Option<ModelHandle<Model>>,
4387 events: Vec<String>,
4388 }
4389
4390 impl Entity for Model {
4391 type Event = usize;
4392 }
4393
4394 impl Model {
4395 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
4396 if let Some(other) = other.as_ref() {
4397 cx.observe(other, |me, _, _| {
4398 me.events.push("notified".into());
4399 })
4400 .detach();
4401 cx.subscribe(other, |me, _, event, _| {
4402 me.events.push(format!("observed event {}", event));
4403 })
4404 .detach();
4405 }
4406
4407 Self {
4408 other,
4409 events: Vec::new(),
4410 }
4411 }
4412 }
4413
4414 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
4415 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
4416 assert_eq!(cx.models.len(), 2);
4417
4418 handle_1.update(cx, |model, cx| {
4419 model.events.push("updated".into());
4420 cx.emit(1);
4421 cx.notify();
4422 cx.emit(2);
4423 });
4424 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
4425 assert_eq!(
4426 handle_2.read(cx).events,
4427 vec![
4428 "observed event 1".to_string(),
4429 "notified".to_string(),
4430 "observed event 2".to_string(),
4431 ]
4432 );
4433
4434 handle_2.update(cx, |model, _| {
4435 drop(handle_1);
4436 model.other.take();
4437 });
4438
4439 assert_eq!(cx.models.len(), 1);
4440 assert!(cx.subscriptions.is_empty());
4441 assert!(cx.observations.is_empty());
4442 }
4443
4444 #[crate::test(self)]
4445 fn test_model_events(cx: &mut AppContext) {
4446 #[derive(Default)]
4447 struct Model {
4448 events: Vec<usize>,
4449 }
4450
4451 impl Entity for Model {
4452 type Event = usize;
4453 }
4454
4455 let handle_1 = cx.add_model(|_| Model::default());
4456 let handle_2 = cx.add_model(|_| Model::default());
4457
4458 handle_1.update(cx, |_, cx| {
4459 cx.subscribe(&handle_2, move |model: &mut Model, emitter, event, cx| {
4460 model.events.push(*event);
4461
4462 cx.subscribe(&emitter, |model, _, event, _| {
4463 model.events.push(*event * 2);
4464 })
4465 .detach();
4466 })
4467 .detach();
4468 });
4469
4470 handle_2.update(cx, |_, c| c.emit(7));
4471 assert_eq!(handle_1.read(cx).events, vec![7]);
4472
4473 handle_2.update(cx, |_, c| c.emit(5));
4474 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
4475 }
4476
4477 #[crate::test(self)]
4478 fn test_model_emit_before_subscribe_in_same_update_cycle(cx: &mut AppContext) {
4479 #[derive(Default)]
4480 struct Model;
4481
4482 impl Entity for Model {
4483 type Event = ();
4484 }
4485
4486 let events = Rc::new(RefCell::new(Vec::new()));
4487 cx.add_model(|cx| {
4488 drop(cx.subscribe(&cx.handle(), {
4489 let events = events.clone();
4490 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
4491 }));
4492 cx.subscribe(&cx.handle(), {
4493 let events = events.clone();
4494 move |_, _, _, _| events.borrow_mut().push("before emit")
4495 })
4496 .detach();
4497 cx.emit(());
4498 cx.subscribe(&cx.handle(), {
4499 let events = events.clone();
4500 move |_, _, _, _| events.borrow_mut().push("after emit")
4501 })
4502 .detach();
4503 Model
4504 });
4505 assert_eq!(*events.borrow(), ["before emit"]);
4506 }
4507
4508 #[crate::test(self)]
4509 fn test_observe_and_notify_from_model(cx: &mut AppContext) {
4510 #[derive(Default)]
4511 struct Model {
4512 count: usize,
4513 events: Vec<usize>,
4514 }
4515
4516 impl Entity for Model {
4517 type Event = ();
4518 }
4519
4520 let handle_1 = cx.add_model(|_| Model::default());
4521 let handle_2 = cx.add_model(|_| Model::default());
4522
4523 handle_1.update(cx, |_, c| {
4524 c.observe(&handle_2, move |model, observed, c| {
4525 model.events.push(observed.read(c).count);
4526 c.observe(&observed, |model, observed, c| {
4527 model.events.push(observed.read(c).count * 2);
4528 })
4529 .detach();
4530 })
4531 .detach();
4532 });
4533
4534 handle_2.update(cx, |model, c| {
4535 model.count = 7;
4536 c.notify()
4537 });
4538 assert_eq!(handle_1.read(cx).events, vec![7]);
4539
4540 handle_2.update(cx, |model, c| {
4541 model.count = 5;
4542 c.notify()
4543 });
4544 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10])
4545 }
4546
4547 #[crate::test(self)]
4548 fn test_model_notify_before_observe_in_same_update_cycle(cx: &mut AppContext) {
4549 #[derive(Default)]
4550 struct Model;
4551
4552 impl Entity for Model {
4553 type Event = ();
4554 }
4555
4556 let events = Rc::new(RefCell::new(Vec::new()));
4557 cx.add_model(|cx| {
4558 drop(cx.observe(&cx.handle(), {
4559 let events = events.clone();
4560 move |_, _, _| events.borrow_mut().push("dropped before flush")
4561 }));
4562 cx.observe(&cx.handle(), {
4563 let events = events.clone();
4564 move |_, _, _| events.borrow_mut().push("before notify")
4565 })
4566 .detach();
4567 cx.notify();
4568 cx.observe(&cx.handle(), {
4569 let events = events.clone();
4570 move |_, _, _| events.borrow_mut().push("after notify")
4571 })
4572 .detach();
4573 Model
4574 });
4575 assert_eq!(*events.borrow(), ["before notify"]);
4576 }
4577
4578 #[crate::test(self)]
4579 fn test_defer_and_after_window_update(cx: &mut TestAppContext) {
4580 struct View {
4581 render_count: usize,
4582 }
4583
4584 impl Entity for View {
4585 type Event = usize;
4586 }
4587
4588 impl super::View for View {
4589 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
4590 post_inc(&mut self.render_count);
4591 Empty::new().into_any()
4592 }
4593
4594 fn ui_name() -> &'static str {
4595 "View"
4596 }
4597 }
4598
4599 let (_, view) = cx.add_window(|_| View { render_count: 0 });
4600 let called_defer = Rc::new(AtomicBool::new(false));
4601 let called_after_window_update = Rc::new(AtomicBool::new(false));
4602
4603 view.update(cx, |this, cx| {
4604 assert_eq!(this.render_count, 1);
4605 cx.defer({
4606 let called_defer = called_defer.clone();
4607 move |this, _| {
4608 assert_eq!(this.render_count, 1);
4609 called_defer.store(true, SeqCst);
4610 }
4611 });
4612 cx.after_window_update({
4613 let called_after_window_update = called_after_window_update.clone();
4614 move |this, cx| {
4615 assert_eq!(this.render_count, 2);
4616 called_after_window_update.store(true, SeqCst);
4617 cx.notify();
4618 }
4619 });
4620 assert!(!called_defer.load(SeqCst));
4621 assert!(!called_after_window_update.load(SeqCst));
4622 cx.notify();
4623 });
4624
4625 assert!(called_defer.load(SeqCst));
4626 assert!(called_after_window_update.load(SeqCst));
4627 assert_eq!(view.read_with(cx, |view, _| view.render_count), 3);
4628 }
4629
4630 #[crate::test(self)]
4631 fn test_view_handles(cx: &mut TestAppContext) {
4632 struct View {
4633 other: Option<ViewHandle<View>>,
4634 events: Vec<String>,
4635 }
4636
4637 impl Entity for View {
4638 type Event = usize;
4639 }
4640
4641 impl super::View for View {
4642 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
4643 Empty::new().into_any()
4644 }
4645
4646 fn ui_name() -> &'static str {
4647 "View"
4648 }
4649 }
4650
4651 impl View {
4652 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
4653 if let Some(other) = other.as_ref() {
4654 cx.subscribe(other, |me, _, event, _| {
4655 me.events.push(format!("observed event {}", event));
4656 })
4657 .detach();
4658 }
4659 Self {
4660 other,
4661 events: Vec::new(),
4662 }
4663 }
4664 }
4665
4666 let (window_id, _root_view) = cx.add_window(|cx| View::new(None, cx));
4667 let handle_1 = cx.add_view(window_id, |cx| View::new(None, cx));
4668 let handle_2 = cx.add_view(window_id, |cx| View::new(Some(handle_1.clone()), cx));
4669 assert_eq!(cx.read(|cx| cx.views.len()), 3);
4670
4671 handle_1.update(cx, |view, cx| {
4672 view.events.push("updated".into());
4673 cx.emit(1);
4674 cx.emit(2);
4675 });
4676 handle_1.read_with(cx, |view, _| {
4677 assert_eq!(view.events, vec!["updated".to_string()]);
4678 });
4679 handle_2.read_with(cx, |view, _| {
4680 assert_eq!(
4681 view.events,
4682 vec![
4683 "observed event 1".to_string(),
4684 "observed event 2".to_string(),
4685 ]
4686 );
4687 });
4688
4689 handle_2.update(cx, |view, _| {
4690 drop(handle_1);
4691 view.other.take();
4692 });
4693
4694 cx.read(|cx| {
4695 assert_eq!(cx.views.len(), 2);
4696 assert!(cx.subscriptions.is_empty());
4697 assert!(cx.observations.is_empty());
4698 });
4699 }
4700
4701 #[crate::test(self)]
4702 fn test_add_window(cx: &mut AppContext) {
4703 struct View {
4704 mouse_down_count: Arc<AtomicUsize>,
4705 }
4706
4707 impl Entity for View {
4708 type Event = ();
4709 }
4710
4711 impl super::View for View {
4712 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
4713 enum Handler {}
4714 let mouse_down_count = self.mouse_down_count.clone();
4715 MouseEventHandler::<Handler, _>::new(0, cx, |_, _| Empty::new())
4716 .on_down(MouseButton::Left, move |_, _, _| {
4717 mouse_down_count.fetch_add(1, SeqCst);
4718 })
4719 .into_any()
4720 }
4721
4722 fn ui_name() -> &'static str {
4723 "View"
4724 }
4725 }
4726
4727 let mouse_down_count = Arc::new(AtomicUsize::new(0));
4728 let (window_id, _) = cx.add_window(Default::default(), |_| View {
4729 mouse_down_count: mouse_down_count.clone(),
4730 });
4731
4732 cx.update_window(window_id, |cx| {
4733 // Ensure window's root element is in a valid lifecycle state.
4734 cx.dispatch_event(
4735 Event::MouseDown(MouseButtonEvent {
4736 position: Default::default(),
4737 button: MouseButton::Left,
4738 modifiers: Default::default(),
4739 click_count: 1,
4740 }),
4741 false,
4742 );
4743 assert_eq!(mouse_down_count.load(SeqCst), 1);
4744 });
4745 }
4746
4747 #[crate::test(self)]
4748 fn test_entity_release_hooks(cx: &mut AppContext) {
4749 struct Model {
4750 released: Rc<Cell<bool>>,
4751 }
4752
4753 struct View {
4754 released: Rc<Cell<bool>>,
4755 }
4756
4757 impl Entity for Model {
4758 type Event = ();
4759
4760 fn release(&mut self, _: &mut AppContext) {
4761 self.released.set(true);
4762 }
4763 }
4764
4765 impl Entity for View {
4766 type Event = ();
4767
4768 fn release(&mut self, _: &mut AppContext) {
4769 self.released.set(true);
4770 }
4771 }
4772
4773 impl super::View for View {
4774 fn ui_name() -> &'static str {
4775 "View"
4776 }
4777
4778 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
4779 Empty::new().into_any()
4780 }
4781 }
4782
4783 let model_released = Rc::new(Cell::new(false));
4784 let model_release_observed = Rc::new(Cell::new(false));
4785 let view_released = Rc::new(Cell::new(false));
4786 let view_release_observed = Rc::new(Cell::new(false));
4787
4788 let model = cx.add_model(|_| Model {
4789 released: model_released.clone(),
4790 });
4791 let (window_id, view) = cx.add_window(Default::default(), |_| View {
4792 released: view_released.clone(),
4793 });
4794 assert!(!model_released.get());
4795 assert!(!view_released.get());
4796
4797 cx.observe_release(&model, {
4798 let model_release_observed = model_release_observed.clone();
4799 move |_, _| model_release_observed.set(true)
4800 })
4801 .detach();
4802 cx.observe_release(&view, {
4803 let view_release_observed = view_release_observed.clone();
4804 move |_, _| view_release_observed.set(true)
4805 })
4806 .detach();
4807
4808 cx.update(move |_| {
4809 drop(model);
4810 });
4811 assert!(model_released.get());
4812 assert!(model_release_observed.get());
4813
4814 drop(view);
4815 cx.update_window(window_id, |cx| cx.remove_window());
4816 assert!(view_released.get());
4817 assert!(view_release_observed.get());
4818 }
4819
4820 #[crate::test(self)]
4821 fn test_view_events(cx: &mut TestAppContext) {
4822 struct Model;
4823
4824 impl Entity for Model {
4825 type Event = String;
4826 }
4827
4828 let (window_id, handle_1) = cx.add_window(|_| TestView::default());
4829 let handle_2 = cx.add_view(window_id, |_| TestView::default());
4830 let handle_3 = cx.add_model(|_| Model);
4831
4832 handle_1.update(cx, |_, cx| {
4833 cx.subscribe(&handle_2, move |me, emitter, event, cx| {
4834 me.events.push(event.clone());
4835
4836 cx.subscribe(&emitter, |me, _, event, _| {
4837 me.events.push(format!("{event} from inner"));
4838 })
4839 .detach();
4840 })
4841 .detach();
4842
4843 cx.subscribe(&handle_3, |me, _, event, _| {
4844 me.events.push(event.clone());
4845 })
4846 .detach();
4847 });
4848
4849 handle_2.update(cx, |_, c| c.emit("7".into()));
4850 handle_1.read_with(cx, |view, _| assert_eq!(view.events, ["7"]));
4851
4852 handle_2.update(cx, |_, c| c.emit("5".into()));
4853 handle_1.read_with(cx, |view, _| {
4854 assert_eq!(view.events, ["7", "5", "5 from inner"])
4855 });
4856
4857 handle_3.update(cx, |_, c| c.emit("9".into()));
4858 handle_1.read_with(cx, |view, _| {
4859 assert_eq!(view.events, ["7", "5", "5 from inner", "9"])
4860 });
4861 }
4862
4863 #[crate::test(self)]
4864 fn test_global_events(cx: &mut AppContext) {
4865 #[derive(Clone, Debug, Eq, PartialEq)]
4866 struct GlobalEvent(u64);
4867
4868 let events = Rc::new(RefCell::new(Vec::new()));
4869 let first_subscription;
4870 let second_subscription;
4871
4872 {
4873 let events = events.clone();
4874 first_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
4875 events.borrow_mut().push(("First", e.clone()));
4876 });
4877 }
4878
4879 {
4880 let events = events.clone();
4881 second_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
4882 events.borrow_mut().push(("Second", e.clone()));
4883 });
4884 }
4885
4886 cx.update(|cx| {
4887 cx.emit_global(GlobalEvent(1));
4888 cx.emit_global(GlobalEvent(2));
4889 });
4890
4891 drop(first_subscription);
4892
4893 cx.update(|cx| {
4894 cx.emit_global(GlobalEvent(3));
4895 });
4896
4897 drop(second_subscription);
4898
4899 cx.update(|cx| {
4900 cx.emit_global(GlobalEvent(4));
4901 });
4902
4903 assert_eq!(
4904 &*events.borrow(),
4905 &[
4906 ("First", GlobalEvent(1)),
4907 ("Second", GlobalEvent(1)),
4908 ("First", GlobalEvent(2)),
4909 ("Second", GlobalEvent(2)),
4910 ("Second", GlobalEvent(3)),
4911 ]
4912 );
4913 }
4914
4915 #[crate::test(self)]
4916 fn test_global_events_emitted_before_subscription_in_same_update_cycle(cx: &mut AppContext) {
4917 let events = Rc::new(RefCell::new(Vec::new()));
4918 cx.update(|cx| {
4919 {
4920 let events = events.clone();
4921 drop(cx.subscribe_global(move |_: &(), _| {
4922 events.borrow_mut().push("dropped before emit");
4923 }));
4924 }
4925
4926 {
4927 let events = events.clone();
4928 cx.subscribe_global(move |_: &(), _| {
4929 events.borrow_mut().push("before emit");
4930 })
4931 .detach();
4932 }
4933
4934 cx.emit_global(());
4935
4936 {
4937 let events = events.clone();
4938 cx.subscribe_global(move |_: &(), _| {
4939 events.borrow_mut().push("after emit");
4940 })
4941 .detach();
4942 }
4943 });
4944
4945 assert_eq!(*events.borrow(), ["before emit"]);
4946 }
4947
4948 #[crate::test(self)]
4949 fn test_global_nested_events(cx: &mut AppContext) {
4950 #[derive(Clone, Debug, Eq, PartialEq)]
4951 struct GlobalEvent(u64);
4952
4953 let events = Rc::new(RefCell::new(Vec::new()));
4954
4955 {
4956 let events = events.clone();
4957 cx.subscribe_global(move |e: &GlobalEvent, cx| {
4958 events.borrow_mut().push(("Outer", e.clone()));
4959
4960 if e.0 == 1 {
4961 let events = events.clone();
4962 cx.subscribe_global(move |e: &GlobalEvent, _| {
4963 events.borrow_mut().push(("Inner", e.clone()));
4964 })
4965 .detach();
4966 }
4967 })
4968 .detach();
4969 }
4970
4971 cx.update(|cx| {
4972 cx.emit_global(GlobalEvent(1));
4973 cx.emit_global(GlobalEvent(2));
4974 cx.emit_global(GlobalEvent(3));
4975 });
4976 cx.update(|cx| {
4977 cx.emit_global(GlobalEvent(4));
4978 });
4979
4980 assert_eq!(
4981 &*events.borrow(),
4982 &[
4983 ("Outer", GlobalEvent(1)),
4984 ("Outer", GlobalEvent(2)),
4985 ("Outer", GlobalEvent(3)),
4986 ("Outer", GlobalEvent(4)),
4987 ("Inner", GlobalEvent(4)),
4988 ]
4989 );
4990 }
4991
4992 #[crate::test(self)]
4993 fn test_global(cx: &mut AppContext) {
4994 type Global = usize;
4995
4996 let observation_count = Rc::new(RefCell::new(0));
4997 let subscription = cx.observe_global::<Global, _>({
4998 let observation_count = observation_count.clone();
4999 move |_| {
5000 *observation_count.borrow_mut() += 1;
5001 }
5002 });
5003
5004 assert!(!cx.has_global::<Global>());
5005 assert_eq!(cx.default_global::<Global>(), &0);
5006 assert_eq!(*observation_count.borrow(), 1);
5007 assert!(cx.has_global::<Global>());
5008 assert_eq!(
5009 cx.update_global::<Global, _, _>(|global, _| {
5010 *global = 1;
5011 "Update Result"
5012 }),
5013 "Update Result"
5014 );
5015 assert_eq!(*observation_count.borrow(), 2);
5016 assert_eq!(cx.global::<Global>(), &1);
5017
5018 drop(subscription);
5019 cx.update_global::<Global, _, _>(|global, _| {
5020 *global = 2;
5021 });
5022 assert_eq!(*observation_count.borrow(), 2);
5023
5024 type OtherGlobal = f32;
5025
5026 let observation_count = Rc::new(RefCell::new(0));
5027 cx.observe_global::<OtherGlobal, _>({
5028 let observation_count = observation_count.clone();
5029 move |_| {
5030 *observation_count.borrow_mut() += 1;
5031 }
5032 })
5033 .detach();
5034
5035 assert_eq!(
5036 cx.update_default_global::<OtherGlobal, _, _>(|global, _| {
5037 assert_eq!(global, &0.0);
5038 *global = 2.0;
5039 "Default update result"
5040 }),
5041 "Default update result"
5042 );
5043 assert_eq!(cx.global::<OtherGlobal>(), &2.0);
5044 assert_eq!(*observation_count.borrow(), 1);
5045 }
5046
5047 #[crate::test(self)]
5048 fn test_dropping_subscribers(cx: &mut TestAppContext) {
5049 struct Model;
5050
5051 impl Entity for Model {
5052 type Event = ();
5053 }
5054
5055 let (window_id, _root_view) = cx.add_window(|_| TestView::default());
5056 let observing_view = cx.add_view(window_id, |_| TestView::default());
5057 let emitting_view = cx.add_view(window_id, |_| TestView::default());
5058 let observing_model = cx.add_model(|_| Model);
5059 let observed_model = cx.add_model(|_| Model);
5060
5061 observing_view.update(cx, |_, cx| {
5062 cx.subscribe(&emitting_view, |_, _, _, _| {}).detach();
5063 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
5064 });
5065 observing_model.update(cx, |_, cx| {
5066 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
5067 });
5068
5069 cx.update(|_| {
5070 drop(observing_view);
5071 drop(observing_model);
5072 });
5073
5074 emitting_view.update(cx, |_, cx| cx.emit(Default::default()));
5075 observed_model.update(cx, |_, cx| cx.emit(()));
5076 }
5077
5078 #[crate::test(self)]
5079 fn test_view_emit_before_subscribe_in_same_update_cycle(cx: &mut AppContext) {
5080 let (_, view) = cx.add_window::<TestView, _>(Default::default(), |cx| {
5081 drop(cx.subscribe(&cx.handle(), {
5082 move |this, _, _, _| this.events.push("dropped before flush".into())
5083 }));
5084 cx.subscribe(&cx.handle(), {
5085 move |this, _, _, _| this.events.push("before emit".into())
5086 })
5087 .detach();
5088 cx.emit("the event".into());
5089 cx.subscribe(&cx.handle(), {
5090 move |this, _, _, _| this.events.push("after emit".into())
5091 })
5092 .detach();
5093 TestView { events: Vec::new() }
5094 });
5095
5096 assert_eq!(view.read(cx).events, ["before emit"]);
5097 }
5098
5099 #[crate::test(self)]
5100 fn test_observe_and_notify_from_view(cx: &mut TestAppContext) {
5101 #[derive(Default)]
5102 struct Model {
5103 state: String,
5104 }
5105
5106 impl Entity for Model {
5107 type Event = ();
5108 }
5109
5110 let (_, view) = cx.add_window(|_| TestView::default());
5111 let model = cx.add_model(|_| Model {
5112 state: "old-state".into(),
5113 });
5114
5115 view.update(cx, |_, c| {
5116 c.observe(&model, |me, observed, cx| {
5117 me.events.push(observed.read(cx).state.clone())
5118 })
5119 .detach();
5120 });
5121
5122 model.update(cx, |model, cx| {
5123 model.state = "new-state".into();
5124 cx.notify();
5125 });
5126 view.read_with(cx, |view, _| assert_eq!(view.events, ["new-state"]));
5127 }
5128
5129 #[crate::test(self)]
5130 fn test_view_notify_before_observe_in_same_update_cycle(cx: &mut AppContext) {
5131 let (_, view) = cx.add_window::<TestView, _>(Default::default(), |cx| {
5132 drop(cx.observe(&cx.handle(), {
5133 move |this, _, _| this.events.push("dropped before flush".into())
5134 }));
5135 cx.observe(&cx.handle(), {
5136 move |this, _, _| this.events.push("before notify".into())
5137 })
5138 .detach();
5139 cx.notify();
5140 cx.observe(&cx.handle(), {
5141 move |this, _, _| this.events.push("after notify".into())
5142 })
5143 .detach();
5144 TestView { events: Vec::new() }
5145 });
5146
5147 assert_eq!(view.read(cx).events, ["before notify"]);
5148 }
5149
5150 #[crate::test(self)]
5151 fn test_notify_and_drop_observe_subscription_in_same_update_cycle(cx: &mut TestAppContext) {
5152 struct Model;
5153 impl Entity for Model {
5154 type Event = ();
5155 }
5156
5157 let model = cx.add_model(|_| Model);
5158 let (_, view) = cx.add_window(|_| TestView::default());
5159
5160 view.update(cx, |_, cx| {
5161 model.update(cx, |_, cx| cx.notify());
5162 drop(cx.observe(&model, move |this, _, _| {
5163 this.events.push("model notified".into());
5164 }));
5165 model.update(cx, |_, cx| cx.notify());
5166 });
5167
5168 for _ in 0..3 {
5169 model.update(cx, |_, cx| cx.notify());
5170 }
5171 view.read_with(cx, |view, _| assert_eq!(view.events, Vec::<&str>::new()));
5172 }
5173
5174 #[crate::test(self)]
5175 fn test_dropping_observers(cx: &mut TestAppContext) {
5176 struct Model;
5177
5178 impl Entity for Model {
5179 type Event = ();
5180 }
5181
5182 let (window_id, _root_view) = cx.add_window(|_| TestView::default());
5183 let observing_view = cx.add_view(window_id, |_| TestView::default());
5184 let observing_model = cx.add_model(|_| Model);
5185 let observed_model = cx.add_model(|_| Model);
5186
5187 observing_view.update(cx, |_, cx| {
5188 cx.observe(&observed_model, |_, _, _| {}).detach();
5189 });
5190 observing_model.update(cx, |_, cx| {
5191 cx.observe(&observed_model, |_, _, _| {}).detach();
5192 });
5193
5194 cx.update(|_| {
5195 drop(observing_view);
5196 drop(observing_model);
5197 });
5198
5199 observed_model.update(cx, |_, cx| cx.notify());
5200 }
5201
5202 #[crate::test(self)]
5203 fn test_dropping_subscriptions_during_callback(cx: &mut TestAppContext) {
5204 struct Model;
5205
5206 impl Entity for Model {
5207 type Event = u64;
5208 }
5209
5210 // Events
5211 let observing_model = cx.add_model(|_| Model);
5212 let observed_model = cx.add_model(|_| Model);
5213
5214 let events = Rc::new(RefCell::new(Vec::new()));
5215
5216 observing_model.update(cx, |_, cx| {
5217 let events = events.clone();
5218 let subscription = Rc::new(RefCell::new(None));
5219 *subscription.borrow_mut() = Some(cx.subscribe(&observed_model, {
5220 let subscription = subscription.clone();
5221 move |_, _, e, _| {
5222 subscription.borrow_mut().take();
5223 events.borrow_mut().push(*e);
5224 }
5225 }));
5226 });
5227
5228 observed_model.update(cx, |_, cx| {
5229 cx.emit(1);
5230 cx.emit(2);
5231 });
5232
5233 assert_eq!(*events.borrow(), [1]);
5234
5235 // Global Events
5236 #[derive(Clone, Debug, Eq, PartialEq)]
5237 struct GlobalEvent(u64);
5238
5239 let events = Rc::new(RefCell::new(Vec::new()));
5240
5241 {
5242 let events = events.clone();
5243 let subscription = Rc::new(RefCell::new(None));
5244 *subscription.borrow_mut() = Some(cx.subscribe_global({
5245 let subscription = subscription.clone();
5246 move |e: &GlobalEvent, _| {
5247 subscription.borrow_mut().take();
5248 events.borrow_mut().push(e.clone());
5249 }
5250 }));
5251 }
5252
5253 cx.update(|cx| {
5254 cx.emit_global(GlobalEvent(1));
5255 cx.emit_global(GlobalEvent(2));
5256 });
5257
5258 assert_eq!(*events.borrow(), [GlobalEvent(1)]);
5259
5260 // Model Observation
5261 let observing_model = cx.add_model(|_| Model);
5262 let observed_model = cx.add_model(|_| Model);
5263
5264 let observation_count = Rc::new(RefCell::new(0));
5265
5266 observing_model.update(cx, |_, cx| {
5267 let observation_count = observation_count.clone();
5268 let subscription = Rc::new(RefCell::new(None));
5269 *subscription.borrow_mut() = Some(cx.observe(&observed_model, {
5270 let subscription = subscription.clone();
5271 move |_, _, _| {
5272 subscription.borrow_mut().take();
5273 *observation_count.borrow_mut() += 1;
5274 }
5275 }));
5276 });
5277
5278 observed_model.update(cx, |_, cx| {
5279 cx.notify();
5280 });
5281
5282 observed_model.update(cx, |_, cx| {
5283 cx.notify();
5284 });
5285
5286 assert_eq!(*observation_count.borrow(), 1);
5287
5288 // View Observation
5289 struct View;
5290
5291 impl Entity for View {
5292 type Event = ();
5293 }
5294
5295 impl super::View for View {
5296 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
5297 Empty::new().into_any()
5298 }
5299
5300 fn ui_name() -> &'static str {
5301 "View"
5302 }
5303 }
5304
5305 let (window_id, _root_view) = cx.add_window(|_| View);
5306 let observing_view = cx.add_view(window_id, |_| View);
5307 let observed_view = cx.add_view(window_id, |_| View);
5308
5309 let observation_count = Rc::new(RefCell::new(0));
5310 observing_view.update(cx, |_, cx| {
5311 let observation_count = observation_count.clone();
5312 let subscription = Rc::new(RefCell::new(None));
5313 *subscription.borrow_mut() = Some(cx.observe(&observed_view, {
5314 let subscription = subscription.clone();
5315 move |_, _, _| {
5316 subscription.borrow_mut().take();
5317 *observation_count.borrow_mut() += 1;
5318 }
5319 }));
5320 });
5321
5322 observed_view.update(cx, |_, cx| {
5323 cx.notify();
5324 });
5325
5326 observed_view.update(cx, |_, cx| {
5327 cx.notify();
5328 });
5329
5330 assert_eq!(*observation_count.borrow(), 1);
5331
5332 // Global Observation
5333 let observation_count = Rc::new(RefCell::new(0));
5334 let subscription = Rc::new(RefCell::new(None));
5335 *subscription.borrow_mut() = Some(cx.observe_global::<(), _>({
5336 let observation_count = observation_count.clone();
5337 let subscription = subscription.clone();
5338 move |_| {
5339 subscription.borrow_mut().take();
5340 *observation_count.borrow_mut() += 1;
5341 }
5342 }));
5343
5344 cx.update(|cx| {
5345 cx.default_global::<()>();
5346 cx.set_global(());
5347 });
5348 assert_eq!(*observation_count.borrow(), 1);
5349 }
5350
5351 #[crate::test(self)]
5352 fn test_focus(cx: &mut TestAppContext) {
5353 struct View {
5354 name: String,
5355 events: Arc<Mutex<Vec<String>>>,
5356 child: Option<AnyViewHandle>,
5357 }
5358
5359 impl Entity for View {
5360 type Event = ();
5361 }
5362
5363 impl super::View for View {
5364 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
5365 self.child
5366 .as_ref()
5367 .map(|child| ChildView::new(child, cx).into_any())
5368 .unwrap_or(Empty::new().into_any())
5369 }
5370
5371 fn ui_name() -> &'static str {
5372 "View"
5373 }
5374
5375 fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
5376 if cx.handle().id() == focused.id() {
5377 self.events.lock().push(format!("{} focused", &self.name));
5378 }
5379 }
5380
5381 fn focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
5382 if cx.handle().id() == blurred.id() {
5383 self.events.lock().push(format!("{} blurred", &self.name));
5384 }
5385 }
5386 }
5387
5388 let view_events: Arc<Mutex<Vec<String>>> = Default::default();
5389 let (window_id, view_1) = cx.add_window(|_| View {
5390 events: view_events.clone(),
5391 name: "view 1".to_string(),
5392 child: None,
5393 });
5394 let view_2 = cx
5395 .update_window(window_id, |cx| {
5396 let view_2 = cx.add_view(|_| View {
5397 events: view_events.clone(),
5398 name: "view 2".to_string(),
5399 child: None,
5400 });
5401 view_1.update(cx, |view_1, cx| {
5402 view_1.child = Some(view_2.clone().into_any());
5403 cx.notify();
5404 });
5405 view_2
5406 })
5407 .unwrap();
5408
5409 let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
5410 view_1.update(cx, |_, cx| {
5411 cx.observe_focus(&view_2, {
5412 let observed_events = observed_events.clone();
5413 move |this, view, focused, cx| {
5414 let label = if focused { "focus" } else { "blur" };
5415 observed_events.lock().push(format!(
5416 "{} observed {}'s {}",
5417 this.name,
5418 view.read(cx).name,
5419 label
5420 ))
5421 }
5422 })
5423 .detach();
5424 });
5425 view_2.update(cx, |_, cx| {
5426 cx.observe_focus(&view_1, {
5427 let observed_events = observed_events.clone();
5428 move |this, view, focused, cx| {
5429 let label = if focused { "focus" } else { "blur" };
5430 observed_events.lock().push(format!(
5431 "{} observed {}'s {}",
5432 this.name,
5433 view.read(cx).name,
5434 label
5435 ))
5436 }
5437 })
5438 .detach();
5439 });
5440 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
5441 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
5442
5443 view_1.update(cx, |_, cx| {
5444 // Ensure only the last focus event is honored.
5445 cx.focus(&view_2);
5446 cx.focus(&view_1);
5447 cx.focus(&view_2);
5448 });
5449
5450 assert_eq!(
5451 mem::take(&mut *view_events.lock()),
5452 ["view 1 blurred", "view 2 focused"],
5453 );
5454 assert_eq!(
5455 mem::take(&mut *observed_events.lock()),
5456 [
5457 "view 2 observed view 1's blur",
5458 "view 1 observed view 2's focus"
5459 ]
5460 );
5461
5462 view_1.update(cx, |_, cx| cx.focus(&view_1));
5463 assert_eq!(
5464 mem::take(&mut *view_events.lock()),
5465 ["view 2 blurred", "view 1 focused"],
5466 );
5467 assert_eq!(
5468 mem::take(&mut *observed_events.lock()),
5469 [
5470 "view 1 observed view 2's blur",
5471 "view 2 observed view 1's focus"
5472 ]
5473 );
5474
5475 view_1.update(cx, |_, cx| cx.focus(&view_2));
5476 assert_eq!(
5477 mem::take(&mut *view_events.lock()),
5478 ["view 1 blurred", "view 2 focused"],
5479 );
5480 assert_eq!(
5481 mem::take(&mut *observed_events.lock()),
5482 [
5483 "view 2 observed view 1's blur",
5484 "view 1 observed view 2's focus"
5485 ]
5486 );
5487
5488 println!("=====================");
5489 view_1.update(cx, |view, _| {
5490 drop(view_2);
5491 view.child = None;
5492 });
5493 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
5494 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
5495 }
5496
5497 #[crate::test(self)]
5498 fn test_deserialize_actions(cx: &mut AppContext) {
5499 #[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
5500 pub struct ComplexAction {
5501 arg: String,
5502 count: usize,
5503 }
5504
5505 actions!(test::something, [SimpleAction]);
5506 impl_actions!(test::something, [ComplexAction]);
5507
5508 cx.add_global_action(move |_: &SimpleAction, _: &mut AppContext| {});
5509 cx.add_global_action(move |_: &ComplexAction, _: &mut AppContext| {});
5510
5511 let action1 = cx
5512 .deserialize_action(
5513 "test::something::ComplexAction",
5514 Some(r#"{"arg": "a", "count": 5}"#),
5515 )
5516 .unwrap();
5517 let action2 = cx
5518 .deserialize_action("test::something::SimpleAction", None)
5519 .unwrap();
5520 assert_eq!(
5521 action1.as_any().downcast_ref::<ComplexAction>().unwrap(),
5522 &ComplexAction {
5523 arg: "a".to_string(),
5524 count: 5,
5525 }
5526 );
5527 assert_eq!(
5528 action2.as_any().downcast_ref::<SimpleAction>().unwrap(),
5529 &SimpleAction
5530 );
5531 }
5532
5533 #[crate::test(self)]
5534 fn test_dispatch_action(cx: &mut AppContext) {
5535 struct ViewA {
5536 id: usize,
5537 child: Option<AnyViewHandle>,
5538 }
5539
5540 impl Entity for ViewA {
5541 type Event = ();
5542 }
5543
5544 impl View for ViewA {
5545 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
5546 self.child
5547 .as_ref()
5548 .map(|child| ChildView::new(child, cx).into_any())
5549 .unwrap_or(Empty::new().into_any())
5550 }
5551
5552 fn ui_name() -> &'static str {
5553 "View"
5554 }
5555 }
5556
5557 struct ViewB {
5558 id: usize,
5559 child: Option<AnyViewHandle>,
5560 }
5561
5562 impl Entity for ViewB {
5563 type Event = ();
5564 }
5565
5566 impl View for ViewB {
5567 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
5568 self.child
5569 .as_ref()
5570 .map(|child| ChildView::new(child, cx).into_any())
5571 .unwrap_or(Empty::new().into_any())
5572 }
5573
5574 fn ui_name() -> &'static str {
5575 "View"
5576 }
5577 }
5578
5579 #[derive(Clone, Default, Deserialize, PartialEq)]
5580 pub struct Action(pub String);
5581
5582 impl_actions!(test, [Action]);
5583
5584 let actions = Rc::new(RefCell::new(Vec::new()));
5585
5586 cx.add_global_action({
5587 let actions = actions.clone();
5588 move |_: &Action, _: &mut AppContext| {
5589 actions.borrow_mut().push("global".to_string());
5590 }
5591 });
5592
5593 cx.add_action({
5594 let actions = actions.clone();
5595 move |view: &mut ViewA, action: &Action, cx| {
5596 assert_eq!(action.0, "bar");
5597 cx.propagate_action();
5598 actions.borrow_mut().push(format!("{} a", view.id));
5599 }
5600 });
5601
5602 cx.add_action({
5603 let actions = actions.clone();
5604 move |view: &mut ViewA, _: &Action, cx| {
5605 if view.id != 1 {
5606 cx.add_view(|cx| {
5607 cx.propagate_action(); // Still works on a nested ViewContext
5608 ViewB { id: 5, child: None }
5609 });
5610 }
5611 actions.borrow_mut().push(format!("{} b", view.id));
5612 }
5613 });
5614
5615 cx.add_action({
5616 let actions = actions.clone();
5617 move |view: &mut ViewB, _: &Action, cx| {
5618 cx.propagate_action();
5619 actions.borrow_mut().push(format!("{} c", view.id));
5620 }
5621 });
5622
5623 cx.add_action({
5624 let actions = actions.clone();
5625 move |view: &mut ViewB, _: &Action, cx| {
5626 cx.propagate_action();
5627 actions.borrow_mut().push(format!("{} d", view.id));
5628 }
5629 });
5630
5631 cx.capture_action({
5632 let actions = actions.clone();
5633 move |view: &mut ViewA, _: &Action, cx| {
5634 cx.propagate_action();
5635 actions.borrow_mut().push(format!("{} capture", view.id));
5636 }
5637 });
5638
5639 let observed_actions = Rc::new(RefCell::new(Vec::new()));
5640 cx.observe_actions({
5641 let observed_actions = observed_actions.clone();
5642 move |action_id, _| observed_actions.borrow_mut().push(action_id)
5643 })
5644 .detach();
5645
5646 let (window_id, view_1) =
5647 cx.add_window(Default::default(), |_| ViewA { id: 1, child: None });
5648 let view_2 = cx
5649 .update_window(window_id, |cx| {
5650 let child = cx.add_view(|_| ViewB { id: 2, child: None });
5651 view_1.update(cx, |view, cx| {
5652 view.child = Some(child.clone().into_any());
5653 cx.notify();
5654 });
5655 child
5656 })
5657 .unwrap();
5658 let view_3 = cx
5659 .update_window(window_id, |cx| {
5660 let child = cx.add_view(|_| ViewA { id: 3, child: None });
5661 view_2.update(cx, |view, cx| {
5662 view.child = Some(child.clone().into_any());
5663 cx.notify();
5664 });
5665 child
5666 })
5667 .unwrap();
5668 let view_4 = cx
5669 .update_window(window_id, |cx| {
5670 let child = cx.add_view(|_| ViewB { id: 4, child: None });
5671 view_3.update(cx, |view, cx| {
5672 view.child = Some(child.clone().into_any());
5673 cx.notify();
5674 });
5675 child
5676 })
5677 .unwrap();
5678
5679 cx.update_window(window_id, |cx| {
5680 cx.dispatch_action(Some(view_4.id()), &Action("bar".to_string()))
5681 });
5682
5683 assert_eq!(
5684 *actions.borrow(),
5685 vec![
5686 "1 capture",
5687 "3 capture",
5688 "4 d",
5689 "4 c",
5690 "3 b",
5691 "3 a",
5692 "2 d",
5693 "2 c",
5694 "1 b"
5695 ]
5696 );
5697 assert_eq!(*observed_actions.borrow(), [Action::default().id()]);
5698
5699 // Remove view_1, which doesn't propagate the action
5700
5701 let (window_id, view_2) =
5702 cx.add_window(Default::default(), |_| ViewB { id: 2, child: None });
5703 let view_3 = cx
5704 .update_window(window_id, |cx| {
5705 let child = cx.add_view(|_| ViewA { id: 3, child: None });
5706 view_2.update(cx, |view, cx| {
5707 view.child = Some(child.clone().into_any());
5708 cx.notify();
5709 });
5710 child
5711 })
5712 .unwrap();
5713 let view_4 = cx
5714 .update_window(window_id, |cx| {
5715 let child = cx.add_view(|_| ViewB { id: 4, child: None });
5716 view_3.update(cx, |view, cx| {
5717 view.child = Some(child.clone().into_any());
5718 cx.notify();
5719 });
5720 child
5721 })
5722 .unwrap();
5723
5724 actions.borrow_mut().clear();
5725 cx.update_window(window_id, |cx| {
5726 cx.dispatch_action(Some(view_4.id()), &Action("bar".to_string()))
5727 });
5728
5729 assert_eq!(
5730 *actions.borrow(),
5731 vec![
5732 "3 capture",
5733 "4 d",
5734 "4 c",
5735 "3 b",
5736 "3 a",
5737 "2 d",
5738 "2 c",
5739 "global"
5740 ]
5741 );
5742 assert_eq!(
5743 *observed_actions.borrow(),
5744 [Action::default().id(), Action::default().id()]
5745 );
5746 }
5747
5748 #[crate::test(self)]
5749 fn test_dispatch_keystroke(cx: &mut AppContext) {
5750 #[derive(Clone, Deserialize, PartialEq)]
5751 pub struct Action(String);
5752
5753 impl_actions!(test, [Action]);
5754
5755 struct View {
5756 id: usize,
5757 keymap_context: KeymapContext,
5758 child: Option<AnyViewHandle>,
5759 }
5760
5761 impl Entity for View {
5762 type Event = ();
5763 }
5764
5765 impl super::View for View {
5766 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
5767 self.child
5768 .as_ref()
5769 .map(|child| ChildView::new(child, cx).into_any())
5770 .unwrap_or(Empty::new().into_any())
5771 }
5772
5773 fn ui_name() -> &'static str {
5774 "View"
5775 }
5776
5777 fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
5778 *keymap = self.keymap_context.clone();
5779 }
5780 }
5781
5782 impl View {
5783 fn new(id: usize) -> Self {
5784 View {
5785 id,
5786 keymap_context: KeymapContext::default(),
5787 child: None,
5788 }
5789 }
5790 }
5791
5792 let mut view_1 = View::new(1);
5793 let mut view_2 = View::new(2);
5794 let mut view_3 = View::new(3);
5795 view_1.keymap_context.add_identifier("a");
5796 view_2.keymap_context.add_identifier("a");
5797 view_2.keymap_context.add_identifier("b");
5798 view_3.keymap_context.add_identifier("a");
5799 view_3.keymap_context.add_identifier("b");
5800 view_3.keymap_context.add_identifier("c");
5801
5802 let (window_id, _view_1) = cx.add_window(Default::default(), |cx| {
5803 let view_2 = cx.add_view(|cx| {
5804 let view_3 = cx.add_view(|cx| {
5805 cx.focus_self();
5806 view_3
5807 });
5808 view_2.child = Some(view_3.into_any());
5809 view_2
5810 });
5811 view_1.child = Some(view_2.into_any());
5812 view_1
5813 });
5814
5815 // This binding only dispatches an action on view 2 because that view will have
5816 // "a" and "b" in its context, but not "c".
5817 cx.add_bindings(vec![Binding::new(
5818 "a",
5819 Action("a".to_string()),
5820 Some("a && b && !c"),
5821 )]);
5822
5823 cx.add_bindings(vec![Binding::new("b", Action("b".to_string()), None)]);
5824
5825 // This binding only dispatches an action on views 2 and 3, because they have
5826 // a parent view with a in its context
5827 cx.add_bindings(vec![Binding::new(
5828 "c",
5829 Action("c".to_string()),
5830 Some("b > c"),
5831 )]);
5832
5833 // This binding only dispatches an action on view 2, because they have
5834 // a parent view with a in its context
5835 cx.add_bindings(vec![Binding::new(
5836 "d",
5837 Action("d".to_string()),
5838 Some("a && !b > b"),
5839 )]);
5840
5841 let actions = Rc::new(RefCell::new(Vec::new()));
5842 cx.add_action({
5843 let actions = actions.clone();
5844 move |view: &mut View, action: &Action, cx| {
5845 actions
5846 .borrow_mut()
5847 .push(format!("{} {}", view.id, action.0));
5848
5849 if action.0 == "b" {
5850 cx.propagate_action();
5851 }
5852 }
5853 });
5854
5855 cx.add_global_action({
5856 let actions = actions.clone();
5857 move |action: &Action, _| {
5858 actions.borrow_mut().push(format!("global {}", action.0));
5859 }
5860 });
5861
5862 cx.update_window(window_id, |cx| {
5863 cx.dispatch_keystroke(&Keystroke::parse("a").unwrap())
5864 });
5865 assert_eq!(&*actions.borrow(), &["2 a"]);
5866 actions.borrow_mut().clear();
5867
5868 cx.update_window(window_id, |cx| {
5869 cx.dispatch_keystroke(&Keystroke::parse("b").unwrap());
5870 });
5871
5872 assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
5873 actions.borrow_mut().clear();
5874
5875 cx.update_window(window_id, |cx| {
5876 cx.dispatch_keystroke(&Keystroke::parse("c").unwrap());
5877 });
5878 assert_eq!(&*actions.borrow(), &["3 c"]);
5879 actions.borrow_mut().clear();
5880
5881 cx.update_window(window_id, |cx| {
5882 cx.dispatch_keystroke(&Keystroke::parse("d").unwrap());
5883 });
5884 assert_eq!(&*actions.borrow(), &["2 d"]);
5885 actions.borrow_mut().clear();
5886 }
5887
5888 #[crate::test(self)]
5889 fn test_keystrokes_for_action(cx: &mut TestAppContext) {
5890 actions!(test, [Action1, Action2, GlobalAction]);
5891
5892 struct View1 {
5893 child: ViewHandle<View2>,
5894 }
5895 struct View2 {}
5896
5897 impl Entity for View1 {
5898 type Event = ();
5899 }
5900 impl Entity for View2 {
5901 type Event = ();
5902 }
5903
5904 impl super::View for View1 {
5905 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
5906 ChildView::new(&self.child, cx).into_any()
5907 }
5908 fn ui_name() -> &'static str {
5909 "View1"
5910 }
5911 }
5912 impl super::View for View2 {
5913 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
5914 Empty::new().into_any()
5915 }
5916 fn ui_name() -> &'static str {
5917 "View2"
5918 }
5919 }
5920
5921 let (window_id, view_1) = cx.add_window(|cx| {
5922 let view_2 = cx.add_view(|cx| {
5923 cx.focus_self();
5924 View2 {}
5925 });
5926 View1 { child: view_2 }
5927 });
5928 let view_2 = view_1.read_with(cx, |view, _| view.child.clone());
5929
5930 cx.update(|cx| {
5931 cx.add_action(|_: &mut View1, _: &Action1, _cx| {});
5932 cx.add_action(|_: &mut View2, _: &Action2, _cx| {});
5933 cx.add_global_action(|_: &GlobalAction, _| {});
5934 cx.add_bindings(vec![
5935 Binding::new("a", Action1, Some("View1")),
5936 Binding::new("b", Action2, Some("View1 > View2")),
5937 Binding::new("c", GlobalAction, Some("View3")), // View 3 does not exist
5938 ]);
5939 });
5940
5941 let view_1_id = view_1.id();
5942 view_1.update(cx, |_, cx| {
5943 view_2.update(cx, |_, cx| {
5944 // Sanity check
5945 let mut new_parents = Default::default();
5946 let mut notify_views_if_parents_change = Default::default();
5947 let mut layout_cx = LayoutContext::new(
5948 cx,
5949 &mut new_parents,
5950 &mut notify_views_if_parents_change,
5951 false,
5952 );
5953 assert_eq!(
5954 layout_cx
5955 .keystrokes_for_action(view_1_id, &Action1)
5956 .unwrap()
5957 .as_slice(),
5958 &[Keystroke::parse("a").unwrap()]
5959 );
5960 assert_eq!(
5961 layout_cx
5962 .keystrokes_for_action(view_2.id(), &Action2)
5963 .unwrap()
5964 .as_slice(),
5965 &[Keystroke::parse("b").unwrap()]
5966 );
5967
5968 // The 'a' keystroke propagates up the view tree from view_2
5969 // to view_1. The action, Action1, is handled by view_1.
5970 assert_eq!(
5971 layout_cx
5972 .keystrokes_for_action(view_2.id(), &Action1)
5973 .unwrap()
5974 .as_slice(),
5975 &[Keystroke::parse("a").unwrap()]
5976 );
5977
5978 // Actions that are handled below the current view don't have bindings
5979 assert_eq!(layout_cx.keystrokes_for_action(view_1_id, &Action2), None);
5980
5981 // Actions that are handled in other branches of the tree should not have a binding
5982 assert_eq!(
5983 layout_cx.keystrokes_for_action(view_2.id(), &GlobalAction),
5984 None
5985 );
5986 });
5987 });
5988
5989 // Check that global actions do not have a binding, even if a binding does exist in another view
5990 assert_eq!(
5991 &available_actions(window_id, view_1.id(), cx),
5992 &[
5993 ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
5994 ("test::GlobalAction", vec![])
5995 ],
5996 );
5997
5998 // Check that view 1 actions and bindings are available even when called from view 2
5999 assert_eq!(
6000 &available_actions(window_id, view_2.id(), cx),
6001 &[
6002 ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
6003 ("test::Action2", vec![Keystroke::parse("b").unwrap()]),
6004 ("test::GlobalAction", vec![]),
6005 ],
6006 );
6007
6008 // Produces a list of actions and key bindings
6009 fn available_actions(
6010 window_id: usize,
6011 view_id: usize,
6012 cx: &TestAppContext,
6013 ) -> Vec<(&'static str, Vec<Keystroke>)> {
6014 cx.available_actions(window_id, view_id)
6015 .into_iter()
6016 .map(|(action_name, _, bindings)| {
6017 (
6018 action_name,
6019 bindings
6020 .iter()
6021 .map(|binding| binding.keystrokes()[0].clone())
6022 .collect::<Vec<_>>(),
6023 )
6024 })
6025 .sorted_by(|(name1, _), (name2, _)| name1.cmp(name2))
6026 .collect()
6027 }
6028 }
6029
6030 #[crate::test(self)]
6031 async fn test_model_condition(cx: &mut TestAppContext) {
6032 struct Counter(usize);
6033
6034 impl super::Entity for Counter {
6035 type Event = ();
6036 }
6037
6038 impl Counter {
6039 fn inc(&mut self, cx: &mut ModelContext<Self>) {
6040 self.0 += 1;
6041 cx.notify();
6042 }
6043 }
6044
6045 let model = cx.add_model(|_| Counter(0));
6046
6047 let condition1 = model.condition(cx, |model, _| model.0 == 2);
6048 let condition2 = model.condition(cx, |model, _| model.0 == 3);
6049 smol::pin!(condition1, condition2);
6050
6051 model.update(cx, |model, cx| model.inc(cx));
6052 assert_eq!(poll_once(&mut condition1).await, None);
6053 assert_eq!(poll_once(&mut condition2).await, None);
6054
6055 model.update(cx, |model, cx| model.inc(cx));
6056 assert_eq!(poll_once(&mut condition1).await, Some(()));
6057 assert_eq!(poll_once(&mut condition2).await, None);
6058
6059 model.update(cx, |model, cx| model.inc(cx));
6060 assert_eq!(poll_once(&mut condition2).await, Some(()));
6061
6062 model.update(cx, |_, cx| cx.notify());
6063 }
6064
6065 #[crate::test(self)]
6066 #[should_panic]
6067 async fn test_model_condition_timeout(cx: &mut TestAppContext) {
6068 struct Model;
6069
6070 impl super::Entity for Model {
6071 type Event = ();
6072 }
6073
6074 let model = cx.add_model(|_| Model);
6075 model.condition(cx, |_, _| false).await;
6076 }
6077
6078 #[crate::test(self)]
6079 #[should_panic(expected = "model dropped with pending condition")]
6080 async fn test_model_condition_panic_on_drop(cx: &mut TestAppContext) {
6081 struct Model;
6082
6083 impl super::Entity for Model {
6084 type Event = ();
6085 }
6086
6087 let model = cx.add_model(|_| Model);
6088 let condition = model.condition(cx, |_, _| false);
6089 cx.update(|_| drop(model));
6090 condition.await;
6091 }
6092
6093 #[crate::test(self)]
6094 async fn test_view_condition(cx: &mut TestAppContext) {
6095 struct Counter(usize);
6096
6097 impl super::Entity for Counter {
6098 type Event = ();
6099 }
6100
6101 impl super::View for Counter {
6102 fn ui_name() -> &'static str {
6103 "test view"
6104 }
6105
6106 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6107 Empty::new().into_any()
6108 }
6109 }
6110
6111 impl Counter {
6112 fn inc(&mut self, cx: &mut ViewContext<Self>) {
6113 self.0 += 1;
6114 cx.notify();
6115 }
6116 }
6117
6118 let (_, view) = cx.add_window(|_| Counter(0));
6119
6120 let condition1 = view.condition(cx, |view, _| view.0 == 2);
6121 let condition2 = view.condition(cx, |view, _| view.0 == 3);
6122 smol::pin!(condition1, condition2);
6123
6124 view.update(cx, |view, cx| view.inc(cx));
6125 assert_eq!(poll_once(&mut condition1).await, None);
6126 assert_eq!(poll_once(&mut condition2).await, None);
6127
6128 view.update(cx, |view, cx| view.inc(cx));
6129 assert_eq!(poll_once(&mut condition1).await, Some(()));
6130 assert_eq!(poll_once(&mut condition2).await, None);
6131
6132 view.update(cx, |view, cx| view.inc(cx));
6133 assert_eq!(poll_once(&mut condition2).await, Some(()));
6134 view.update(cx, |_, cx| cx.notify());
6135 }
6136
6137 #[crate::test(self)]
6138 #[should_panic]
6139 async fn test_view_condition_timeout(cx: &mut TestAppContext) {
6140 let (_, view) = cx.add_window(|_| TestView::default());
6141 view.condition(cx, |_, _| false).await;
6142 }
6143
6144 #[crate::test(self)]
6145 #[should_panic(expected = "view dropped with pending condition")]
6146 async fn test_view_condition_panic_on_drop(cx: &mut TestAppContext) {
6147 let (window_id, _root_view) = cx.add_window(|_| TestView::default());
6148 let view = cx.add_view(window_id, |_| TestView::default());
6149
6150 let condition = view.condition(cx, |_, _| false);
6151 cx.update(|_| drop(view));
6152 condition.await;
6153 }
6154
6155 #[crate::test(self)]
6156 fn test_refresh_windows(cx: &mut AppContext) {
6157 struct View(usize);
6158
6159 impl super::Entity for View {
6160 type Event = ();
6161 }
6162
6163 impl super::View for View {
6164 fn ui_name() -> &'static str {
6165 "test view"
6166 }
6167
6168 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6169 Empty::new().into_any_named(format!("render count: {}", post_inc(&mut self.0)))
6170 }
6171 }
6172
6173 let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0));
6174 cx.update_window(window_id, |cx| {
6175 assert_eq!(
6176 cx.window.rendered_views[&root_view.id()].name(),
6177 Some("render count: 0")
6178 );
6179 });
6180
6181 let view = cx
6182 .update_window(window_id, |cx| {
6183 cx.refresh_windows();
6184 cx.add_view(|_| View(0))
6185 })
6186 .unwrap();
6187
6188 cx.update_window(window_id, |cx| {
6189 assert_eq!(
6190 cx.window.rendered_views[&root_view.id()].name(),
6191 Some("render count: 1")
6192 );
6193 assert_eq!(
6194 cx.window.rendered_views[&view.id()].name(),
6195 Some("render count: 0")
6196 );
6197 });
6198
6199 cx.update(|cx| cx.refresh_windows());
6200
6201 cx.update_window(window_id, |cx| {
6202 assert_eq!(
6203 cx.window.rendered_views[&root_view.id()].name(),
6204 Some("render count: 2")
6205 );
6206 assert_eq!(
6207 cx.window.rendered_views[&view.id()].name(),
6208 Some("render count: 1")
6209 );
6210 });
6211
6212 cx.update(|cx| {
6213 cx.refresh_windows();
6214 drop(view);
6215 });
6216
6217 cx.update_window(window_id, |cx| {
6218 assert_eq!(
6219 cx.window.rendered_views[&root_view.id()].name(),
6220 Some("render count: 3")
6221 );
6222 assert_eq!(cx.window.rendered_views.len(), 1);
6223 });
6224 }
6225
6226 #[crate::test(self)]
6227 async fn test_labeled_tasks(cx: &mut TestAppContext) {
6228 assert_eq!(None, cx.update(|cx| cx.active_labeled_tasks().next()));
6229 let (mut sender, mut reciever) = postage::oneshot::channel::<()>();
6230 let task = cx
6231 .update(|cx| cx.spawn_labeled("Test Label", |_| async move { reciever.recv().await }));
6232
6233 assert_eq!(
6234 Some("Test Label"),
6235 cx.update(|cx| cx.active_labeled_tasks().next())
6236 );
6237 sender
6238 .send(())
6239 .await
6240 .expect("Could not send message to complete task");
6241 task.await;
6242
6243 assert_eq!(None, cx.update(|cx| cx.active_labeled_tasks().next()));
6244 }
6245
6246 #[crate::test(self)]
6247 async fn test_window_activation(cx: &mut TestAppContext) {
6248 struct View(&'static str);
6249
6250 impl super::Entity for View {
6251 type Event = ();
6252 }
6253
6254 impl super::View for View {
6255 fn ui_name() -> &'static str {
6256 "test view"
6257 }
6258
6259 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6260 Empty::new().into_any()
6261 }
6262 }
6263
6264 let events = Rc::new(RefCell::new(Vec::new()));
6265 let (window_1, _) = cx.add_window(|cx: &mut ViewContext<View>| {
6266 cx.observe_window_activation({
6267 let events = events.clone();
6268 move |this, active, _| events.borrow_mut().push((this.0, active))
6269 })
6270 .detach();
6271 View("window 1")
6272 });
6273 assert_eq!(mem::take(&mut *events.borrow_mut()), [("window 1", true)]);
6274
6275 let (window_2, _) = cx.add_window(|cx: &mut ViewContext<View>| {
6276 cx.observe_window_activation({
6277 let events = events.clone();
6278 move |this, active, _| events.borrow_mut().push((this.0, active))
6279 })
6280 .detach();
6281 View("window 2")
6282 });
6283 assert_eq!(
6284 mem::take(&mut *events.borrow_mut()),
6285 [("window 1", false), ("window 2", true)]
6286 );
6287
6288 let (window_3, _) = cx.add_window(|cx: &mut ViewContext<View>| {
6289 cx.observe_window_activation({
6290 let events = events.clone();
6291 move |this, active, _| events.borrow_mut().push((this.0, active))
6292 })
6293 .detach();
6294 View("window 3")
6295 });
6296 assert_eq!(
6297 mem::take(&mut *events.borrow_mut()),
6298 [("window 2", false), ("window 3", true)]
6299 );
6300
6301 cx.simulate_window_activation(Some(window_2));
6302 assert_eq!(
6303 mem::take(&mut *events.borrow_mut()),
6304 [("window 3", false), ("window 2", true)]
6305 );
6306
6307 cx.simulate_window_activation(Some(window_1));
6308 assert_eq!(
6309 mem::take(&mut *events.borrow_mut()),
6310 [("window 2", false), ("window 1", true)]
6311 );
6312
6313 cx.simulate_window_activation(Some(window_3));
6314 assert_eq!(
6315 mem::take(&mut *events.borrow_mut()),
6316 [("window 1", false), ("window 3", true)]
6317 );
6318
6319 cx.simulate_window_activation(Some(window_3));
6320 assert_eq!(mem::take(&mut *events.borrow_mut()), []);
6321 }
6322
6323 #[crate::test(self)]
6324 fn test_child_view(cx: &mut TestAppContext) {
6325 struct Child {
6326 rendered: Rc<Cell<bool>>,
6327 dropped: Rc<Cell<bool>>,
6328 }
6329
6330 impl super::Entity for Child {
6331 type Event = ();
6332 }
6333
6334 impl super::View for Child {
6335 fn ui_name() -> &'static str {
6336 "child view"
6337 }
6338
6339 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6340 self.rendered.set(true);
6341 Empty::new().into_any()
6342 }
6343 }
6344
6345 impl Drop for Child {
6346 fn drop(&mut self) {
6347 self.dropped.set(true);
6348 }
6349 }
6350
6351 struct Parent {
6352 child: Option<ViewHandle<Child>>,
6353 }
6354
6355 impl super::Entity for Parent {
6356 type Event = ();
6357 }
6358
6359 impl super::View for Parent {
6360 fn ui_name() -> &'static str {
6361 "parent view"
6362 }
6363
6364 fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
6365 if let Some(child) = self.child.as_ref() {
6366 ChildView::new(child, cx).into_any()
6367 } else {
6368 Empty::new().into_any()
6369 }
6370 }
6371 }
6372
6373 let child_rendered = Rc::new(Cell::new(false));
6374 let child_dropped = Rc::new(Cell::new(false));
6375 let (_, root_view) = cx.add_window(|cx| Parent {
6376 child: Some(cx.add_view(|_| Child {
6377 rendered: child_rendered.clone(),
6378 dropped: child_dropped.clone(),
6379 })),
6380 });
6381 assert!(child_rendered.take());
6382 assert!(!child_dropped.take());
6383
6384 root_view.update(cx, |view, cx| {
6385 view.child.take();
6386 cx.notify();
6387 });
6388 assert!(!child_rendered.take());
6389 assert!(child_dropped.take());
6390 }
6391
6392 #[derive(Default)]
6393 struct TestView {
6394 events: Vec<String>,
6395 }
6396
6397 impl Entity for TestView {
6398 type Event = String;
6399 }
6400
6401 impl View for TestView {
6402 fn ui_name() -> &'static str {
6403 "TestView"
6404 }
6405
6406 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement<Self> {
6407 Empty::new().into_any()
6408 }
6409 }
6410}