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