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