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