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