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