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