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<T> PartialEq<ViewHandle<T>> for AnyViewHandle {
4919 fn eq(&self, other: &ViewHandle<T>) -> bool {
4920 self.window_id == other.window_id && self.view_id == other.view_id
4921 }
4922}
4923
4924impl Drop for AnyViewHandle {
4925 fn drop(&mut self) {
4926 self.ref_counts
4927 .lock()
4928 .dec_view(self.window_id, self.view_id);
4929 #[cfg(any(test, feature = "test-support"))]
4930 self.ref_counts
4931 .lock()
4932 .leak_detector
4933 .lock()
4934 .handle_dropped(self.view_id, self.handle_id);
4935 }
4936}
4937
4938pub struct AnyModelHandle {
4939 model_id: usize,
4940 model_type: TypeId,
4941 ref_counts: Arc<Mutex<RefCounts>>,
4942
4943 #[cfg(any(test, feature = "test-support"))]
4944 handle_id: usize,
4945}
4946
4947impl AnyModelHandle {
4948 fn new(model_id: usize, model_type: TypeId, ref_counts: Arc<Mutex<RefCounts>>) -> Self {
4949 ref_counts.lock().inc_model(model_id);
4950
4951 #[cfg(any(test, feature = "test-support"))]
4952 let handle_id = ref_counts
4953 .lock()
4954 .leak_detector
4955 .lock()
4956 .handle_created(None, model_id);
4957
4958 Self {
4959 model_id,
4960 model_type,
4961 ref_counts,
4962
4963 #[cfg(any(test, feature = "test-support"))]
4964 handle_id,
4965 }
4966 }
4967
4968 pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> {
4969 if self.is::<T>() {
4970 let result = Some(ModelHandle {
4971 model_id: self.model_id,
4972 model_type: PhantomData,
4973 ref_counts: self.ref_counts.clone(),
4974
4975 #[cfg(any(test, feature = "test-support"))]
4976 handle_id: self.handle_id,
4977 });
4978 unsafe {
4979 Arc::decrement_strong_count(Arc::as_ptr(&self.ref_counts));
4980 }
4981 std::mem::forget(self);
4982 result
4983 } else {
4984 None
4985 }
4986 }
4987
4988 pub fn downgrade(&self) -> AnyWeakModelHandle {
4989 AnyWeakModelHandle {
4990 model_id: self.model_id,
4991 model_type: self.model_type,
4992 }
4993 }
4994
4995 pub fn is<T: Entity>(&self) -> bool {
4996 self.model_type == TypeId::of::<T>()
4997 }
4998
4999 pub fn model_type(&self) -> TypeId {
5000 self.model_type
5001 }
5002}
5003
5004impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
5005 fn from(handle: ModelHandle<T>) -> Self {
5006 Self::new(
5007 handle.model_id,
5008 TypeId::of::<T>(),
5009 handle.ref_counts.clone(),
5010 )
5011 }
5012}
5013
5014impl Clone for AnyModelHandle {
5015 fn clone(&self) -> Self {
5016 Self::new(self.model_id, self.model_type, self.ref_counts.clone())
5017 }
5018}
5019
5020impl Drop for AnyModelHandle {
5021 fn drop(&mut self) {
5022 let mut ref_counts = self.ref_counts.lock();
5023 ref_counts.dec_model(self.model_id);
5024
5025 #[cfg(any(test, feature = "test-support"))]
5026 ref_counts
5027 .leak_detector
5028 .lock()
5029 .handle_dropped(self.model_id, self.handle_id);
5030 }
5031}
5032
5033#[derive(Hash, PartialEq, Eq, Debug)]
5034pub struct AnyWeakModelHandle {
5035 model_id: usize,
5036 model_type: TypeId,
5037}
5038
5039impl AnyWeakModelHandle {
5040 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<AnyModelHandle> {
5041 cx.upgrade_any_model_handle(self)
5042 }
5043 pub fn model_type(&self) -> TypeId {
5044 self.model_type
5045 }
5046
5047 fn is<T: 'static>(&self) -> bool {
5048 TypeId::of::<T>() == self.model_type
5049 }
5050
5051 pub fn downcast<T: Entity>(&self) -> Option<WeakModelHandle<T>> {
5052 if self.is::<T>() {
5053 let result = Some(WeakModelHandle {
5054 model_id: self.model_id,
5055 model_type: PhantomData,
5056 });
5057
5058 result
5059 } else {
5060 None
5061 }
5062 }
5063}
5064
5065impl<T: Entity> From<WeakModelHandle<T>> for AnyWeakModelHandle {
5066 fn from(handle: WeakModelHandle<T>) -> Self {
5067 AnyWeakModelHandle {
5068 model_id: handle.model_id,
5069 model_type: TypeId::of::<T>(),
5070 }
5071 }
5072}
5073
5074#[derive(Debug)]
5075pub struct WeakViewHandle<T> {
5076 window_id: usize,
5077 view_id: usize,
5078 view_type: PhantomData<T>,
5079}
5080
5081impl<T> WeakHandle for WeakViewHandle<T> {
5082 fn id(&self) -> usize {
5083 self.view_id
5084 }
5085}
5086
5087impl<T: View> WeakViewHandle<T> {
5088 fn new(window_id: usize, view_id: usize) -> Self {
5089 Self {
5090 window_id,
5091 view_id,
5092 view_type: PhantomData,
5093 }
5094 }
5095
5096 pub fn id(&self) -> usize {
5097 self.view_id
5098 }
5099
5100 pub fn window_id(&self) -> usize {
5101 self.window_id
5102 }
5103
5104 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<ViewHandle<T>> {
5105 cx.upgrade_view_handle(self)
5106 }
5107}
5108
5109impl<T> Clone for WeakViewHandle<T> {
5110 fn clone(&self) -> Self {
5111 Self {
5112 window_id: self.window_id,
5113 view_id: self.view_id,
5114 view_type: PhantomData,
5115 }
5116 }
5117}
5118
5119impl<T> PartialEq for WeakViewHandle<T> {
5120 fn eq(&self, other: &Self) -> bool {
5121 self.window_id == other.window_id && self.view_id == other.view_id
5122 }
5123}
5124
5125impl<T> Eq for WeakViewHandle<T> {}
5126
5127impl<T> Hash for WeakViewHandle<T> {
5128 fn hash<H: Hasher>(&self, state: &mut H) {
5129 self.window_id.hash(state);
5130 self.view_id.hash(state);
5131 }
5132}
5133
5134pub struct AnyWeakViewHandle {
5135 window_id: usize,
5136 view_id: usize,
5137 view_type: TypeId,
5138}
5139
5140impl AnyWeakViewHandle {
5141 pub fn id(&self) -> usize {
5142 self.view_id
5143 }
5144
5145 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<AnyViewHandle> {
5146 cx.upgrade_any_view_handle(self)
5147 }
5148}
5149
5150impl<T: View> From<WeakViewHandle<T>> for AnyWeakViewHandle {
5151 fn from(handle: WeakViewHandle<T>) -> Self {
5152 AnyWeakViewHandle {
5153 window_id: handle.window_id,
5154 view_id: handle.view_id,
5155 view_type: TypeId::of::<T>(),
5156 }
5157 }
5158}
5159
5160#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
5161pub struct ElementStateId {
5162 view_id: usize,
5163 element_id: usize,
5164 tag: TypeId,
5165}
5166
5167pub struct ElementStateHandle<T> {
5168 value_type: PhantomData<T>,
5169 id: ElementStateId,
5170 ref_counts: Weak<Mutex<RefCounts>>,
5171}
5172
5173impl<T: 'static> ElementStateHandle<T> {
5174 fn new(id: ElementStateId, frame_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
5175 ref_counts.lock().inc_element_state(id, frame_id);
5176 Self {
5177 value_type: PhantomData,
5178 id,
5179 ref_counts: Arc::downgrade(ref_counts),
5180 }
5181 }
5182
5183 pub fn id(&self) -> ElementStateId {
5184 self.id
5185 }
5186
5187 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
5188 cx.element_states
5189 .get(&self.id)
5190 .unwrap()
5191 .downcast_ref()
5192 .unwrap()
5193 }
5194
5195 pub fn update<C, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R
5196 where
5197 C: DerefMut<Target = MutableAppContext>,
5198 {
5199 let mut element_state = cx.deref_mut().cx.element_states.remove(&self.id).unwrap();
5200 let result = f(element_state.downcast_mut().unwrap(), cx);
5201 cx.deref_mut()
5202 .cx
5203 .element_states
5204 .insert(self.id, element_state);
5205 result
5206 }
5207}
5208
5209impl<T> Drop for ElementStateHandle<T> {
5210 fn drop(&mut self) {
5211 if let Some(ref_counts) = self.ref_counts.upgrade() {
5212 ref_counts.lock().dec_element_state(self.id);
5213 }
5214 }
5215}
5216
5217#[must_use]
5218pub enum Subscription {
5219 Subscription(callback_collection::Subscription<usize, SubscriptionCallback>),
5220 Observation(callback_collection::Subscription<usize, ObservationCallback>),
5221 GlobalSubscription(callback_collection::Subscription<TypeId, GlobalSubscriptionCallback>),
5222 GlobalObservation(callback_collection::Subscription<TypeId, GlobalObservationCallback>),
5223 FocusObservation(callback_collection::Subscription<usize, FocusObservationCallback>),
5224 WindowActivationObservation(callback_collection::Subscription<usize, WindowActivationCallback>),
5225 WindowFullscreenObservation(callback_collection::Subscription<usize, WindowFullscreenCallback>),
5226 WindowBoundsObservation(callback_collection::Subscription<usize, WindowBoundsCallback>),
5227 KeystrokeObservation(callback_collection::Subscription<usize, KeystrokeCallback>),
5228 ReleaseObservation(callback_collection::Subscription<usize, ReleaseObservationCallback>),
5229 ActionObservation(callback_collection::Subscription<(), ActionObservationCallback>),
5230}
5231
5232impl Subscription {
5233 pub fn id(&self) -> usize {
5234 match self {
5235 Subscription::Subscription(subscription) => subscription.id(),
5236 Subscription::Observation(subscription) => subscription.id(),
5237 Subscription::GlobalSubscription(subscription) => subscription.id(),
5238 Subscription::GlobalObservation(subscription) => subscription.id(),
5239 Subscription::FocusObservation(subscription) => subscription.id(),
5240 Subscription::WindowActivationObservation(subscription) => subscription.id(),
5241 Subscription::WindowFullscreenObservation(subscription) => subscription.id(),
5242 Subscription::WindowBoundsObservation(subscription) => subscription.id(),
5243 Subscription::KeystrokeObservation(subscription) => subscription.id(),
5244 Subscription::ReleaseObservation(subscription) => subscription.id(),
5245 Subscription::ActionObservation(subscription) => subscription.id(),
5246 }
5247 }
5248
5249 pub fn detach(&mut self) {
5250 match self {
5251 Subscription::Subscription(subscription) => subscription.detach(),
5252 Subscription::GlobalSubscription(subscription) => subscription.detach(),
5253 Subscription::Observation(subscription) => subscription.detach(),
5254 Subscription::GlobalObservation(subscription) => subscription.detach(),
5255 Subscription::FocusObservation(subscription) => subscription.detach(),
5256 Subscription::KeystrokeObservation(subscription) => subscription.detach(),
5257 Subscription::WindowActivationObservation(subscription) => subscription.detach(),
5258 Subscription::WindowFullscreenObservation(subscription) => subscription.detach(),
5259 Subscription::WindowBoundsObservation(subscription) => subscription.detach(),
5260 Subscription::ReleaseObservation(subscription) => subscription.detach(),
5261 Subscription::ActionObservation(subscription) => subscription.detach(),
5262 }
5263 }
5264}
5265
5266lazy_static! {
5267 static ref LEAK_BACKTRACE: bool =
5268 std::env::var("LEAK_BACKTRACE").map_or(false, |b| !b.is_empty());
5269}
5270
5271#[cfg(any(test, feature = "test-support"))]
5272#[derive(Default)]
5273pub struct LeakDetector {
5274 next_handle_id: usize,
5275 #[allow(clippy::type_complexity)]
5276 handle_backtraces: HashMap<
5277 usize,
5278 (
5279 Option<&'static str>,
5280 HashMap<usize, Option<backtrace::Backtrace>>,
5281 ),
5282 >,
5283}
5284
5285#[cfg(any(test, feature = "test-support"))]
5286impl LeakDetector {
5287 fn handle_created(&mut self, type_name: Option<&'static str>, entity_id: usize) -> usize {
5288 let handle_id = post_inc(&mut self.next_handle_id);
5289 let entry = self.handle_backtraces.entry(entity_id).or_default();
5290 let backtrace = if *LEAK_BACKTRACE {
5291 Some(backtrace::Backtrace::new_unresolved())
5292 } else {
5293 None
5294 };
5295 if let Some(type_name) = type_name {
5296 entry.0.get_or_insert(type_name);
5297 }
5298 entry.1.insert(handle_id, backtrace);
5299 handle_id
5300 }
5301
5302 fn handle_dropped(&mut self, entity_id: usize, handle_id: usize) {
5303 if let Some((_, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
5304 assert!(backtraces.remove(&handle_id).is_some());
5305 if backtraces.is_empty() {
5306 self.handle_backtraces.remove(&entity_id);
5307 }
5308 }
5309 }
5310
5311 pub fn assert_dropped(&mut self, entity_id: usize) {
5312 if let Some((type_name, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
5313 for trace in backtraces.values_mut().flatten() {
5314 trace.resolve();
5315 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
5316 }
5317
5318 let hint = if *LEAK_BACKTRACE {
5319 ""
5320 } else {
5321 " – set LEAK_BACKTRACE=1 for more information"
5322 };
5323
5324 panic!(
5325 "{} handles to {} {} still exist{}",
5326 backtraces.len(),
5327 type_name.unwrap_or("entity"),
5328 entity_id,
5329 hint
5330 );
5331 }
5332 }
5333
5334 pub fn detect(&mut self) {
5335 let mut found_leaks = false;
5336 for (id, (type_name, backtraces)) in self.handle_backtraces.iter_mut() {
5337 eprintln!(
5338 "leaked {} handles to {} {}",
5339 backtraces.len(),
5340 type_name.unwrap_or("entity"),
5341 id
5342 );
5343 for trace in backtraces.values_mut().flatten() {
5344 trace.resolve();
5345 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
5346 }
5347 found_leaks = true;
5348 }
5349
5350 let hint = if *LEAK_BACKTRACE {
5351 ""
5352 } else {
5353 " – set LEAK_BACKTRACE=1 for more information"
5354 };
5355 assert!(!found_leaks, "detected leaked handles{}", hint);
5356 }
5357}
5358
5359#[derive(Default)]
5360struct RefCounts {
5361 entity_counts: HashMap<usize, usize>,
5362 element_state_counts: HashMap<ElementStateId, ElementStateRefCount>,
5363 dropped_models: HashSet<usize>,
5364 dropped_views: HashSet<(usize, usize)>,
5365 dropped_element_states: HashSet<ElementStateId>,
5366
5367 #[cfg(any(test, feature = "test-support"))]
5368 leak_detector: Arc<Mutex<LeakDetector>>,
5369}
5370
5371struct ElementStateRefCount {
5372 ref_count: usize,
5373 frame_id: usize,
5374}
5375
5376impl RefCounts {
5377 fn inc_model(&mut self, model_id: usize) {
5378 match self.entity_counts.entry(model_id) {
5379 Entry::Occupied(mut entry) => {
5380 *entry.get_mut() += 1;
5381 }
5382 Entry::Vacant(entry) => {
5383 entry.insert(1);
5384 self.dropped_models.remove(&model_id);
5385 }
5386 }
5387 }
5388
5389 fn inc_view(&mut self, window_id: usize, view_id: usize) {
5390 match self.entity_counts.entry(view_id) {
5391 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
5392 Entry::Vacant(entry) => {
5393 entry.insert(1);
5394 self.dropped_views.remove(&(window_id, view_id));
5395 }
5396 }
5397 }
5398
5399 fn inc_element_state(&mut self, id: ElementStateId, frame_id: usize) {
5400 match self.element_state_counts.entry(id) {
5401 Entry::Occupied(mut entry) => {
5402 let entry = entry.get_mut();
5403 if entry.frame_id == frame_id || entry.ref_count >= 2 {
5404 panic!("used the same element state more than once in the same frame");
5405 }
5406 entry.ref_count += 1;
5407 entry.frame_id = frame_id;
5408 }
5409 Entry::Vacant(entry) => {
5410 entry.insert(ElementStateRefCount {
5411 ref_count: 1,
5412 frame_id,
5413 });
5414 self.dropped_element_states.remove(&id);
5415 }
5416 }
5417 }
5418
5419 fn dec_model(&mut self, model_id: usize) {
5420 let count = self.entity_counts.get_mut(&model_id).unwrap();
5421 *count -= 1;
5422 if *count == 0 {
5423 self.entity_counts.remove(&model_id);
5424 self.dropped_models.insert(model_id);
5425 }
5426 }
5427
5428 fn dec_view(&mut self, window_id: usize, view_id: usize) {
5429 let count = self.entity_counts.get_mut(&view_id).unwrap();
5430 *count -= 1;
5431 if *count == 0 {
5432 self.entity_counts.remove(&view_id);
5433 self.dropped_views.insert((window_id, view_id));
5434 }
5435 }
5436
5437 fn dec_element_state(&mut self, id: ElementStateId) {
5438 let entry = self.element_state_counts.get_mut(&id).unwrap();
5439 entry.ref_count -= 1;
5440 if entry.ref_count == 0 {
5441 self.element_state_counts.remove(&id);
5442 self.dropped_element_states.insert(id);
5443 }
5444 }
5445
5446 fn is_entity_alive(&self, entity_id: usize) -> bool {
5447 self.entity_counts.contains_key(&entity_id)
5448 }
5449
5450 fn take_dropped(
5451 &mut self,
5452 ) -> (
5453 HashSet<usize>,
5454 HashSet<(usize, usize)>,
5455 HashSet<ElementStateId>,
5456 ) {
5457 (
5458 std::mem::take(&mut self.dropped_models),
5459 std::mem::take(&mut self.dropped_views),
5460 std::mem::take(&mut self.dropped_element_states),
5461 )
5462 }
5463}
5464
5465#[cfg(test)]
5466mod tests {
5467 use super::*;
5468 use crate::{actions, elements::*, impl_actions, MouseButton, MouseButtonEvent};
5469 use serde::Deserialize;
5470 use smol::future::poll_once;
5471 use std::{
5472 cell::Cell,
5473 sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
5474 };
5475
5476 #[crate::test(self)]
5477 fn test_model_handles(cx: &mut MutableAppContext) {
5478 struct Model {
5479 other: Option<ModelHandle<Model>>,
5480 events: Vec<String>,
5481 }
5482
5483 impl Entity for Model {
5484 type Event = usize;
5485 }
5486
5487 impl Model {
5488 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
5489 if let Some(other) = other.as_ref() {
5490 cx.observe(other, |me, _, _| {
5491 me.events.push("notified".into());
5492 })
5493 .detach();
5494 cx.subscribe(other, |me, _, event, _| {
5495 me.events.push(format!("observed event {}", event));
5496 })
5497 .detach();
5498 }
5499
5500 Self {
5501 other,
5502 events: Vec::new(),
5503 }
5504 }
5505 }
5506
5507 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
5508 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
5509 assert_eq!(cx.cx.models.len(), 2);
5510
5511 handle_1.update(cx, |model, cx| {
5512 model.events.push("updated".into());
5513 cx.emit(1);
5514 cx.notify();
5515 cx.emit(2);
5516 });
5517 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5518 assert_eq!(
5519 handle_2.read(cx).events,
5520 vec![
5521 "observed event 1".to_string(),
5522 "notified".to_string(),
5523 "observed event 2".to_string(),
5524 ]
5525 );
5526
5527 handle_2.update(cx, |model, _| {
5528 drop(handle_1);
5529 model.other.take();
5530 });
5531
5532 assert_eq!(cx.cx.models.len(), 1);
5533 assert!(cx.subscriptions.is_empty());
5534 assert!(cx.observations.is_empty());
5535 }
5536
5537 #[crate::test(self)]
5538 fn test_model_events(cx: &mut MutableAppContext) {
5539 #[derive(Default)]
5540 struct Model {
5541 events: Vec<usize>,
5542 }
5543
5544 impl Entity for Model {
5545 type Event = usize;
5546 }
5547
5548 let handle_1 = cx.add_model(|_| Model::default());
5549 let handle_2 = cx.add_model(|_| Model::default());
5550
5551 handle_1.update(cx, |_, cx| {
5552 cx.subscribe(&handle_2, move |model: &mut Model, emitter, event, cx| {
5553 model.events.push(*event);
5554
5555 cx.subscribe(&emitter, |model, _, event, _| {
5556 model.events.push(*event * 2);
5557 })
5558 .detach();
5559 })
5560 .detach();
5561 });
5562
5563 handle_2.update(cx, |_, c| c.emit(7));
5564 assert_eq!(handle_1.read(cx).events, vec![7]);
5565
5566 handle_2.update(cx, |_, c| c.emit(5));
5567 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
5568 }
5569
5570 #[crate::test(self)]
5571 fn test_model_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
5572 #[derive(Default)]
5573 struct Model;
5574
5575 impl Entity for Model {
5576 type Event = ();
5577 }
5578
5579 let events = Rc::new(RefCell::new(Vec::new()));
5580 cx.add_model(|cx| {
5581 drop(cx.subscribe(&cx.handle(), {
5582 let events = events.clone();
5583 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
5584 }));
5585 cx.subscribe(&cx.handle(), {
5586 let events = events.clone();
5587 move |_, _, _, _| events.borrow_mut().push("before emit")
5588 })
5589 .detach();
5590 cx.emit(());
5591 cx.subscribe(&cx.handle(), {
5592 let events = events.clone();
5593 move |_, _, _, _| events.borrow_mut().push("after emit")
5594 })
5595 .detach();
5596 Model
5597 });
5598 assert_eq!(*events.borrow(), ["before emit"]);
5599 }
5600
5601 #[crate::test(self)]
5602 fn test_observe_and_notify_from_model(cx: &mut MutableAppContext) {
5603 #[derive(Default)]
5604 struct Model {
5605 count: usize,
5606 events: Vec<usize>,
5607 }
5608
5609 impl Entity for Model {
5610 type Event = ();
5611 }
5612
5613 let handle_1 = cx.add_model(|_| Model::default());
5614 let handle_2 = cx.add_model(|_| Model::default());
5615
5616 handle_1.update(cx, |_, c| {
5617 c.observe(&handle_2, move |model, observed, c| {
5618 model.events.push(observed.read(c).count);
5619 c.observe(&observed, |model, observed, c| {
5620 model.events.push(observed.read(c).count * 2);
5621 })
5622 .detach();
5623 })
5624 .detach();
5625 });
5626
5627 handle_2.update(cx, |model, c| {
5628 model.count = 7;
5629 c.notify()
5630 });
5631 assert_eq!(handle_1.read(cx).events, vec![7]);
5632
5633 handle_2.update(cx, |model, c| {
5634 model.count = 5;
5635 c.notify()
5636 });
5637 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10])
5638 }
5639
5640 #[crate::test(self)]
5641 fn test_model_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
5642 #[derive(Default)]
5643 struct Model;
5644
5645 impl Entity for Model {
5646 type Event = ();
5647 }
5648
5649 let events = Rc::new(RefCell::new(Vec::new()));
5650 cx.add_model(|cx| {
5651 drop(cx.observe(&cx.handle(), {
5652 let events = events.clone();
5653 move |_, _, _| events.borrow_mut().push("dropped before flush")
5654 }));
5655 cx.observe(&cx.handle(), {
5656 let events = events.clone();
5657 move |_, _, _| events.borrow_mut().push("before notify")
5658 })
5659 .detach();
5660 cx.notify();
5661 cx.observe(&cx.handle(), {
5662 let events = events.clone();
5663 move |_, _, _| events.borrow_mut().push("after notify")
5664 })
5665 .detach();
5666 Model
5667 });
5668 assert_eq!(*events.borrow(), ["before notify"]);
5669 }
5670
5671 #[crate::test(self)]
5672 fn test_defer_and_after_window_update(cx: &mut MutableAppContext) {
5673 struct View {
5674 render_count: usize,
5675 }
5676
5677 impl Entity for View {
5678 type Event = usize;
5679 }
5680
5681 impl super::View for View {
5682 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5683 post_inc(&mut self.render_count);
5684 Empty::new().boxed()
5685 }
5686
5687 fn ui_name() -> &'static str {
5688 "View"
5689 }
5690 }
5691
5692 let (_, view) = cx.add_window(Default::default(), |_| View { render_count: 0 });
5693 let called_defer = Rc::new(AtomicBool::new(false));
5694 let called_after_window_update = Rc::new(AtomicBool::new(false));
5695
5696 view.update(cx, |this, cx| {
5697 assert_eq!(this.render_count, 1);
5698 cx.defer({
5699 let called_defer = called_defer.clone();
5700 move |this, _| {
5701 assert_eq!(this.render_count, 1);
5702 called_defer.store(true, SeqCst);
5703 }
5704 });
5705 cx.after_window_update({
5706 let called_after_window_update = called_after_window_update.clone();
5707 move |this, cx| {
5708 assert_eq!(this.render_count, 2);
5709 called_after_window_update.store(true, SeqCst);
5710 cx.notify();
5711 }
5712 });
5713 assert!(!called_defer.load(SeqCst));
5714 assert!(!called_after_window_update.load(SeqCst));
5715 cx.notify();
5716 });
5717
5718 assert!(called_defer.load(SeqCst));
5719 assert!(called_after_window_update.load(SeqCst));
5720 assert_eq!(view.read(cx).render_count, 3);
5721 }
5722
5723 #[crate::test(self)]
5724 fn test_view_handles(cx: &mut MutableAppContext) {
5725 struct View {
5726 other: Option<ViewHandle<View>>,
5727 events: Vec<String>,
5728 }
5729
5730 impl Entity for View {
5731 type Event = usize;
5732 }
5733
5734 impl super::View for View {
5735 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5736 Empty::new().boxed()
5737 }
5738
5739 fn ui_name() -> &'static str {
5740 "View"
5741 }
5742 }
5743
5744 impl View {
5745 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
5746 if let Some(other) = other.as_ref() {
5747 cx.subscribe(other, |me, _, event, _| {
5748 me.events.push(format!("observed event {}", event));
5749 })
5750 .detach();
5751 }
5752 Self {
5753 other,
5754 events: Vec::new(),
5755 }
5756 }
5757 }
5758
5759 let (_, root_view) = cx.add_window(Default::default(), |cx| View::new(None, cx));
5760 let handle_1 = cx.add_view(&root_view, |cx| View::new(None, cx));
5761 let handle_2 = cx.add_view(&root_view, |cx| View::new(Some(handle_1.clone()), cx));
5762 assert_eq!(cx.cx.views.len(), 3);
5763
5764 handle_1.update(cx, |view, cx| {
5765 view.events.push("updated".into());
5766 cx.emit(1);
5767 cx.emit(2);
5768 });
5769 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5770 assert_eq!(
5771 handle_2.read(cx).events,
5772 vec![
5773 "observed event 1".to_string(),
5774 "observed event 2".to_string(),
5775 ]
5776 );
5777
5778 handle_2.update(cx, |view, _| {
5779 drop(handle_1);
5780 view.other.take();
5781 });
5782
5783 assert_eq!(cx.cx.views.len(), 2);
5784 assert!(cx.subscriptions.is_empty());
5785 assert!(cx.observations.is_empty());
5786 }
5787
5788 #[crate::test(self)]
5789 fn test_add_window(cx: &mut MutableAppContext) {
5790 struct View {
5791 mouse_down_count: Arc<AtomicUsize>,
5792 }
5793
5794 impl Entity for View {
5795 type Event = ();
5796 }
5797
5798 impl super::View for View {
5799 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
5800 enum Handler {}
5801 let mouse_down_count = self.mouse_down_count.clone();
5802 MouseEventHandler::<Handler>::new(0, cx, |_, _| Empty::new().boxed())
5803 .on_down(MouseButton::Left, move |_, _| {
5804 mouse_down_count.fetch_add(1, SeqCst);
5805 })
5806 .boxed()
5807 }
5808
5809 fn ui_name() -> &'static str {
5810 "View"
5811 }
5812 }
5813
5814 let mouse_down_count = Arc::new(AtomicUsize::new(0));
5815 let (window_id, _) = cx.add_window(Default::default(), |_| View {
5816 mouse_down_count: mouse_down_count.clone(),
5817 });
5818 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
5819 // Ensure window's root element is in a valid lifecycle state.
5820 presenter.borrow_mut().dispatch_event(
5821 Event::MouseDown(MouseButtonEvent {
5822 position: Default::default(),
5823 button: MouseButton::Left,
5824 modifiers: Default::default(),
5825 click_count: 1,
5826 }),
5827 false,
5828 cx,
5829 );
5830 assert_eq!(mouse_down_count.load(SeqCst), 1);
5831 }
5832
5833 #[crate::test(self)]
5834 fn test_entity_release_hooks(cx: &mut MutableAppContext) {
5835 struct Model {
5836 released: Rc<Cell<bool>>,
5837 }
5838
5839 struct View {
5840 released: Rc<Cell<bool>>,
5841 }
5842
5843 impl Entity for Model {
5844 type Event = ();
5845
5846 fn release(&mut self, _: &mut MutableAppContext) {
5847 self.released.set(true);
5848 }
5849 }
5850
5851 impl Entity for View {
5852 type Event = ();
5853
5854 fn release(&mut self, _: &mut MutableAppContext) {
5855 self.released.set(true);
5856 }
5857 }
5858
5859 impl super::View for View {
5860 fn ui_name() -> &'static str {
5861 "View"
5862 }
5863
5864 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5865 Empty::new().boxed()
5866 }
5867 }
5868
5869 let model_released = Rc::new(Cell::new(false));
5870 let model_release_observed = Rc::new(Cell::new(false));
5871 let view_released = Rc::new(Cell::new(false));
5872 let view_release_observed = Rc::new(Cell::new(false));
5873
5874 let model = cx.add_model(|_| Model {
5875 released: model_released.clone(),
5876 });
5877 let (window_id, view) = cx.add_window(Default::default(), |_| View {
5878 released: view_released.clone(),
5879 });
5880 assert!(!model_released.get());
5881 assert!(!view_released.get());
5882
5883 cx.observe_release(&model, {
5884 let model_release_observed = model_release_observed.clone();
5885 move |_, _| model_release_observed.set(true)
5886 })
5887 .detach();
5888 cx.observe_release(&view, {
5889 let view_release_observed = view_release_observed.clone();
5890 move |_, _| view_release_observed.set(true)
5891 })
5892 .detach();
5893
5894 cx.update(move |_| {
5895 drop(model);
5896 });
5897 assert!(model_released.get());
5898 assert!(model_release_observed.get());
5899
5900 drop(view);
5901 cx.remove_window(window_id);
5902 assert!(view_released.get());
5903 assert!(view_release_observed.get());
5904 }
5905
5906 #[crate::test(self)]
5907 fn test_view_events(cx: &mut MutableAppContext) {
5908 struct Model;
5909
5910 impl Entity for Model {
5911 type Event = String;
5912 }
5913
5914 let (_, handle_1) = cx.add_window(Default::default(), |_| TestView::default());
5915 let handle_2 = cx.add_view(&handle_1, |_| TestView::default());
5916 let handle_3 = cx.add_model(|_| Model);
5917
5918 handle_1.update(cx, |_, cx| {
5919 cx.subscribe(&handle_2, move |me, emitter, event, cx| {
5920 me.events.push(event.clone());
5921
5922 cx.subscribe(&emitter, |me, _, event, _| {
5923 me.events.push(format!("{event} from inner"));
5924 })
5925 .detach();
5926 })
5927 .detach();
5928
5929 cx.subscribe(&handle_3, |me, _, event, _| {
5930 me.events.push(event.clone());
5931 })
5932 .detach();
5933 });
5934
5935 handle_2.update(cx, |_, c| c.emit("7".into()));
5936 assert_eq!(handle_1.read(cx).events, vec!["7"]);
5937
5938 handle_2.update(cx, |_, c| c.emit("5".into()));
5939 assert_eq!(handle_1.read(cx).events, vec!["7", "5", "5 from inner"]);
5940
5941 handle_3.update(cx, |_, c| c.emit("9".into()));
5942 assert_eq!(
5943 handle_1.read(cx).events,
5944 vec!["7", "5", "5 from inner", "9"]
5945 );
5946 }
5947
5948 #[crate::test(self)]
5949 fn test_global_events(cx: &mut MutableAppContext) {
5950 #[derive(Clone, Debug, Eq, PartialEq)]
5951 struct GlobalEvent(u64);
5952
5953 let events = Rc::new(RefCell::new(Vec::new()));
5954 let first_subscription;
5955 let second_subscription;
5956
5957 {
5958 let events = events.clone();
5959 first_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
5960 events.borrow_mut().push(("First", e.clone()));
5961 });
5962 }
5963
5964 {
5965 let events = events.clone();
5966 second_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
5967 events.borrow_mut().push(("Second", e.clone()));
5968 });
5969 }
5970
5971 cx.update(|cx| {
5972 cx.emit_global(GlobalEvent(1));
5973 cx.emit_global(GlobalEvent(2));
5974 });
5975
5976 drop(first_subscription);
5977
5978 cx.update(|cx| {
5979 cx.emit_global(GlobalEvent(3));
5980 });
5981
5982 drop(second_subscription);
5983
5984 cx.update(|cx| {
5985 cx.emit_global(GlobalEvent(4));
5986 });
5987
5988 assert_eq!(
5989 &*events.borrow(),
5990 &[
5991 ("First", GlobalEvent(1)),
5992 ("Second", GlobalEvent(1)),
5993 ("First", GlobalEvent(2)),
5994 ("Second", GlobalEvent(2)),
5995 ("Second", GlobalEvent(3)),
5996 ]
5997 );
5998 }
5999
6000 #[crate::test(self)]
6001 fn test_global_events_emitted_before_subscription_in_same_update_cycle(
6002 cx: &mut MutableAppContext,
6003 ) {
6004 let events = Rc::new(RefCell::new(Vec::new()));
6005 cx.update(|cx| {
6006 {
6007 let events = events.clone();
6008 drop(cx.subscribe_global(move |_: &(), _| {
6009 events.borrow_mut().push("dropped before emit");
6010 }));
6011 }
6012
6013 {
6014 let events = events.clone();
6015 cx.subscribe_global(move |_: &(), _| {
6016 events.borrow_mut().push("before emit");
6017 })
6018 .detach();
6019 }
6020
6021 cx.emit_global(());
6022
6023 {
6024 let events = events.clone();
6025 cx.subscribe_global(move |_: &(), _| {
6026 events.borrow_mut().push("after emit");
6027 })
6028 .detach();
6029 }
6030 });
6031
6032 assert_eq!(*events.borrow(), ["before emit"]);
6033 }
6034
6035 #[crate::test(self)]
6036 fn test_global_nested_events(cx: &mut MutableAppContext) {
6037 #[derive(Clone, Debug, Eq, PartialEq)]
6038 struct GlobalEvent(u64);
6039
6040 let events = Rc::new(RefCell::new(Vec::new()));
6041
6042 {
6043 let events = events.clone();
6044 cx.subscribe_global(move |e: &GlobalEvent, cx| {
6045 events.borrow_mut().push(("Outer", e.clone()));
6046
6047 if e.0 == 1 {
6048 let events = events.clone();
6049 cx.subscribe_global(move |e: &GlobalEvent, _| {
6050 events.borrow_mut().push(("Inner", e.clone()));
6051 })
6052 .detach();
6053 }
6054 })
6055 .detach();
6056 }
6057
6058 cx.update(|cx| {
6059 cx.emit_global(GlobalEvent(1));
6060 cx.emit_global(GlobalEvent(2));
6061 cx.emit_global(GlobalEvent(3));
6062 });
6063 cx.update(|cx| {
6064 cx.emit_global(GlobalEvent(4));
6065 });
6066
6067 assert_eq!(
6068 &*events.borrow(),
6069 &[
6070 ("Outer", GlobalEvent(1)),
6071 ("Outer", GlobalEvent(2)),
6072 ("Outer", GlobalEvent(3)),
6073 ("Outer", GlobalEvent(4)),
6074 ("Inner", GlobalEvent(4)),
6075 ]
6076 );
6077 }
6078
6079 #[crate::test(self)]
6080 fn test_global(cx: &mut MutableAppContext) {
6081 type Global = usize;
6082
6083 let observation_count = Rc::new(RefCell::new(0));
6084 let subscription = cx.observe_global::<Global, _>({
6085 let observation_count = observation_count.clone();
6086 move |_| {
6087 *observation_count.borrow_mut() += 1;
6088 }
6089 });
6090
6091 assert!(!cx.has_global::<Global>());
6092 assert_eq!(cx.default_global::<Global>(), &0);
6093 assert_eq!(*observation_count.borrow(), 1);
6094 assert!(cx.has_global::<Global>());
6095 assert_eq!(
6096 cx.update_global::<Global, _, _>(|global, _| {
6097 *global = 1;
6098 "Update Result"
6099 }),
6100 "Update Result"
6101 );
6102 assert_eq!(*observation_count.borrow(), 2);
6103 assert_eq!(cx.global::<Global>(), &1);
6104
6105 drop(subscription);
6106 cx.update_global::<Global, _, _>(|global, _| {
6107 *global = 2;
6108 });
6109 assert_eq!(*observation_count.borrow(), 2);
6110
6111 type OtherGlobal = f32;
6112
6113 let observation_count = Rc::new(RefCell::new(0));
6114 cx.observe_global::<OtherGlobal, _>({
6115 let observation_count = observation_count.clone();
6116 move |_| {
6117 *observation_count.borrow_mut() += 1;
6118 }
6119 })
6120 .detach();
6121
6122 assert_eq!(
6123 cx.update_default_global::<OtherGlobal, _, _>(|global, _| {
6124 assert_eq!(global, &0.0);
6125 *global = 2.0;
6126 "Default update result"
6127 }),
6128 "Default update result"
6129 );
6130 assert_eq!(cx.global::<OtherGlobal>(), &2.0);
6131 assert_eq!(*observation_count.borrow(), 1);
6132 }
6133
6134 #[crate::test(self)]
6135 fn test_dropping_subscribers(cx: &mut MutableAppContext) {
6136 struct Model;
6137
6138 impl Entity for Model {
6139 type Event = ();
6140 }
6141
6142 let (_, root_view) = cx.add_window(Default::default(), |_| TestView::default());
6143 let observing_view = cx.add_view(&root_view, |_| TestView::default());
6144 let emitting_view = cx.add_view(&root_view, |_| TestView::default());
6145 let observing_model = cx.add_model(|_| Model);
6146 let observed_model = cx.add_model(|_| Model);
6147
6148 observing_view.update(cx, |_, cx| {
6149 cx.subscribe(&emitting_view, |_, _, _, _| {}).detach();
6150 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
6151 });
6152 observing_model.update(cx, |_, cx| {
6153 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
6154 });
6155
6156 cx.update(|_| {
6157 drop(observing_view);
6158 drop(observing_model);
6159 });
6160
6161 emitting_view.update(cx, |_, cx| cx.emit(Default::default()));
6162 observed_model.update(cx, |_, cx| cx.emit(()));
6163 }
6164
6165 #[crate::test(self)]
6166 fn test_view_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
6167 let (_, view) = cx.add_window::<TestView, _>(Default::default(), |cx| {
6168 drop(cx.subscribe(&cx.handle(), {
6169 move |this, _, _, _| this.events.push("dropped before flush".into())
6170 }));
6171 cx.subscribe(&cx.handle(), {
6172 move |this, _, _, _| this.events.push("before emit".into())
6173 })
6174 .detach();
6175 cx.emit("the event".into());
6176 cx.subscribe(&cx.handle(), {
6177 move |this, _, _, _| this.events.push("after emit".into())
6178 })
6179 .detach();
6180 TestView { events: Vec::new() }
6181 });
6182
6183 assert_eq!(view.read(cx).events, ["before emit"]);
6184 }
6185
6186 #[crate::test(self)]
6187 fn test_observe_and_notify_from_view(cx: &mut MutableAppContext) {
6188 #[derive(Default)]
6189 struct Model {
6190 state: String,
6191 }
6192
6193 impl Entity for Model {
6194 type Event = ();
6195 }
6196
6197 let (_, view) = cx.add_window(Default::default(), |_| TestView::default());
6198 let model = cx.add_model(|_| Model {
6199 state: "old-state".into(),
6200 });
6201
6202 view.update(cx, |_, c| {
6203 c.observe(&model, |me, observed, c| {
6204 me.events.push(observed.read(c).state.clone())
6205 })
6206 .detach();
6207 });
6208
6209 model.update(cx, |model, cx| {
6210 model.state = "new-state".into();
6211 cx.notify();
6212 });
6213 assert_eq!(view.read(cx).events, vec!["new-state"]);
6214 }
6215
6216 #[crate::test(self)]
6217 fn test_view_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
6218 let (_, view) = cx.add_window::<TestView, _>(Default::default(), |cx| {
6219 drop(cx.observe(&cx.handle(), {
6220 move |this, _, _| this.events.push("dropped before flush".into())
6221 }));
6222 cx.observe(&cx.handle(), {
6223 move |this, _, _| this.events.push("before notify".into())
6224 })
6225 .detach();
6226 cx.notify();
6227 cx.observe(&cx.handle(), {
6228 move |this, _, _| this.events.push("after notify".into())
6229 })
6230 .detach();
6231 TestView { events: Vec::new() }
6232 });
6233
6234 assert_eq!(view.read(cx).events, ["before notify"]);
6235 }
6236
6237 #[crate::test(self)]
6238 fn test_notify_and_drop_observe_subscription_in_same_update_cycle(cx: &mut MutableAppContext) {
6239 struct Model;
6240 impl Entity for Model {
6241 type Event = ();
6242 }
6243
6244 let model = cx.add_model(|_| Model);
6245 let (_, view) = cx.add_window(Default::default(), |_| TestView::default());
6246
6247 view.update(cx, |_, cx| {
6248 model.update(cx, |_, cx| cx.notify());
6249 drop(cx.observe(&model, move |this, _, _| {
6250 this.events.push("model notified".into());
6251 }));
6252 model.update(cx, |_, cx| cx.notify());
6253 });
6254
6255 for _ in 0..3 {
6256 model.update(cx, |_, cx| cx.notify());
6257 }
6258
6259 assert_eq!(view.read(cx).events, Vec::<String>::new());
6260 }
6261
6262 #[crate::test(self)]
6263 fn test_dropping_observers(cx: &mut MutableAppContext) {
6264 struct Model;
6265
6266 impl Entity for Model {
6267 type Event = ();
6268 }
6269
6270 let (_, root_view) = cx.add_window(Default::default(), |_| TestView::default());
6271 let observing_view = cx.add_view(root_view, |_| TestView::default());
6272 let observing_model = cx.add_model(|_| Model);
6273 let observed_model = cx.add_model(|_| Model);
6274
6275 observing_view.update(cx, |_, cx| {
6276 cx.observe(&observed_model, |_, _, _| {}).detach();
6277 });
6278 observing_model.update(cx, |_, cx| {
6279 cx.observe(&observed_model, |_, _, _| {}).detach();
6280 });
6281
6282 cx.update(|_| {
6283 drop(observing_view);
6284 drop(observing_model);
6285 });
6286
6287 observed_model.update(cx, |_, cx| cx.notify());
6288 }
6289
6290 #[crate::test(self)]
6291 fn test_dropping_subscriptions_during_callback(cx: &mut MutableAppContext) {
6292 struct Model;
6293
6294 impl Entity for Model {
6295 type Event = u64;
6296 }
6297
6298 // Events
6299 let observing_model = cx.add_model(|_| Model);
6300 let observed_model = cx.add_model(|_| Model);
6301
6302 let events = Rc::new(RefCell::new(Vec::new()));
6303
6304 observing_model.update(cx, |_, cx| {
6305 let events = events.clone();
6306 let subscription = Rc::new(RefCell::new(None));
6307 *subscription.borrow_mut() = Some(cx.subscribe(&observed_model, {
6308 let subscription = subscription.clone();
6309 move |_, _, e, _| {
6310 subscription.borrow_mut().take();
6311 events.borrow_mut().push(*e);
6312 }
6313 }));
6314 });
6315
6316 observed_model.update(cx, |_, cx| {
6317 cx.emit(1);
6318 cx.emit(2);
6319 });
6320
6321 assert_eq!(*events.borrow(), [1]);
6322
6323 // Global Events
6324 #[derive(Clone, Debug, Eq, PartialEq)]
6325 struct GlobalEvent(u64);
6326
6327 let events = Rc::new(RefCell::new(Vec::new()));
6328
6329 {
6330 let events = events.clone();
6331 let subscription = Rc::new(RefCell::new(None));
6332 *subscription.borrow_mut() = Some(cx.subscribe_global({
6333 let subscription = subscription.clone();
6334 move |e: &GlobalEvent, _| {
6335 subscription.borrow_mut().take();
6336 events.borrow_mut().push(e.clone());
6337 }
6338 }));
6339 }
6340
6341 cx.update(|cx| {
6342 cx.emit_global(GlobalEvent(1));
6343 cx.emit_global(GlobalEvent(2));
6344 });
6345
6346 assert_eq!(*events.borrow(), [GlobalEvent(1)]);
6347
6348 // Model Observation
6349 let observing_model = cx.add_model(|_| Model);
6350 let observed_model = cx.add_model(|_| Model);
6351
6352 let observation_count = Rc::new(RefCell::new(0));
6353
6354 observing_model.update(cx, |_, cx| {
6355 let observation_count = observation_count.clone();
6356 let subscription = Rc::new(RefCell::new(None));
6357 *subscription.borrow_mut() = Some(cx.observe(&observed_model, {
6358 let subscription = subscription.clone();
6359 move |_, _, _| {
6360 subscription.borrow_mut().take();
6361 *observation_count.borrow_mut() += 1;
6362 }
6363 }));
6364 });
6365
6366 observed_model.update(cx, |_, cx| {
6367 cx.notify();
6368 });
6369
6370 observed_model.update(cx, |_, cx| {
6371 cx.notify();
6372 });
6373
6374 assert_eq!(*observation_count.borrow(), 1);
6375
6376 // View Observation
6377 struct View;
6378
6379 impl Entity for View {
6380 type Event = ();
6381 }
6382
6383 impl super::View for View {
6384 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6385 Empty::new().boxed()
6386 }
6387
6388 fn ui_name() -> &'static str {
6389 "View"
6390 }
6391 }
6392
6393 let (_, root_view) = cx.add_window(Default::default(), |_| View);
6394 let observing_view = cx.add_view(&root_view, |_| View);
6395 let observed_view = cx.add_view(&root_view, |_| View);
6396
6397 let observation_count = Rc::new(RefCell::new(0));
6398 observing_view.update(cx, |_, cx| {
6399 let observation_count = observation_count.clone();
6400 let subscription = Rc::new(RefCell::new(None));
6401 *subscription.borrow_mut() = Some(cx.observe(&observed_view, {
6402 let subscription = subscription.clone();
6403 move |_, _, _| {
6404 subscription.borrow_mut().take();
6405 *observation_count.borrow_mut() += 1;
6406 }
6407 }));
6408 });
6409
6410 observed_view.update(cx, |_, cx| {
6411 cx.notify();
6412 });
6413
6414 observed_view.update(cx, |_, cx| {
6415 cx.notify();
6416 });
6417
6418 assert_eq!(*observation_count.borrow(), 1);
6419
6420 // Global Observation
6421 let observation_count = Rc::new(RefCell::new(0));
6422 let subscription = Rc::new(RefCell::new(None));
6423 *subscription.borrow_mut() = Some(cx.observe_global::<(), _>({
6424 let observation_count = observation_count.clone();
6425 let subscription = subscription.clone();
6426 move |_| {
6427 subscription.borrow_mut().take();
6428 *observation_count.borrow_mut() += 1;
6429 }
6430 }));
6431
6432 cx.default_global::<()>();
6433 cx.set_global(());
6434 assert_eq!(*observation_count.borrow(), 1);
6435 }
6436
6437 #[crate::test(self)]
6438 fn test_focus(cx: &mut MutableAppContext) {
6439 struct View {
6440 name: String,
6441 events: Arc<Mutex<Vec<String>>>,
6442 }
6443
6444 impl Entity for View {
6445 type Event = ();
6446 }
6447
6448 impl super::View for View {
6449 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6450 Empty::new().boxed()
6451 }
6452
6453 fn ui_name() -> &'static str {
6454 "View"
6455 }
6456
6457 fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
6458 if cx.handle().id() == focused.id() {
6459 self.events.lock().push(format!("{} focused", &self.name));
6460 }
6461 }
6462
6463 fn focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
6464 if cx.handle().id() == blurred.id() {
6465 self.events.lock().push(format!("{} blurred", &self.name));
6466 }
6467 }
6468 }
6469
6470 let view_events: Arc<Mutex<Vec<String>>> = Default::default();
6471 let (_, view_1) = cx.add_window(Default::default(), |_| View {
6472 events: view_events.clone(),
6473 name: "view 1".to_string(),
6474 });
6475 let view_2 = cx.add_view(&view_1, |_| View {
6476 events: view_events.clone(),
6477 name: "view 2".to_string(),
6478 });
6479
6480 let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
6481 view_1.update(cx, |_, cx| {
6482 cx.observe_focus(&view_2, {
6483 let observed_events = observed_events.clone();
6484 move |this, view, focused, cx| {
6485 let label = if focused { "focus" } else { "blur" };
6486 observed_events.lock().push(format!(
6487 "{} observed {}'s {}",
6488 this.name,
6489 view.read(cx).name,
6490 label
6491 ))
6492 }
6493 })
6494 .detach();
6495 });
6496 view_2.update(cx, |_, cx| {
6497 cx.observe_focus(&view_1, {
6498 let observed_events = observed_events.clone();
6499 move |this, view, focused, cx| {
6500 let label = if focused { "focus" } else { "blur" };
6501 observed_events.lock().push(format!(
6502 "{} observed {}'s {}",
6503 this.name,
6504 view.read(cx).name,
6505 label
6506 ))
6507 }
6508 })
6509 .detach();
6510 });
6511 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
6512 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
6513
6514 view_1.update(cx, |_, cx| {
6515 // Ensure focus events are sent for all intermediate focuses
6516 cx.focus(&view_2);
6517 cx.focus(&view_1);
6518 cx.focus(&view_2);
6519 });
6520 assert!(cx.is_child_focused(view_1.clone()));
6521 assert!(!cx.is_child_focused(view_2.clone()));
6522 assert_eq!(
6523 mem::take(&mut *view_events.lock()),
6524 [
6525 "view 1 blurred",
6526 "view 2 focused",
6527 "view 2 blurred",
6528 "view 1 focused",
6529 "view 1 blurred",
6530 "view 2 focused"
6531 ],
6532 );
6533 assert_eq!(
6534 mem::take(&mut *observed_events.lock()),
6535 [
6536 "view 2 observed view 1's blur",
6537 "view 1 observed view 2's focus",
6538 "view 1 observed view 2's blur",
6539 "view 2 observed view 1's focus",
6540 "view 2 observed view 1's blur",
6541 "view 1 observed view 2's focus"
6542 ]
6543 );
6544
6545 view_1.update(cx, |_, cx| cx.focus(&view_1));
6546 assert!(!cx.is_child_focused(view_1.clone()));
6547 assert!(!cx.is_child_focused(view_2.clone()));
6548 assert_eq!(
6549 mem::take(&mut *view_events.lock()),
6550 ["view 2 blurred", "view 1 focused"],
6551 );
6552 assert_eq!(
6553 mem::take(&mut *observed_events.lock()),
6554 [
6555 "view 1 observed view 2's blur",
6556 "view 2 observed view 1's focus"
6557 ]
6558 );
6559
6560 view_1.update(cx, |_, cx| cx.focus(&view_2));
6561 assert_eq!(
6562 mem::take(&mut *view_events.lock()),
6563 ["view 1 blurred", "view 2 focused"],
6564 );
6565 assert_eq!(
6566 mem::take(&mut *observed_events.lock()),
6567 [
6568 "view 2 observed view 1's blur",
6569 "view 1 observed view 2's focus"
6570 ]
6571 );
6572
6573 view_1.update(cx, |_, _| drop(view_2));
6574 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
6575 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
6576 }
6577
6578 #[crate::test(self)]
6579 fn test_deserialize_actions(cx: &mut MutableAppContext) {
6580 #[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
6581 pub struct ComplexAction {
6582 arg: String,
6583 count: usize,
6584 }
6585
6586 actions!(test::something, [SimpleAction]);
6587 impl_actions!(test::something, [ComplexAction]);
6588
6589 cx.add_global_action(move |_: &SimpleAction, _: &mut MutableAppContext| {});
6590 cx.add_global_action(move |_: &ComplexAction, _: &mut MutableAppContext| {});
6591
6592 let action1 = cx
6593 .deserialize_action(
6594 "test::something::ComplexAction",
6595 Some(r#"{"arg": "a", "count": 5}"#),
6596 )
6597 .unwrap();
6598 let action2 = cx
6599 .deserialize_action("test::something::SimpleAction", None)
6600 .unwrap();
6601 assert_eq!(
6602 action1.as_any().downcast_ref::<ComplexAction>().unwrap(),
6603 &ComplexAction {
6604 arg: "a".to_string(),
6605 count: 5,
6606 }
6607 );
6608 assert_eq!(
6609 action2.as_any().downcast_ref::<SimpleAction>().unwrap(),
6610 &SimpleAction
6611 );
6612 }
6613
6614 #[crate::test(self)]
6615 fn test_dispatch_action(cx: &mut MutableAppContext) {
6616 struct ViewA {
6617 id: usize,
6618 }
6619
6620 impl Entity for ViewA {
6621 type Event = ();
6622 }
6623
6624 impl View for ViewA {
6625 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6626 Empty::new().boxed()
6627 }
6628
6629 fn ui_name() -> &'static str {
6630 "View"
6631 }
6632 }
6633
6634 struct ViewB {
6635 id: usize,
6636 }
6637
6638 impl Entity for ViewB {
6639 type Event = ();
6640 }
6641
6642 impl View for ViewB {
6643 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6644 Empty::new().boxed()
6645 }
6646
6647 fn ui_name() -> &'static str {
6648 "View"
6649 }
6650 }
6651
6652 #[derive(Clone, Default, Deserialize, PartialEq)]
6653 pub struct Action(pub String);
6654
6655 impl_actions!(test, [Action]);
6656
6657 let actions = Rc::new(RefCell::new(Vec::new()));
6658
6659 cx.add_global_action({
6660 let actions = actions.clone();
6661 move |_: &Action, _: &mut MutableAppContext| {
6662 actions.borrow_mut().push("global".to_string());
6663 }
6664 });
6665
6666 cx.add_action({
6667 let actions = actions.clone();
6668 move |view: &mut ViewA, action: &Action, cx| {
6669 assert_eq!(action.0, "bar");
6670 cx.propagate_action();
6671 actions.borrow_mut().push(format!("{} a", view.id));
6672 }
6673 });
6674
6675 cx.add_action({
6676 let actions = actions.clone();
6677 move |view: &mut ViewA, _: &Action, cx| {
6678 if view.id != 1 {
6679 cx.add_view(|cx| {
6680 cx.propagate_action(); // Still works on a nested ViewContext
6681 ViewB { id: 5 }
6682 });
6683 }
6684 actions.borrow_mut().push(format!("{} b", view.id));
6685 }
6686 });
6687
6688 cx.add_action({
6689 let actions = actions.clone();
6690 move |view: &mut ViewB, _: &Action, cx| {
6691 cx.propagate_action();
6692 actions.borrow_mut().push(format!("{} c", view.id));
6693 }
6694 });
6695
6696 cx.add_action({
6697 let actions = actions.clone();
6698 move |view: &mut ViewB, _: &Action, cx| {
6699 cx.propagate_action();
6700 actions.borrow_mut().push(format!("{} d", view.id));
6701 }
6702 });
6703
6704 cx.capture_action({
6705 let actions = actions.clone();
6706 move |view: &mut ViewA, _: &Action, cx| {
6707 cx.propagate_action();
6708 actions.borrow_mut().push(format!("{} capture", view.id));
6709 }
6710 });
6711
6712 let observed_actions = Rc::new(RefCell::new(Vec::new()));
6713 cx.observe_actions({
6714 let observed_actions = observed_actions.clone();
6715 move |action_id, _| observed_actions.borrow_mut().push(action_id)
6716 })
6717 .detach();
6718
6719 let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 });
6720 let view_2 = cx.add_view(&view_1, |_| ViewB { id: 2 });
6721 let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 });
6722 let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 });
6723
6724 cx.handle_dispatch_action_from_effect(
6725 window_id,
6726 Some(view_4.id()),
6727 &Action("bar".to_string()),
6728 );
6729
6730 assert_eq!(
6731 *actions.borrow(),
6732 vec![
6733 "1 capture",
6734 "3 capture",
6735 "4 d",
6736 "4 c",
6737 "3 b",
6738 "3 a",
6739 "2 d",
6740 "2 c",
6741 "1 b"
6742 ]
6743 );
6744 assert_eq!(*observed_actions.borrow(), [Action::default().id()]);
6745
6746 // Remove view_1, which doesn't propagate the action
6747
6748 let (window_id, view_2) = cx.add_window(Default::default(), |_| ViewB { id: 2 });
6749 let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 });
6750 let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 });
6751
6752 actions.borrow_mut().clear();
6753 cx.handle_dispatch_action_from_effect(
6754 window_id,
6755 Some(view_4.id()),
6756 &Action("bar".to_string()),
6757 );
6758
6759 assert_eq!(
6760 *actions.borrow(),
6761 vec![
6762 "3 capture",
6763 "4 d",
6764 "4 c",
6765 "3 b",
6766 "3 a",
6767 "2 d",
6768 "2 c",
6769 "global"
6770 ]
6771 );
6772 assert_eq!(
6773 *observed_actions.borrow(),
6774 [Action::default().id(), Action::default().id()]
6775 );
6776 }
6777
6778 #[crate::test(self)]
6779 fn test_dispatch_keystroke(cx: &mut MutableAppContext) {
6780 #[derive(Clone, Deserialize, PartialEq)]
6781 pub struct Action(String);
6782
6783 impl_actions!(test, [Action]);
6784
6785 struct View {
6786 id: usize,
6787 keymap_context: KeymapContext,
6788 }
6789
6790 impl Entity for View {
6791 type Event = ();
6792 }
6793
6794 impl super::View for View {
6795 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6796 Empty::new().boxed()
6797 }
6798
6799 fn ui_name() -> &'static str {
6800 "View"
6801 }
6802
6803 fn keymap_context(&self, _: &AppContext) -> KeymapContext {
6804 self.keymap_context.clone()
6805 }
6806 }
6807
6808 impl View {
6809 fn new(id: usize) -> Self {
6810 View {
6811 id,
6812 keymap_context: KeymapContext::default(),
6813 }
6814 }
6815 }
6816
6817 let mut view_1 = View::new(1);
6818 let mut view_2 = View::new(2);
6819 let mut view_3 = View::new(3);
6820 view_1.keymap_context.set.insert("a".into());
6821 view_2.keymap_context.set.insert("a".into());
6822 view_2.keymap_context.set.insert("b".into());
6823 view_3.keymap_context.set.insert("a".into());
6824 view_3.keymap_context.set.insert("b".into());
6825 view_3.keymap_context.set.insert("c".into());
6826
6827 let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1);
6828 let view_2 = cx.add_view(&view_1, |_| view_2);
6829 let _view_3 = cx.add_view(&view_2, |cx| {
6830 cx.focus_self();
6831 view_3
6832 });
6833
6834 // This binding only dispatches an action on view 2 because that view will have
6835 // "a" and "b" in its context, but not "c".
6836 cx.add_bindings(vec![Binding::new(
6837 "a",
6838 Action("a".to_string()),
6839 Some("a && b && !c"),
6840 )]);
6841
6842 cx.add_bindings(vec![Binding::new("b", Action("b".to_string()), None)]);
6843
6844 // This binding only dispatches an action on views 2 and 3, because they have
6845 // a parent view with a in its context
6846 cx.add_bindings(vec![Binding::new(
6847 "c",
6848 Action("c".to_string()),
6849 Some("b > c"),
6850 )]);
6851
6852 // This binding only dispatches an action on view 2, because they have
6853 // a parent view with a in its context
6854 cx.add_bindings(vec![Binding::new(
6855 "d",
6856 Action("d".to_string()),
6857 Some("a && !b > b"),
6858 )]);
6859
6860 let actions = Rc::new(RefCell::new(Vec::new()));
6861 cx.add_action({
6862 let actions = actions.clone();
6863 move |view: &mut View, action: &Action, cx| {
6864 actions
6865 .borrow_mut()
6866 .push(format!("{} {}", view.id, action.0));
6867
6868 if action.0 == "b" {
6869 cx.propagate_action();
6870 }
6871 }
6872 });
6873
6874 cx.add_global_action({
6875 let actions = actions.clone();
6876 move |action: &Action, _| {
6877 actions.borrow_mut().push(format!("global {}", action.0));
6878 }
6879 });
6880
6881 cx.dispatch_keystroke(window_id, &Keystroke::parse("a").unwrap());
6882 assert_eq!(&*actions.borrow(), &["2 a"]);
6883 actions.borrow_mut().clear();
6884
6885 cx.dispatch_keystroke(window_id, &Keystroke::parse("b").unwrap());
6886 assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
6887 actions.borrow_mut().clear();
6888
6889 cx.dispatch_keystroke(window_id, &Keystroke::parse("c").unwrap());
6890 assert_eq!(&*actions.borrow(), &["3 c"]);
6891 actions.borrow_mut().clear();
6892
6893 cx.dispatch_keystroke(window_id, &Keystroke::parse("d").unwrap());
6894 assert_eq!(&*actions.borrow(), &["2 d"]);
6895 actions.borrow_mut().clear();
6896 }
6897
6898 #[crate::test(self)]
6899 async fn test_model_condition(cx: &mut TestAppContext) {
6900 struct Counter(usize);
6901
6902 impl super::Entity for Counter {
6903 type Event = ();
6904 }
6905
6906 impl Counter {
6907 fn inc(&mut self, cx: &mut ModelContext<Self>) {
6908 self.0 += 1;
6909 cx.notify();
6910 }
6911 }
6912
6913 let model = cx.add_model(|_| Counter(0));
6914
6915 let condition1 = model.condition(cx, |model, _| model.0 == 2);
6916 let condition2 = model.condition(cx, |model, _| model.0 == 3);
6917 smol::pin!(condition1, condition2);
6918
6919 model.update(cx, |model, cx| model.inc(cx));
6920 assert_eq!(poll_once(&mut condition1).await, None);
6921 assert_eq!(poll_once(&mut condition2).await, None);
6922
6923 model.update(cx, |model, cx| model.inc(cx));
6924 assert_eq!(poll_once(&mut condition1).await, Some(()));
6925 assert_eq!(poll_once(&mut condition2).await, None);
6926
6927 model.update(cx, |model, cx| model.inc(cx));
6928 assert_eq!(poll_once(&mut condition2).await, Some(()));
6929
6930 model.update(cx, |_, cx| cx.notify());
6931 }
6932
6933 #[crate::test(self)]
6934 #[should_panic]
6935 async fn test_model_condition_timeout(cx: &mut TestAppContext) {
6936 struct Model;
6937
6938 impl super::Entity for Model {
6939 type Event = ();
6940 }
6941
6942 let model = cx.add_model(|_| Model);
6943 model.condition(cx, |_, _| false).await;
6944 }
6945
6946 #[crate::test(self)]
6947 #[should_panic(expected = "model dropped with pending condition")]
6948 async fn test_model_condition_panic_on_drop(cx: &mut TestAppContext) {
6949 struct Model;
6950
6951 impl super::Entity for Model {
6952 type Event = ();
6953 }
6954
6955 let model = cx.add_model(|_| Model);
6956 let condition = model.condition(cx, |_, _| false);
6957 cx.update(|_| drop(model));
6958 condition.await;
6959 }
6960
6961 #[crate::test(self)]
6962 async fn test_view_condition(cx: &mut TestAppContext) {
6963 struct Counter(usize);
6964
6965 impl super::Entity for Counter {
6966 type Event = ();
6967 }
6968
6969 impl super::View for Counter {
6970 fn ui_name() -> &'static str {
6971 "test view"
6972 }
6973
6974 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6975 Empty::new().boxed()
6976 }
6977 }
6978
6979 impl Counter {
6980 fn inc(&mut self, cx: &mut ViewContext<Self>) {
6981 self.0 += 1;
6982 cx.notify();
6983 }
6984 }
6985
6986 let (_, view) = cx.add_window(|_| Counter(0));
6987
6988 let condition1 = view.condition(cx, |view, _| view.0 == 2);
6989 let condition2 = view.condition(cx, |view, _| view.0 == 3);
6990 smol::pin!(condition1, condition2);
6991
6992 view.update(cx, |view, cx| view.inc(cx));
6993 assert_eq!(poll_once(&mut condition1).await, None);
6994 assert_eq!(poll_once(&mut condition2).await, None);
6995
6996 view.update(cx, |view, cx| view.inc(cx));
6997 assert_eq!(poll_once(&mut condition1).await, Some(()));
6998 assert_eq!(poll_once(&mut condition2).await, None);
6999
7000 view.update(cx, |view, cx| view.inc(cx));
7001 assert_eq!(poll_once(&mut condition2).await, Some(()));
7002 view.update(cx, |_, cx| cx.notify());
7003 }
7004
7005 #[crate::test(self)]
7006 #[should_panic]
7007 async fn test_view_condition_timeout(cx: &mut TestAppContext) {
7008 let (_, view) = cx.add_window(|_| TestView::default());
7009 view.condition(cx, |_, _| false).await;
7010 }
7011
7012 #[crate::test(self)]
7013 #[should_panic(expected = "view dropped with pending condition")]
7014 async fn test_view_condition_panic_on_drop(cx: &mut TestAppContext) {
7015 let (_, root_view) = cx.add_window(|_| TestView::default());
7016 let view = cx.add_view(&root_view, |_| TestView::default());
7017
7018 let condition = view.condition(cx, |_, _| false);
7019 cx.update(|_| drop(view));
7020 condition.await;
7021 }
7022
7023 #[crate::test(self)]
7024 fn test_refresh_windows(cx: &mut MutableAppContext) {
7025 struct View(usize);
7026
7027 impl super::Entity for View {
7028 type Event = ();
7029 }
7030
7031 impl super::View for View {
7032 fn ui_name() -> &'static str {
7033 "test view"
7034 }
7035
7036 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7037 Empty::new().named(format!("render count: {}", post_inc(&mut self.0)))
7038 }
7039 }
7040
7041 let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0));
7042 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
7043
7044 assert_eq!(
7045 presenter.borrow().rendered_views[&root_view.id()].name(),
7046 Some("render count: 0")
7047 );
7048
7049 let view = cx.add_view(&root_view, |cx| {
7050 cx.refresh_windows();
7051 View(0)
7052 });
7053
7054 assert_eq!(
7055 presenter.borrow().rendered_views[&root_view.id()].name(),
7056 Some("render count: 1")
7057 );
7058 assert_eq!(
7059 presenter.borrow().rendered_views[&view.id()].name(),
7060 Some("render count: 0")
7061 );
7062
7063 cx.update(|cx| cx.refresh_windows());
7064 assert_eq!(
7065 presenter.borrow().rendered_views[&root_view.id()].name(),
7066 Some("render count: 2")
7067 );
7068 assert_eq!(
7069 presenter.borrow().rendered_views[&view.id()].name(),
7070 Some("render count: 1")
7071 );
7072
7073 cx.update(|cx| {
7074 cx.refresh_windows();
7075 drop(view);
7076 });
7077 assert_eq!(
7078 presenter.borrow().rendered_views[&root_view.id()].name(),
7079 Some("render count: 3")
7080 );
7081 assert_eq!(presenter.borrow().rendered_views.len(), 1);
7082 }
7083
7084 #[crate::test(self)]
7085 async fn test_window_activation(cx: &mut TestAppContext) {
7086 struct View(&'static str);
7087
7088 impl super::Entity for View {
7089 type Event = ();
7090 }
7091
7092 impl super::View for View {
7093 fn ui_name() -> &'static str {
7094 "test view"
7095 }
7096
7097 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7098 Empty::new().boxed()
7099 }
7100 }
7101
7102 let events = Rc::new(RefCell::new(Vec::new()));
7103 let (window_1, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7104 cx.observe_window_activation({
7105 let events = events.clone();
7106 move |this, active, _| events.borrow_mut().push((this.0, active))
7107 })
7108 .detach();
7109 View("window 1")
7110 });
7111 assert_eq!(mem::take(&mut *events.borrow_mut()), [("window 1", true)]);
7112
7113 let (window_2, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7114 cx.observe_window_activation({
7115 let events = events.clone();
7116 move |this, active, _| events.borrow_mut().push((this.0, active))
7117 })
7118 .detach();
7119 View("window 2")
7120 });
7121 assert_eq!(
7122 mem::take(&mut *events.borrow_mut()),
7123 [("window 1", false), ("window 2", true)]
7124 );
7125
7126 let (window_3, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7127 cx.observe_window_activation({
7128 let events = events.clone();
7129 move |this, active, _| events.borrow_mut().push((this.0, active))
7130 })
7131 .detach();
7132 View("window 3")
7133 });
7134 assert_eq!(
7135 mem::take(&mut *events.borrow_mut()),
7136 [("window 2", false), ("window 3", true)]
7137 );
7138
7139 cx.simulate_window_activation(Some(window_2));
7140 assert_eq!(
7141 mem::take(&mut *events.borrow_mut()),
7142 [("window 3", false), ("window 2", true)]
7143 );
7144
7145 cx.simulate_window_activation(Some(window_1));
7146 assert_eq!(
7147 mem::take(&mut *events.borrow_mut()),
7148 [("window 2", false), ("window 1", true)]
7149 );
7150
7151 cx.simulate_window_activation(Some(window_3));
7152 assert_eq!(
7153 mem::take(&mut *events.borrow_mut()),
7154 [("window 1", false), ("window 3", true)]
7155 );
7156
7157 cx.simulate_window_activation(Some(window_3));
7158 assert_eq!(mem::take(&mut *events.borrow_mut()), []);
7159 }
7160
7161 #[crate::test(self)]
7162 fn test_child_view(cx: &mut MutableAppContext) {
7163 struct Child {
7164 rendered: Rc<Cell<bool>>,
7165 dropped: Rc<Cell<bool>>,
7166 }
7167
7168 impl super::Entity for Child {
7169 type Event = ();
7170 }
7171
7172 impl super::View for Child {
7173 fn ui_name() -> &'static str {
7174 "child view"
7175 }
7176
7177 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7178 self.rendered.set(true);
7179 Empty::new().boxed()
7180 }
7181 }
7182
7183 impl Drop for Child {
7184 fn drop(&mut self) {
7185 self.dropped.set(true);
7186 }
7187 }
7188
7189 struct Parent {
7190 child: Option<ViewHandle<Child>>,
7191 }
7192
7193 impl super::Entity for Parent {
7194 type Event = ();
7195 }
7196
7197 impl super::View for Parent {
7198 fn ui_name() -> &'static str {
7199 "parent view"
7200 }
7201
7202 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
7203 if let Some(child) = self.child.as_ref() {
7204 ChildView::new(child, cx).boxed()
7205 } else {
7206 Empty::new().boxed()
7207 }
7208 }
7209 }
7210
7211 let child_rendered = Rc::new(Cell::new(false));
7212 let child_dropped = Rc::new(Cell::new(false));
7213 let (_, root_view) = cx.add_window(Default::default(), |cx| Parent {
7214 child: Some(cx.add_view(|_| Child {
7215 rendered: child_rendered.clone(),
7216 dropped: child_dropped.clone(),
7217 })),
7218 });
7219 assert!(child_rendered.take());
7220 assert!(!child_dropped.take());
7221
7222 root_view.update(cx, |view, cx| {
7223 view.child.take();
7224 cx.notify();
7225 });
7226 assert!(!child_rendered.take());
7227 assert!(child_dropped.take());
7228 }
7229
7230 #[derive(Default)]
7231 struct TestView {
7232 events: Vec<String>,
7233 }
7234
7235 impl Entity for TestView {
7236 type Event = String;
7237 }
7238
7239 impl View for TestView {
7240 fn ui_name() -> &'static str {
7241 "TestView"
7242 }
7243
7244 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7245 Empty::new().boxed()
7246 }
7247 }
7248}