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