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