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