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