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) -> Option<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 if let Some(uuid) = this.window_display_uuid(window_id) {
2379 let bounds = this.window_bounds(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
2386 Some(())
2387 });
2388 }
2389
2390 fn handle_keystroke_effect(
2391 &mut self,
2392 window_id: usize,
2393 keystroke: Keystroke,
2394 handled_by: Option<Box<dyn Action>>,
2395 result: MatchResult,
2396 ) {
2397 self.update(|this| {
2398 let mut observations = this.keystroke_observations.clone();
2399 observations.emit(window_id, this, {
2400 move |callback, this| callback(&keystroke, &result, handled_by.as_ref(), this)
2401 });
2402 });
2403 }
2404
2405 fn handle_window_activation_effect(&mut self, window_id: usize, active: bool) {
2406 //Short circuit evaluation if we're already g2g
2407 if self
2408 .cx
2409 .windows
2410 .get(&window_id)
2411 .map(|w| w.is_active == active)
2412 .unwrap_or(false)
2413 {
2414 return;
2415 }
2416
2417 self.update(|this| {
2418 let window = this.cx.windows.get_mut(&window_id)?;
2419 window.is_active = active;
2420
2421 //Handle focus
2422 let focused_id = window.focused_view_id?;
2423 for view_id in this.ancestors(window_id, focused_id).collect::<Vec<_>>() {
2424 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
2425 if active {
2426 view.focus_in(this, window_id, view_id, focused_id);
2427 } else {
2428 view.focus_out(this, window_id, view_id, focused_id);
2429 }
2430 this.cx.views.insert((window_id, view_id), view);
2431 }
2432 }
2433
2434 let mut observations = this.window_activation_observations.clone();
2435 observations.emit(window_id, this, |callback, this| callback(active, this));
2436
2437 Some(())
2438 });
2439 }
2440
2441 fn handle_focus_effect(&mut self, window_id: usize, focused_id: Option<usize>) {
2442 if self
2443 .cx
2444 .windows
2445 .get(&window_id)
2446 .map(|w| w.focused_view_id)
2447 .map_or(false, |cur_focused| cur_focused == focused_id)
2448 {
2449 return;
2450 }
2451
2452 self.update(|this| {
2453 let blurred_id = this.cx.windows.get_mut(&window_id).and_then(|window| {
2454 let blurred_id = window.focused_view_id;
2455 window.focused_view_id = focused_id;
2456 blurred_id
2457 });
2458
2459 let blurred_parents = blurred_id
2460 .map(|blurred_id| this.ancestors(window_id, blurred_id).collect::<Vec<_>>())
2461 .unwrap_or_default();
2462 let focused_parents = focused_id
2463 .map(|focused_id| this.ancestors(window_id, focused_id).collect::<Vec<_>>())
2464 .unwrap_or_default();
2465
2466 if let Some(blurred_id) = blurred_id {
2467 for view_id in blurred_parents.iter().copied() {
2468 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
2469 view.focus_out(this, window_id, view_id, blurred_id);
2470 this.cx.views.insert((window_id, view_id), view);
2471 }
2472 }
2473
2474 let mut subscriptions = this.focus_observations.clone();
2475 subscriptions.emit(blurred_id, this, |callback, this| callback(false, this));
2476 }
2477
2478 if let Some(focused_id) = focused_id {
2479 for view_id in focused_parents {
2480 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
2481 view.focus_in(this, window_id, view_id, focused_id);
2482 this.cx.views.insert((window_id, view_id), view);
2483 }
2484 }
2485
2486 let mut subscriptions = this.focus_observations.clone();
2487 subscriptions.emit(focused_id, this, |callback, this| callback(true, this));
2488 }
2489 })
2490 }
2491
2492 fn handle_dispatch_action_from_effect(
2493 &mut self,
2494 window_id: usize,
2495 view_id: Option<usize>,
2496 action: &dyn Action,
2497 ) -> bool {
2498 self.update(|this| {
2499 if let Some(view_id) = view_id {
2500 this.halt_action_dispatch = false;
2501 this.visit_dispatch_path(window_id, view_id, |view_id, capture_phase, this| {
2502 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
2503 let type_id = view.as_any().type_id();
2504
2505 if let Some((name, mut handlers)) = this
2506 .actions_mut(capture_phase)
2507 .get_mut(&type_id)
2508 .and_then(|h| h.remove_entry(&action.id()))
2509 {
2510 for handler in handlers.iter_mut().rev() {
2511 this.halt_action_dispatch = true;
2512 handler(view.as_mut(), action, this, window_id, view_id);
2513 if this.halt_action_dispatch {
2514 break;
2515 }
2516 }
2517 this.actions_mut(capture_phase)
2518 .get_mut(&type_id)
2519 .unwrap()
2520 .insert(name, handlers);
2521 }
2522
2523 this.cx.views.insert((window_id, view_id), view);
2524 }
2525
2526 !this.halt_action_dispatch
2527 });
2528 }
2529
2530 if !this.halt_action_dispatch {
2531 this.halt_action_dispatch = this.dispatch_global_action_any(action);
2532 }
2533
2534 this.pending_effects
2535 .push_back(Effect::ActionDispatchNotification {
2536 action_id: action.id(),
2537 });
2538 this.halt_action_dispatch
2539 })
2540 }
2541
2542 fn handle_action_dispatch_notification_effect(&mut self, action_id: TypeId) {
2543 self.action_dispatch_observations
2544 .clone()
2545 .emit((), self, |callback, this| {
2546 callback(action_id, this);
2547 true
2548 });
2549 }
2550
2551 fn handle_window_should_close_subscription_effect(
2552 &mut self,
2553 window_id: usize,
2554 mut callback: WindowShouldCloseSubscriptionCallback,
2555 ) {
2556 let mut app = self.upgrade();
2557 if let Some((_, window)) = self.presenters_and_platform_windows.get_mut(&window_id) {
2558 window.on_should_close(Box::new(move || app.update(|cx| callback(cx))))
2559 }
2560 }
2561
2562 fn handle_window_moved(&mut self, window_id: usize) {
2563 if let Some(display) = self.window_display_uuid(window_id) {
2564 let bounds = self.window_bounds(window_id);
2565 self.window_bounds_observations
2566 .clone()
2567 .emit(window_id, self, move |callback, this| {
2568 callback(bounds, display, this);
2569 true
2570 });
2571 }
2572 }
2573
2574 pub fn focus(&mut self, window_id: usize, view_id: Option<usize>) {
2575 self.pending_effects
2576 .push_back(Effect::Focus { window_id, view_id });
2577 }
2578
2579 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
2580 where
2581 F: FnOnce(AsyncAppContext) -> Fut,
2582 Fut: 'static + Future<Output = T>,
2583 T: 'static,
2584 {
2585 let future = f(self.to_async());
2586 let cx = self.to_async();
2587 self.foreground.spawn(async move {
2588 let result = future.await;
2589 cx.0.borrow_mut().flush_effects();
2590 result
2591 })
2592 }
2593
2594 pub fn to_async(&self) -> AsyncAppContext {
2595 AsyncAppContext(self.weak_self.as_ref().unwrap().upgrade().unwrap())
2596 }
2597
2598 pub fn write_to_clipboard(&self, item: ClipboardItem) {
2599 self.cx.platform.write_to_clipboard(item);
2600 }
2601
2602 pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {
2603 self.cx.platform.read_from_clipboard()
2604 }
2605
2606 #[cfg(any(test, feature = "test-support"))]
2607 pub fn leak_detector(&self) -> Arc<Mutex<LeakDetector>> {
2608 self.cx.ref_counts.lock().leak_detector.clone()
2609 }
2610}
2611
2612impl ReadModel for MutableAppContext {
2613 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2614 if let Some(model) = self.cx.models.get(&handle.model_id) {
2615 model
2616 .as_any()
2617 .downcast_ref()
2618 .expect("downcast is type safe")
2619 } else {
2620 panic!("circular model reference");
2621 }
2622 }
2623}
2624
2625impl UpdateModel for MutableAppContext {
2626 fn update_model<T: Entity, V>(
2627 &mut self,
2628 handle: &ModelHandle<T>,
2629 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
2630 ) -> V {
2631 if let Some(mut model) = self.cx.models.remove(&handle.model_id) {
2632 self.update(|this| {
2633 let mut cx = ModelContext::new(this, handle.model_id);
2634 let result = update(
2635 model
2636 .as_any_mut()
2637 .downcast_mut()
2638 .expect("downcast is type safe"),
2639 &mut cx,
2640 );
2641 this.cx.models.insert(handle.model_id, model);
2642 result
2643 })
2644 } else {
2645 panic!("circular model update");
2646 }
2647 }
2648}
2649
2650impl UpgradeModelHandle for MutableAppContext {
2651 fn upgrade_model_handle<T: Entity>(
2652 &self,
2653 handle: &WeakModelHandle<T>,
2654 ) -> Option<ModelHandle<T>> {
2655 self.cx.upgrade_model_handle(handle)
2656 }
2657
2658 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
2659 self.cx.model_handle_is_upgradable(handle)
2660 }
2661
2662 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
2663 self.cx.upgrade_any_model_handle(handle)
2664 }
2665}
2666
2667impl UpgradeViewHandle for MutableAppContext {
2668 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
2669 self.cx.upgrade_view_handle(handle)
2670 }
2671
2672 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
2673 self.cx.upgrade_any_view_handle(handle)
2674 }
2675}
2676
2677impl ReadView for MutableAppContext {
2678 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2679 if let Some(view) = self.cx.views.get(&(handle.window_id, handle.view_id)) {
2680 view.as_any().downcast_ref().expect("downcast is type safe")
2681 } else {
2682 panic!("circular view reference for type {}", type_name::<T>());
2683 }
2684 }
2685}
2686
2687impl UpdateView for MutableAppContext {
2688 fn update_view<T, S>(
2689 &mut self,
2690 handle: &ViewHandle<T>,
2691 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
2692 ) -> S
2693 where
2694 T: View,
2695 {
2696 self.update(|this| {
2697 let mut view = this
2698 .cx
2699 .views
2700 .remove(&(handle.window_id, handle.view_id))
2701 .expect("circular view update");
2702
2703 let mut cx = ViewContext::new(this, handle.window_id, handle.view_id);
2704 let result = update(
2705 view.as_any_mut()
2706 .downcast_mut()
2707 .expect("downcast is type safe"),
2708 &mut cx,
2709 );
2710 this.cx
2711 .views
2712 .insert((handle.window_id, handle.view_id), view);
2713 result
2714 })
2715 }
2716}
2717
2718impl AsRef<AppContext> for MutableAppContext {
2719 fn as_ref(&self) -> &AppContext {
2720 &self.cx
2721 }
2722}
2723
2724impl Deref for MutableAppContext {
2725 type Target = AppContext;
2726
2727 fn deref(&self) -> &Self::Target {
2728 &self.cx
2729 }
2730}
2731
2732#[derive(Debug)]
2733pub enum ParentId {
2734 View(usize),
2735 Root,
2736}
2737
2738pub struct AppContext {
2739 models: HashMap<usize, Box<dyn AnyModel>>,
2740 views: HashMap<(usize, usize), Box<dyn AnyView>>,
2741 pub(crate) parents: HashMap<(usize, usize), ParentId>,
2742 windows: HashMap<usize, Window>,
2743 globals: HashMap<TypeId, Box<dyn Any>>,
2744 element_states: HashMap<ElementStateId, Box<dyn Any>>,
2745 background: Arc<executor::Background>,
2746 ref_counts: Arc<Mutex<RefCounts>>,
2747 font_cache: Arc<FontCache>,
2748 platform: Arc<dyn Platform>,
2749}
2750
2751impl AppContext {
2752 pub(crate) fn root_view(&self, window_id: usize) -> Option<AnyViewHandle> {
2753 self.windows
2754 .get(&window_id)
2755 .map(|window| window.root_view.clone())
2756 }
2757
2758 pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
2759 self.windows
2760 .get(&window_id)
2761 .map(|window| window.root_view.id())
2762 }
2763
2764 pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
2765 self.windows
2766 .get(&window_id)
2767 .and_then(|window| window.focused_view_id)
2768 }
2769
2770 pub fn view_ui_name(&self, window_id: usize, view_id: usize) -> Option<&'static str> {
2771 Some(self.views.get(&(window_id, view_id))?.ui_name())
2772 }
2773
2774 pub fn background(&self) -> &Arc<executor::Background> {
2775 &self.background
2776 }
2777
2778 pub fn font_cache(&self) -> &Arc<FontCache> {
2779 &self.font_cache
2780 }
2781
2782 pub fn platform(&self) -> &Arc<dyn Platform> {
2783 &self.platform
2784 }
2785
2786 pub fn has_global<T: 'static>(&self) -> bool {
2787 self.globals.contains_key(&TypeId::of::<T>())
2788 }
2789
2790 pub fn global<T: 'static>(&self) -> &T {
2791 if let Some(global) = self.globals.get(&TypeId::of::<T>()) {
2792 global.downcast_ref().unwrap()
2793 } else {
2794 panic!("no global has been added for {}", type_name::<T>());
2795 }
2796 }
2797
2798 /// Returns an iterator over all of the view ids from the passed view up to the root of the window
2799 /// Includes the passed view itself
2800 fn ancestors(&self, window_id: usize, mut view_id: usize) -> impl Iterator<Item = usize> + '_ {
2801 std::iter::once(view_id)
2802 .into_iter()
2803 .chain(std::iter::from_fn(move || {
2804 if let Some(ParentId::View(parent_id)) = self.parents.get(&(window_id, view_id)) {
2805 view_id = *parent_id;
2806 Some(view_id)
2807 } else {
2808 None
2809 }
2810 }))
2811 }
2812
2813 pub fn is_child_focused(&self, view: impl Into<AnyViewHandle>) -> bool {
2814 let view = view.into();
2815 if let Some(focused_view_id) = self.focused_view_id(view.window_id) {
2816 self.ancestors(view.window_id, focused_view_id)
2817 .skip(1) // Skip self id
2818 .any(|parent| parent == view.view_id)
2819 } else {
2820 false
2821 }
2822 }
2823}
2824
2825impl ReadModel for AppContext {
2826 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2827 if let Some(model) = self.models.get(&handle.model_id) {
2828 model
2829 .as_any()
2830 .downcast_ref()
2831 .expect("downcast should be type safe")
2832 } else {
2833 panic!("circular model reference");
2834 }
2835 }
2836}
2837
2838impl UpgradeModelHandle for AppContext {
2839 fn upgrade_model_handle<T: Entity>(
2840 &self,
2841 handle: &WeakModelHandle<T>,
2842 ) -> Option<ModelHandle<T>> {
2843 if self.models.contains_key(&handle.model_id) {
2844 Some(ModelHandle::new(handle.model_id, &self.ref_counts))
2845 } else {
2846 None
2847 }
2848 }
2849
2850 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
2851 self.models.contains_key(&handle.model_id)
2852 }
2853
2854 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
2855 if self.models.contains_key(&handle.model_id) {
2856 Some(AnyModelHandle::new(
2857 handle.model_id,
2858 handle.model_type,
2859 self.ref_counts.clone(),
2860 ))
2861 } else {
2862 None
2863 }
2864 }
2865}
2866
2867impl UpgradeViewHandle for AppContext {
2868 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
2869 if self.ref_counts.lock().is_entity_alive(handle.view_id) {
2870 Some(ViewHandle::new(
2871 handle.window_id,
2872 handle.view_id,
2873 &self.ref_counts,
2874 ))
2875 } else {
2876 None
2877 }
2878 }
2879
2880 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
2881 if self.ref_counts.lock().is_entity_alive(handle.view_id) {
2882 Some(AnyViewHandle::new(
2883 handle.window_id,
2884 handle.view_id,
2885 handle.view_type,
2886 self.ref_counts.clone(),
2887 ))
2888 } else {
2889 None
2890 }
2891 }
2892}
2893
2894impl ReadView for AppContext {
2895 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2896 if let Some(view) = self.views.get(&(handle.window_id, handle.view_id)) {
2897 view.as_any()
2898 .downcast_ref()
2899 .expect("downcast should be type safe")
2900 } else {
2901 panic!("circular view reference");
2902 }
2903 }
2904}
2905
2906struct Window {
2907 root_view: AnyViewHandle,
2908 focused_view_id: Option<usize>,
2909 is_active: bool,
2910 is_fullscreen: bool,
2911 invalidation: Option<WindowInvalidation>,
2912}
2913
2914#[derive(Default, Clone)]
2915pub struct WindowInvalidation {
2916 pub updated: HashSet<usize>,
2917 pub removed: Vec<usize>,
2918}
2919
2920pub enum Effect {
2921 Subscription {
2922 entity_id: usize,
2923 subscription_id: usize,
2924 callback: SubscriptionCallback,
2925 },
2926 Event {
2927 entity_id: usize,
2928 payload: Box<dyn Any>,
2929 },
2930 GlobalSubscription {
2931 type_id: TypeId,
2932 subscription_id: usize,
2933 callback: GlobalSubscriptionCallback,
2934 },
2935 GlobalEvent {
2936 payload: Box<dyn Any>,
2937 },
2938 Observation {
2939 entity_id: usize,
2940 subscription_id: usize,
2941 callback: ObservationCallback,
2942 },
2943 ModelNotification {
2944 model_id: usize,
2945 },
2946 ViewNotification {
2947 window_id: usize,
2948 view_id: usize,
2949 },
2950 Deferred {
2951 callback: Box<dyn FnOnce(&mut MutableAppContext)>,
2952 after_window_update: bool,
2953 },
2954 GlobalNotification {
2955 type_id: TypeId,
2956 },
2957 ModelRelease {
2958 model_id: usize,
2959 model: Box<dyn AnyModel>,
2960 },
2961 ViewRelease {
2962 view_id: usize,
2963 view: Box<dyn AnyView>,
2964 },
2965 Focus {
2966 window_id: usize,
2967 view_id: Option<usize>,
2968 },
2969 FocusObservation {
2970 view_id: usize,
2971 subscription_id: usize,
2972 callback: FocusObservationCallback,
2973 },
2974 ResizeWindow {
2975 window_id: usize,
2976 },
2977 MoveWindow {
2978 window_id: usize,
2979 },
2980 ActivateWindow {
2981 window_id: usize,
2982 is_active: bool,
2983 },
2984 WindowActivationObservation {
2985 window_id: usize,
2986 subscription_id: usize,
2987 callback: WindowActivationCallback,
2988 },
2989 FullscreenWindow {
2990 window_id: usize,
2991 is_fullscreen: bool,
2992 },
2993 WindowFullscreenObservation {
2994 window_id: usize,
2995 subscription_id: usize,
2996 callback: WindowFullscreenCallback,
2997 },
2998 WindowBoundsObservation {
2999 window_id: usize,
3000 subscription_id: usize,
3001 callback: WindowBoundsCallback,
3002 },
3003 Keystroke {
3004 window_id: usize,
3005 keystroke: Keystroke,
3006 handled_by: Option<Box<dyn Action>>,
3007 result: MatchResult,
3008 },
3009 RefreshWindows,
3010 DispatchActionFrom {
3011 window_id: usize,
3012 view_id: usize,
3013 action: Box<dyn Action>,
3014 },
3015 ActionDispatchNotification {
3016 action_id: TypeId,
3017 },
3018 WindowShouldCloseSubscription {
3019 window_id: usize,
3020 callback: WindowShouldCloseSubscriptionCallback,
3021 },
3022}
3023
3024impl Debug for Effect {
3025 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3026 match self {
3027 Effect::Subscription {
3028 entity_id,
3029 subscription_id,
3030 ..
3031 } => f
3032 .debug_struct("Effect::Subscribe")
3033 .field("entity_id", entity_id)
3034 .field("subscription_id", subscription_id)
3035 .finish(),
3036 Effect::Event { entity_id, .. } => f
3037 .debug_struct("Effect::Event")
3038 .field("entity_id", entity_id)
3039 .finish(),
3040 Effect::GlobalSubscription {
3041 type_id,
3042 subscription_id,
3043 ..
3044 } => f
3045 .debug_struct("Effect::Subscribe")
3046 .field("type_id", type_id)
3047 .field("subscription_id", subscription_id)
3048 .finish(),
3049 Effect::GlobalEvent { payload, .. } => f
3050 .debug_struct("Effect::GlobalEvent")
3051 .field("type_id", &(&*payload).type_id())
3052 .finish(),
3053 Effect::Observation {
3054 entity_id,
3055 subscription_id,
3056 ..
3057 } => f
3058 .debug_struct("Effect::Observation")
3059 .field("entity_id", entity_id)
3060 .field("subscription_id", subscription_id)
3061 .finish(),
3062 Effect::ModelNotification { model_id } => f
3063 .debug_struct("Effect::ModelNotification")
3064 .field("model_id", model_id)
3065 .finish(),
3066 Effect::ViewNotification { window_id, view_id } => f
3067 .debug_struct("Effect::ViewNotification")
3068 .field("window_id", window_id)
3069 .field("view_id", view_id)
3070 .finish(),
3071 Effect::GlobalNotification { type_id } => f
3072 .debug_struct("Effect::GlobalNotification")
3073 .field("type_id", type_id)
3074 .finish(),
3075 Effect::Deferred { .. } => f.debug_struct("Effect::Deferred").finish(),
3076 Effect::ModelRelease { model_id, .. } => f
3077 .debug_struct("Effect::ModelRelease")
3078 .field("model_id", model_id)
3079 .finish(),
3080 Effect::ViewRelease { view_id, .. } => f
3081 .debug_struct("Effect::ViewRelease")
3082 .field("view_id", view_id)
3083 .finish(),
3084 Effect::Focus { window_id, view_id } => f
3085 .debug_struct("Effect::Focus")
3086 .field("window_id", window_id)
3087 .field("view_id", view_id)
3088 .finish(),
3089 Effect::FocusObservation {
3090 view_id,
3091 subscription_id,
3092 ..
3093 } => f
3094 .debug_struct("Effect::FocusObservation")
3095 .field("view_id", view_id)
3096 .field("subscription_id", subscription_id)
3097 .finish(),
3098 Effect::DispatchActionFrom {
3099 window_id, view_id, ..
3100 } => f
3101 .debug_struct("Effect::DispatchActionFrom")
3102 .field("window_id", window_id)
3103 .field("view_id", view_id)
3104 .finish(),
3105 Effect::ActionDispatchNotification { action_id, .. } => f
3106 .debug_struct("Effect::ActionDispatchNotification")
3107 .field("action_id", action_id)
3108 .finish(),
3109 Effect::ResizeWindow { window_id } => f
3110 .debug_struct("Effect::RefreshWindow")
3111 .field("window_id", window_id)
3112 .finish(),
3113 Effect::MoveWindow { window_id } => f
3114 .debug_struct("Effect::MoveWindow")
3115 .field("window_id", window_id)
3116 .finish(),
3117 Effect::WindowActivationObservation {
3118 window_id,
3119 subscription_id,
3120 ..
3121 } => f
3122 .debug_struct("Effect::WindowActivationObservation")
3123 .field("window_id", window_id)
3124 .field("subscription_id", subscription_id)
3125 .finish(),
3126 Effect::ActivateWindow {
3127 window_id,
3128 is_active,
3129 } => f
3130 .debug_struct("Effect::ActivateWindow")
3131 .field("window_id", window_id)
3132 .field("is_active", is_active)
3133 .finish(),
3134 Effect::FullscreenWindow {
3135 window_id,
3136 is_fullscreen,
3137 } => f
3138 .debug_struct("Effect::FullscreenWindow")
3139 .field("window_id", window_id)
3140 .field("is_fullscreen", is_fullscreen)
3141 .finish(),
3142 Effect::WindowFullscreenObservation {
3143 window_id,
3144 subscription_id,
3145 callback: _,
3146 } => f
3147 .debug_struct("Effect::WindowFullscreenObservation")
3148 .field("window_id", window_id)
3149 .field("subscription_id", subscription_id)
3150 .finish(),
3151
3152 Effect::WindowBoundsObservation {
3153 window_id,
3154 subscription_id,
3155 callback: _,
3156 } => f
3157 .debug_struct("Effect::WindowBoundsObservation")
3158 .field("window_id", window_id)
3159 .field("subscription_id", subscription_id)
3160 .finish(),
3161 Effect::RefreshWindows => f.debug_struct("Effect::FullViewRefresh").finish(),
3162 Effect::WindowShouldCloseSubscription { window_id, .. } => f
3163 .debug_struct("Effect::WindowShouldCloseSubscription")
3164 .field("window_id", window_id)
3165 .finish(),
3166 Effect::Keystroke {
3167 window_id,
3168 keystroke,
3169 handled_by,
3170 result,
3171 } => f
3172 .debug_struct("Effect::Keystroke")
3173 .field("window_id", window_id)
3174 .field("keystroke", keystroke)
3175 .field(
3176 "keystroke",
3177 &handled_by.as_ref().map(|handled_by| handled_by.name()),
3178 )
3179 .field("result", result)
3180 .finish(),
3181 }
3182 }
3183}
3184
3185pub trait AnyModel {
3186 fn as_any(&self) -> &dyn Any;
3187 fn as_any_mut(&mut self) -> &mut dyn Any;
3188 fn release(&mut self, cx: &mut MutableAppContext);
3189 fn app_will_quit(
3190 &mut self,
3191 cx: &mut MutableAppContext,
3192 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
3193}
3194
3195impl<T> AnyModel for T
3196where
3197 T: Entity,
3198{
3199 fn as_any(&self) -> &dyn Any {
3200 self
3201 }
3202
3203 fn as_any_mut(&mut self) -> &mut dyn Any {
3204 self
3205 }
3206
3207 fn release(&mut self, cx: &mut MutableAppContext) {
3208 self.release(cx);
3209 }
3210
3211 fn app_will_quit(
3212 &mut self,
3213 cx: &mut MutableAppContext,
3214 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
3215 self.app_will_quit(cx)
3216 }
3217}
3218
3219pub trait AnyView {
3220 fn as_any(&self) -> &dyn Any;
3221 fn as_any_mut(&mut self) -> &mut dyn Any;
3222 fn release(&mut self, cx: &mut MutableAppContext);
3223 fn app_will_quit(
3224 &mut self,
3225 cx: &mut MutableAppContext,
3226 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
3227 fn ui_name(&self) -> &'static str;
3228 fn render(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox;
3229 fn focus_in(
3230 &mut self,
3231 cx: &mut MutableAppContext,
3232 window_id: usize,
3233 view_id: usize,
3234 focused_id: usize,
3235 );
3236 fn focus_out(
3237 &mut self,
3238 cx: &mut MutableAppContext,
3239 window_id: usize,
3240 view_id: usize,
3241 focused_id: usize,
3242 );
3243 fn key_down(
3244 &mut self,
3245 event: &KeyDownEvent,
3246 cx: &mut MutableAppContext,
3247 window_id: usize,
3248 view_id: usize,
3249 ) -> bool;
3250 fn key_up(
3251 &mut self,
3252 event: &KeyUpEvent,
3253 cx: &mut MutableAppContext,
3254 window_id: usize,
3255 view_id: usize,
3256 ) -> bool;
3257 fn modifiers_changed(
3258 &mut self,
3259 event: &ModifiersChangedEvent,
3260 cx: &mut MutableAppContext,
3261 window_id: usize,
3262 view_id: usize,
3263 ) -> bool;
3264 fn keymap_context(&self, cx: &AppContext) -> KeymapContext;
3265 fn debug_json(&self, cx: &AppContext) -> serde_json::Value;
3266
3267 fn text_for_range(&self, range: Range<usize>, cx: &AppContext) -> Option<String>;
3268 fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>>;
3269 fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>>;
3270 fn unmark_text(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize);
3271 fn replace_text_in_range(
3272 &mut self,
3273 range: Option<Range<usize>>,
3274 text: &str,
3275 cx: &mut MutableAppContext,
3276 window_id: usize,
3277 view_id: usize,
3278 );
3279 fn replace_and_mark_text_in_range(
3280 &mut self,
3281 range: Option<Range<usize>>,
3282 new_text: &str,
3283 new_selected_range: Option<Range<usize>>,
3284 cx: &mut MutableAppContext,
3285 window_id: usize,
3286 view_id: usize,
3287 );
3288 fn any_handle(&self, window_id: usize, view_id: usize, cx: &AppContext) -> AnyViewHandle {
3289 AnyViewHandle::new(
3290 window_id,
3291 view_id,
3292 self.as_any().type_id(),
3293 cx.ref_counts.clone(),
3294 )
3295 }
3296}
3297
3298impl<T> AnyView for T
3299where
3300 T: View,
3301{
3302 fn as_any(&self) -> &dyn Any {
3303 self
3304 }
3305
3306 fn as_any_mut(&mut self) -> &mut dyn Any {
3307 self
3308 }
3309
3310 fn release(&mut self, cx: &mut MutableAppContext) {
3311 self.release(cx);
3312 }
3313
3314 fn app_will_quit(
3315 &mut self,
3316 cx: &mut MutableAppContext,
3317 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
3318 self.app_will_quit(cx)
3319 }
3320
3321 fn ui_name(&self) -> &'static str {
3322 T::ui_name()
3323 }
3324
3325 fn render(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox {
3326 View::render(self, &mut RenderContext::new(params, cx))
3327 }
3328
3329 fn focus_in(
3330 &mut self,
3331 cx: &mut MutableAppContext,
3332 window_id: usize,
3333 view_id: usize,
3334 focused_id: usize,
3335 ) {
3336 let mut cx = ViewContext::new(cx, window_id, view_id);
3337 let focused_view_handle: AnyViewHandle = if view_id == focused_id {
3338 cx.handle().into()
3339 } else {
3340 let focused_type = cx
3341 .views
3342 .get(&(window_id, focused_id))
3343 .unwrap()
3344 .as_any()
3345 .type_id();
3346 AnyViewHandle::new(window_id, focused_id, focused_type, cx.ref_counts.clone())
3347 };
3348 View::focus_in(self, focused_view_handle, &mut cx);
3349 }
3350
3351 fn focus_out(
3352 &mut self,
3353 cx: &mut MutableAppContext,
3354 window_id: usize,
3355 view_id: usize,
3356 blurred_id: usize,
3357 ) {
3358 let mut cx = ViewContext::new(cx, window_id, view_id);
3359 let blurred_view_handle: AnyViewHandle = if view_id == blurred_id {
3360 cx.handle().into()
3361 } else {
3362 let blurred_type = cx
3363 .views
3364 .get(&(window_id, blurred_id))
3365 .unwrap()
3366 .as_any()
3367 .type_id();
3368 AnyViewHandle::new(window_id, blurred_id, blurred_type, cx.ref_counts.clone())
3369 };
3370 View::focus_out(self, blurred_view_handle, &mut cx);
3371 }
3372
3373 fn key_down(
3374 &mut self,
3375 event: &KeyDownEvent,
3376 cx: &mut MutableAppContext,
3377 window_id: usize,
3378 view_id: usize,
3379 ) -> bool {
3380 let mut cx = ViewContext::new(cx, window_id, view_id);
3381 View::key_down(self, event, &mut cx)
3382 }
3383
3384 fn key_up(
3385 &mut self,
3386 event: &KeyUpEvent,
3387 cx: &mut MutableAppContext,
3388 window_id: usize,
3389 view_id: usize,
3390 ) -> bool {
3391 let mut cx = ViewContext::new(cx, window_id, view_id);
3392 View::key_up(self, event, &mut cx)
3393 }
3394
3395 fn modifiers_changed(
3396 &mut self,
3397 event: &ModifiersChangedEvent,
3398 cx: &mut MutableAppContext,
3399 window_id: usize,
3400 view_id: usize,
3401 ) -> bool {
3402 let mut cx = ViewContext::new(cx, window_id, view_id);
3403 View::modifiers_changed(self, event, &mut cx)
3404 }
3405
3406 fn keymap_context(&self, cx: &AppContext) -> KeymapContext {
3407 View::keymap_context(self, cx)
3408 }
3409
3410 fn debug_json(&self, cx: &AppContext) -> serde_json::Value {
3411 View::debug_json(self, cx)
3412 }
3413
3414 fn text_for_range(&self, range: Range<usize>, cx: &AppContext) -> Option<String> {
3415 View::text_for_range(self, range, cx)
3416 }
3417
3418 fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
3419 View::selected_text_range(self, cx)
3420 }
3421
3422 fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
3423 View::marked_text_range(self, cx)
3424 }
3425
3426 fn unmark_text(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) {
3427 let mut cx = ViewContext::new(cx, window_id, view_id);
3428 View::unmark_text(self, &mut cx)
3429 }
3430
3431 fn replace_text_in_range(
3432 &mut self,
3433 range: Option<Range<usize>>,
3434 text: &str,
3435 cx: &mut MutableAppContext,
3436 window_id: usize,
3437 view_id: usize,
3438 ) {
3439 let mut cx = ViewContext::new(cx, window_id, view_id);
3440 View::replace_text_in_range(self, range, text, &mut cx)
3441 }
3442
3443 fn replace_and_mark_text_in_range(
3444 &mut self,
3445 range: Option<Range<usize>>,
3446 new_text: &str,
3447 new_selected_range: Option<Range<usize>>,
3448 cx: &mut MutableAppContext,
3449 window_id: usize,
3450 view_id: usize,
3451 ) {
3452 let mut cx = ViewContext::new(cx, window_id, view_id);
3453 View::replace_and_mark_text_in_range(self, range, new_text, new_selected_range, &mut cx)
3454 }
3455}
3456
3457pub struct ModelContext<'a, T: ?Sized> {
3458 app: &'a mut MutableAppContext,
3459 model_id: usize,
3460 model_type: PhantomData<T>,
3461 halt_stream: bool,
3462}
3463
3464impl<'a, T: Entity> ModelContext<'a, T> {
3465 fn new(app: &'a mut MutableAppContext, model_id: usize) -> Self {
3466 Self {
3467 app,
3468 model_id,
3469 model_type: PhantomData,
3470 halt_stream: false,
3471 }
3472 }
3473
3474 pub fn background(&self) -> &Arc<executor::Background> {
3475 &self.app.cx.background
3476 }
3477
3478 pub fn halt_stream(&mut self) {
3479 self.halt_stream = true;
3480 }
3481
3482 pub fn model_id(&self) -> usize {
3483 self.model_id
3484 }
3485
3486 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
3487 where
3488 S: Entity,
3489 F: FnOnce(&mut ModelContext<S>) -> S,
3490 {
3491 self.app.add_model(build_model)
3492 }
3493
3494 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ModelContext<T>)) {
3495 let handle = self.handle();
3496 self.app.defer(move |cx| {
3497 handle.update(cx, |model, cx| {
3498 callback(model, cx);
3499 })
3500 })
3501 }
3502
3503 pub fn emit(&mut self, payload: T::Event) {
3504 self.app.pending_effects.push_back(Effect::Event {
3505 entity_id: self.model_id,
3506 payload: Box::new(payload),
3507 });
3508 }
3509
3510 pub fn notify(&mut self) {
3511 self.app.notify_model(self.model_id);
3512 }
3513
3514 pub fn subscribe<S: Entity, F>(
3515 &mut self,
3516 handle: &ModelHandle<S>,
3517 mut callback: F,
3518 ) -> Subscription
3519 where
3520 S::Event: 'static,
3521 F: 'static + FnMut(&mut T, ModelHandle<S>, &S::Event, &mut ModelContext<T>),
3522 {
3523 let subscriber = self.weak_handle();
3524 self.app
3525 .subscribe_internal(handle, move |emitter, event, cx| {
3526 if let Some(subscriber) = subscriber.upgrade(cx) {
3527 subscriber.update(cx, |subscriber, cx| {
3528 callback(subscriber, emitter, event, cx);
3529 });
3530 true
3531 } else {
3532 false
3533 }
3534 })
3535 }
3536
3537 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F) -> Subscription
3538 where
3539 S: Entity,
3540 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ModelContext<T>),
3541 {
3542 let observer = self.weak_handle();
3543 self.app.observe_internal(handle, move |observed, cx| {
3544 if let Some(observer) = observer.upgrade(cx) {
3545 observer.update(cx, |observer, cx| {
3546 callback(observer, observed, cx);
3547 });
3548 true
3549 } else {
3550 false
3551 }
3552 })
3553 }
3554
3555 pub fn observe_global<G, F>(&mut self, mut callback: F) -> Subscription
3556 where
3557 G: Any,
3558 F: 'static + FnMut(&mut T, &mut ModelContext<T>),
3559 {
3560 let observer = self.weak_handle();
3561 self.app.observe_global::<G, _>(move |cx| {
3562 if let Some(observer) = observer.upgrade(cx) {
3563 observer.update(cx, |observer, cx| callback(observer, cx));
3564 }
3565 })
3566 }
3567
3568 pub fn observe_release<S, F>(
3569 &mut self,
3570 handle: &ModelHandle<S>,
3571 mut callback: F,
3572 ) -> Subscription
3573 where
3574 S: Entity,
3575 F: 'static + FnMut(&mut T, &S, &mut ModelContext<T>),
3576 {
3577 let observer = self.weak_handle();
3578 self.app.observe_release(handle, move |released, cx| {
3579 if let Some(observer) = observer.upgrade(cx) {
3580 observer.update(cx, |observer, cx| {
3581 callback(observer, released, cx);
3582 });
3583 }
3584 })
3585 }
3586
3587 pub fn handle(&self) -> ModelHandle<T> {
3588 ModelHandle::new(self.model_id, &self.app.cx.ref_counts)
3589 }
3590
3591 pub fn weak_handle(&self) -> WeakModelHandle<T> {
3592 WeakModelHandle::new(self.model_id)
3593 }
3594
3595 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
3596 where
3597 F: FnOnce(ModelHandle<T>, AsyncAppContext) -> Fut,
3598 Fut: 'static + Future<Output = S>,
3599 S: 'static,
3600 {
3601 let handle = self.handle();
3602 self.app.spawn(|cx| f(handle, cx))
3603 }
3604
3605 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
3606 where
3607 F: FnOnce(WeakModelHandle<T>, AsyncAppContext) -> Fut,
3608 Fut: 'static + Future<Output = S>,
3609 S: 'static,
3610 {
3611 let handle = self.weak_handle();
3612 self.app.spawn(|cx| f(handle, cx))
3613 }
3614}
3615
3616impl<M> AsRef<AppContext> for ModelContext<'_, M> {
3617 fn as_ref(&self) -> &AppContext {
3618 &self.app.cx
3619 }
3620}
3621
3622impl<M> AsMut<MutableAppContext> for ModelContext<'_, M> {
3623 fn as_mut(&mut self) -> &mut MutableAppContext {
3624 self.app
3625 }
3626}
3627
3628impl<M> ReadModel for ModelContext<'_, M> {
3629 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
3630 self.app.read_model(handle)
3631 }
3632}
3633
3634impl<M> UpdateModel for ModelContext<'_, M> {
3635 fn update_model<T: Entity, V>(
3636 &mut self,
3637 handle: &ModelHandle<T>,
3638 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
3639 ) -> V {
3640 self.app.update_model(handle, update)
3641 }
3642}
3643
3644impl<M> UpgradeModelHandle for ModelContext<'_, M> {
3645 fn upgrade_model_handle<T: Entity>(
3646 &self,
3647 handle: &WeakModelHandle<T>,
3648 ) -> Option<ModelHandle<T>> {
3649 self.cx.upgrade_model_handle(handle)
3650 }
3651
3652 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
3653 self.cx.model_handle_is_upgradable(handle)
3654 }
3655
3656 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
3657 self.cx.upgrade_any_model_handle(handle)
3658 }
3659}
3660
3661impl<M> Deref for ModelContext<'_, M> {
3662 type Target = MutableAppContext;
3663
3664 fn deref(&self) -> &Self::Target {
3665 self.app
3666 }
3667}
3668
3669impl<M> DerefMut for ModelContext<'_, M> {
3670 fn deref_mut(&mut self) -> &mut Self::Target {
3671 &mut self.app
3672 }
3673}
3674
3675pub struct ViewContext<'a, T: ?Sized> {
3676 app: &'a mut MutableAppContext,
3677 window_id: usize,
3678 view_id: usize,
3679 view_type: PhantomData<T>,
3680}
3681
3682impl<'a, T: View> ViewContext<'a, T> {
3683 fn new(app: &'a mut MutableAppContext, window_id: usize, view_id: usize) -> Self {
3684 Self {
3685 app,
3686 window_id,
3687 view_id,
3688 view_type: PhantomData,
3689 }
3690 }
3691
3692 pub fn handle(&self) -> ViewHandle<T> {
3693 ViewHandle::new(self.window_id, self.view_id, &self.app.cx.ref_counts)
3694 }
3695
3696 pub fn weak_handle(&self) -> WeakViewHandle<T> {
3697 WeakViewHandle::new(self.window_id, self.view_id)
3698 }
3699
3700 pub fn window_id(&self) -> usize {
3701 self.window_id
3702 }
3703
3704 pub fn view_id(&self) -> usize {
3705 self.view_id
3706 }
3707
3708 pub fn foreground(&self) -> &Rc<executor::Foreground> {
3709 self.app.foreground()
3710 }
3711
3712 pub fn background_executor(&self) -> &Arc<executor::Background> {
3713 &self.app.cx.background
3714 }
3715
3716 pub fn platform(&self) -> Arc<dyn Platform> {
3717 self.app.platform()
3718 }
3719
3720 pub fn show_character_palette(&self) {
3721 self.app.show_character_palette(self.window_id);
3722 }
3723
3724 pub fn minimize_window(&self) {
3725 self.app.minimize_window(self.window_id)
3726 }
3727
3728 pub fn zoom_window(&self) {
3729 self.app.zoom_window(self.window_id)
3730 }
3731
3732 pub fn toggle_full_screen(&self) {
3733 self.app.toggle_window_full_screen(self.window_id)
3734 }
3735
3736 pub fn window_bounds(&self) -> WindowBounds {
3737 self.app.window_bounds(self.window_id)
3738 }
3739
3740 pub fn prompt(
3741 &self,
3742 level: PromptLevel,
3743 msg: &str,
3744 answers: &[&str],
3745 ) -> oneshot::Receiver<usize> {
3746 self.app.prompt(self.window_id, level, msg, answers)
3747 }
3748
3749 pub fn prompt_for_paths(
3750 &self,
3751 options: PathPromptOptions,
3752 ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
3753 self.app.prompt_for_paths(options)
3754 }
3755
3756 pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
3757 self.app.prompt_for_new_path(directory)
3758 }
3759
3760 pub fn debug_elements(&self) -> crate::json::Value {
3761 self.app.debug_elements(self.window_id).unwrap()
3762 }
3763
3764 pub fn focus<S>(&mut self, handle: S)
3765 where
3766 S: Into<AnyViewHandle>,
3767 {
3768 let handle = handle.into();
3769 self.app.focus(handle.window_id, Some(handle.view_id));
3770 }
3771
3772 pub fn focus_self(&mut self) {
3773 self.app.focus(self.window_id, Some(self.view_id));
3774 }
3775
3776 pub fn is_self_focused(&self) -> bool {
3777 self.app.focused_view_id(self.window_id) == Some(self.view_id)
3778 }
3779
3780 pub fn is_child(&self, view: impl Into<AnyViewHandle>) -> bool {
3781 let view = view.into();
3782 if self.window_id != view.window_id {
3783 return false;
3784 }
3785 self.ancestors(view.window_id, view.view_id)
3786 .skip(1) // Skip self id
3787 .any(|parent| parent == self.view_id)
3788 }
3789
3790 pub fn blur(&mut self) {
3791 self.app.focus(self.window_id, None);
3792 }
3793
3794 pub fn set_window_title(&mut self, title: &str) {
3795 let window_id = self.window_id();
3796 if let Some((_, window)) = self.presenters_and_platform_windows.get_mut(&window_id) {
3797 window.set_title(title);
3798 }
3799 }
3800
3801 pub fn set_window_edited(&mut self, edited: bool) {
3802 let window_id = self.window_id();
3803 if let Some((_, window)) = self.presenters_and_platform_windows.get_mut(&window_id) {
3804 window.set_edited(edited);
3805 }
3806 }
3807
3808 pub fn on_window_should_close<F>(&mut self, mut callback: F)
3809 where
3810 F: 'static + FnMut(&mut T, &mut ViewContext<T>) -> bool,
3811 {
3812 let window_id = self.window_id();
3813 let view = self.weak_handle();
3814 self.pending_effects
3815 .push_back(Effect::WindowShouldCloseSubscription {
3816 window_id,
3817 callback: Box::new(move |cx| {
3818 if let Some(view) = view.upgrade(cx) {
3819 view.update(cx, |view, cx| callback(view, cx))
3820 } else {
3821 true
3822 }
3823 }),
3824 });
3825 }
3826
3827 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
3828 where
3829 S: Entity,
3830 F: FnOnce(&mut ModelContext<S>) -> S,
3831 {
3832 self.app.add_model(build_model)
3833 }
3834
3835 pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
3836 where
3837 S: View,
3838 F: FnOnce(&mut ViewContext<S>) -> S,
3839 {
3840 self.app
3841 .build_and_insert_view(self.window_id, ParentId::View(self.view_id), |cx| {
3842 Some(build_view(cx))
3843 })
3844 .unwrap()
3845 }
3846
3847 pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
3848 where
3849 S: View,
3850 F: FnOnce(&mut ViewContext<S>) -> Option<S>,
3851 {
3852 self.app
3853 .build_and_insert_view(self.window_id, ParentId::View(self.view_id), build_view)
3854 }
3855
3856 pub fn reparent(&mut self, view_handle: impl Into<AnyViewHandle>) {
3857 let view_handle = view_handle.into();
3858 if self.window_id != view_handle.window_id {
3859 panic!("Can't reparent view to a view from a different window");
3860 }
3861 self.cx
3862 .parents
3863 .remove(&(view_handle.window_id, view_handle.view_id));
3864 let new_parent_id = self.view_id;
3865 self.cx.parents.insert(
3866 (view_handle.window_id, view_handle.view_id),
3867 ParentId::View(new_parent_id),
3868 );
3869 }
3870
3871 pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
3872 where
3873 V: View,
3874 F: FnOnce(&mut ViewContext<V>) -> V,
3875 {
3876 let window_id = self.window_id;
3877 self.update(|this| {
3878 let root_view = this
3879 .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
3880 .unwrap();
3881 let window = this.cx.windows.get_mut(&window_id).unwrap();
3882 window.root_view = root_view.clone().into();
3883 window.focused_view_id = Some(root_view.id());
3884 root_view
3885 })
3886 }
3887
3888 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
3889 where
3890 E: Entity,
3891 E::Event: 'static,
3892 H: Handle<E>,
3893 F: 'static + FnMut(&mut T, H, &E::Event, &mut ViewContext<T>),
3894 {
3895 let subscriber = self.weak_handle();
3896 self.app
3897 .subscribe_internal(handle, move |emitter, event, cx| {
3898 if let Some(subscriber) = subscriber.upgrade(cx) {
3899 subscriber.update(cx, |subscriber, cx| {
3900 callback(subscriber, emitter, event, cx);
3901 });
3902 true
3903 } else {
3904 false
3905 }
3906 })
3907 }
3908
3909 pub fn observe<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
3910 where
3911 E: Entity,
3912 H: Handle<E>,
3913 F: 'static + FnMut(&mut T, H, &mut ViewContext<T>),
3914 {
3915 let observer = self.weak_handle();
3916 self.app.observe_internal(handle, move |observed, cx| {
3917 if let Some(observer) = observer.upgrade(cx) {
3918 observer.update(cx, |observer, cx| {
3919 callback(observer, observed, cx);
3920 });
3921 true
3922 } else {
3923 false
3924 }
3925 })
3926 }
3927
3928 pub fn observe_focus<F, V>(&mut self, handle: &ViewHandle<V>, mut callback: F) -> Subscription
3929 where
3930 F: 'static + FnMut(&mut T, ViewHandle<V>, bool, &mut ViewContext<T>),
3931 V: View,
3932 {
3933 let observer = self.weak_handle();
3934 self.app
3935 .observe_focus(handle, move |observed, focused, cx| {
3936 if let Some(observer) = observer.upgrade(cx) {
3937 observer.update(cx, |observer, cx| {
3938 callback(observer, observed, focused, cx);
3939 });
3940 true
3941 } else {
3942 false
3943 }
3944 })
3945 }
3946
3947 pub fn observe_release<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
3948 where
3949 E: Entity,
3950 H: Handle<E>,
3951 F: 'static + FnMut(&mut T, &E, &mut ViewContext<T>),
3952 {
3953 let observer = self.weak_handle();
3954 self.app.observe_release(handle, move |released, cx| {
3955 if let Some(observer) = observer.upgrade(cx) {
3956 observer.update(cx, |observer, cx| {
3957 callback(observer, released, cx);
3958 });
3959 }
3960 })
3961 }
3962
3963 pub fn observe_actions<F>(&mut self, mut callback: F) -> Subscription
3964 where
3965 F: 'static + FnMut(&mut T, TypeId, &mut ViewContext<T>),
3966 {
3967 let observer = self.weak_handle();
3968 self.app.observe_actions(move |action_id, cx| {
3969 if let Some(observer) = observer.upgrade(cx) {
3970 observer.update(cx, |observer, cx| {
3971 callback(observer, action_id, cx);
3972 });
3973 }
3974 })
3975 }
3976
3977 pub fn observe_window_activation<F>(&mut self, mut callback: F) -> Subscription
3978 where
3979 F: 'static + FnMut(&mut T, bool, &mut ViewContext<T>),
3980 {
3981 let observer = self.weak_handle();
3982 self.app
3983 .observe_window_activation(self.window_id(), move |active, cx| {
3984 if let Some(observer) = observer.upgrade(cx) {
3985 observer.update(cx, |observer, cx| {
3986 callback(observer, active, cx);
3987 });
3988 true
3989 } else {
3990 false
3991 }
3992 })
3993 }
3994
3995 pub fn observe_fullscreen<F>(&mut self, mut callback: F) -> Subscription
3996 where
3997 F: 'static + FnMut(&mut T, bool, &mut ViewContext<T>),
3998 {
3999 let observer = self.weak_handle();
4000 self.app
4001 .observe_fullscreen(self.window_id(), move |active, cx| {
4002 if let Some(observer) = observer.upgrade(cx) {
4003 observer.update(cx, |observer, cx| {
4004 callback(observer, active, cx);
4005 });
4006 true
4007 } else {
4008 false
4009 }
4010 })
4011 }
4012
4013 pub fn observe_keystroke<F>(&mut self, mut callback: F) -> Subscription
4014 where
4015 F: 'static
4016 + FnMut(
4017 &mut T,
4018 &Keystroke,
4019 Option<&Box<dyn Action>>,
4020 &MatchResult,
4021 &mut ViewContext<T>,
4022 ) -> bool,
4023 {
4024 let observer = self.weak_handle();
4025 self.app.observe_keystrokes(
4026 self.window_id(),
4027 move |keystroke, result, handled_by, cx| {
4028 if let Some(observer) = observer.upgrade(cx) {
4029 observer.update(cx, |observer, cx| {
4030 callback(observer, keystroke, handled_by, result, cx);
4031 });
4032 true
4033 } else {
4034 false
4035 }
4036 },
4037 )
4038 }
4039
4040 pub fn observe_window_bounds<F>(&mut self, mut callback: F) -> Subscription
4041 where
4042 F: 'static + FnMut(&mut T, WindowBounds, Uuid, &mut ViewContext<T>),
4043 {
4044 let observer = self.weak_handle();
4045 self.app
4046 .observe_window_bounds(self.window_id(), move |bounds, display, cx| {
4047 if let Some(observer) = observer.upgrade(cx) {
4048 observer.update(cx, |observer, cx| {
4049 callback(observer, bounds, display, cx);
4050 });
4051 true
4052 } else {
4053 false
4054 }
4055 })
4056 }
4057
4058 pub fn emit(&mut self, payload: T::Event) {
4059 self.app.pending_effects.push_back(Effect::Event {
4060 entity_id: self.view_id,
4061 payload: Box::new(payload),
4062 });
4063 }
4064
4065 pub fn notify(&mut self) {
4066 self.app.notify_view(self.window_id, self.view_id);
4067 }
4068
4069 pub fn dispatch_action(&mut self, action: impl Action) {
4070 self.app
4071 .dispatch_action_at(self.window_id, self.view_id, action)
4072 }
4073
4074 pub fn dispatch_any_action(&mut self, action: Box<dyn Action>) {
4075 self.app
4076 .dispatch_any_action_at(self.window_id, self.view_id, action)
4077 }
4078
4079 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>)) {
4080 let handle = self.handle();
4081 self.app.defer(move |cx| {
4082 handle.update(cx, |view, cx| {
4083 callback(view, cx);
4084 })
4085 })
4086 }
4087
4088 pub fn after_window_update(
4089 &mut self,
4090 callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>),
4091 ) {
4092 let handle = self.handle();
4093 self.app.after_window_update(move |cx| {
4094 handle.update(cx, |view, cx| {
4095 callback(view, cx);
4096 })
4097 })
4098 }
4099
4100 pub fn propagate_action(&mut self) {
4101 self.app.halt_action_dispatch = false;
4102 }
4103
4104 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
4105 where
4106 F: FnOnce(ViewHandle<T>, AsyncAppContext) -> Fut,
4107 Fut: 'static + Future<Output = S>,
4108 S: 'static,
4109 {
4110 let handle = self.handle();
4111 self.app.spawn(|cx| f(handle, cx))
4112 }
4113
4114 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
4115 where
4116 F: FnOnce(WeakViewHandle<T>, AsyncAppContext) -> Fut,
4117 Fut: 'static + Future<Output = S>,
4118 S: 'static,
4119 {
4120 let handle = self.weak_handle();
4121 self.app.spawn(|cx| f(handle, cx))
4122 }
4123}
4124
4125pub struct RenderParams {
4126 pub window_id: usize,
4127 pub view_id: usize,
4128 pub titlebar_height: f32,
4129 pub hovered_region_ids: HashSet<MouseRegionId>,
4130 pub clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
4131 pub refreshing: bool,
4132 pub appearance: Appearance,
4133}
4134
4135pub struct RenderContext<'a, T: View> {
4136 pub(crate) window_id: usize,
4137 pub(crate) view_id: usize,
4138 pub(crate) view_type: PhantomData<T>,
4139 pub(crate) hovered_region_ids: HashSet<MouseRegionId>,
4140 pub(crate) clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
4141 pub app: &'a mut MutableAppContext,
4142 pub titlebar_height: f32,
4143 pub appearance: Appearance,
4144 pub refreshing: bool,
4145}
4146
4147#[derive(Debug, Clone, Default)]
4148pub struct MouseState {
4149 hovered: bool,
4150 clicked: Option<MouseButton>,
4151 accessed_hovered: bool,
4152 accessed_clicked: bool,
4153}
4154
4155impl MouseState {
4156 pub fn hovered(&mut self) -> bool {
4157 self.accessed_hovered = true;
4158 self.hovered
4159 }
4160
4161 pub fn clicked(&mut self) -> Option<MouseButton> {
4162 self.accessed_clicked = true;
4163 self.clicked
4164 }
4165
4166 pub fn accessed_hovered(&self) -> bool {
4167 self.accessed_hovered
4168 }
4169
4170 pub fn accessed_clicked(&self) -> bool {
4171 self.accessed_clicked
4172 }
4173}
4174
4175impl<'a, V: View> RenderContext<'a, V> {
4176 fn new(params: RenderParams, app: &'a mut MutableAppContext) -> Self {
4177 Self {
4178 app,
4179 window_id: params.window_id,
4180 view_id: params.view_id,
4181 view_type: PhantomData,
4182 titlebar_height: params.titlebar_height,
4183 hovered_region_ids: params.hovered_region_ids.clone(),
4184 clicked_region_ids: params.clicked_region_ids.clone(),
4185 refreshing: params.refreshing,
4186 appearance: params.appearance,
4187 }
4188 }
4189
4190 pub fn handle(&self) -> WeakViewHandle<V> {
4191 WeakViewHandle::new(self.window_id, self.view_id)
4192 }
4193
4194 pub fn window_id(&self) -> usize {
4195 self.window_id
4196 }
4197
4198 pub fn view_id(&self) -> usize {
4199 self.view_id
4200 }
4201
4202 pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
4203 let region_id = MouseRegionId::new::<Tag>(self.view_id, region_id);
4204 MouseState {
4205 hovered: self.hovered_region_ids.contains(®ion_id),
4206 clicked: self.clicked_region_ids.as_ref().and_then(|(ids, button)| {
4207 if ids.contains(®ion_id) {
4208 Some(*button)
4209 } else {
4210 None
4211 }
4212 }),
4213 accessed_hovered: false,
4214 accessed_clicked: false,
4215 }
4216 }
4217
4218 pub fn element_state<Tag: 'static, T: 'static>(
4219 &mut self,
4220 element_id: usize,
4221 initial: T,
4222 ) -> ElementStateHandle<T> {
4223 let id = ElementStateId {
4224 view_id: self.view_id(),
4225 element_id,
4226 tag: TypeId::of::<Tag>(),
4227 };
4228 self.cx
4229 .element_states
4230 .entry(id)
4231 .or_insert_with(|| Box::new(initial));
4232 ElementStateHandle::new(id, self.frame_count, &self.cx.ref_counts)
4233 }
4234
4235 pub fn default_element_state<Tag: 'static, T: 'static + Default>(
4236 &mut self,
4237 element_id: usize,
4238 ) -> ElementStateHandle<T> {
4239 self.element_state::<Tag, T>(element_id, T::default())
4240 }
4241}
4242
4243impl AsRef<AppContext> for &AppContext {
4244 fn as_ref(&self) -> &AppContext {
4245 self
4246 }
4247}
4248
4249impl<V: View> Deref for RenderContext<'_, V> {
4250 type Target = MutableAppContext;
4251
4252 fn deref(&self) -> &Self::Target {
4253 self.app
4254 }
4255}
4256
4257impl<V: View> DerefMut for RenderContext<'_, V> {
4258 fn deref_mut(&mut self) -> &mut Self::Target {
4259 self.app
4260 }
4261}
4262
4263impl<V: View> ReadModel for RenderContext<'_, V> {
4264 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
4265 self.app.read_model(handle)
4266 }
4267}
4268
4269impl<V: View> UpdateModel for RenderContext<'_, V> {
4270 fn update_model<T: Entity, O>(
4271 &mut self,
4272 handle: &ModelHandle<T>,
4273 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
4274 ) -> O {
4275 self.app.update_model(handle, update)
4276 }
4277}
4278
4279impl<V: View> ReadView for RenderContext<'_, V> {
4280 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
4281 self.app.read_view(handle)
4282 }
4283}
4284
4285impl<M> AsRef<AppContext> for ViewContext<'_, M> {
4286 fn as_ref(&self) -> &AppContext {
4287 &self.app.cx
4288 }
4289}
4290
4291impl<M> Deref for ViewContext<'_, M> {
4292 type Target = MutableAppContext;
4293
4294 fn deref(&self) -> &Self::Target {
4295 self.app
4296 }
4297}
4298
4299impl<M> DerefMut for ViewContext<'_, M> {
4300 fn deref_mut(&mut self) -> &mut Self::Target {
4301 &mut self.app
4302 }
4303}
4304
4305impl<M> AsMut<MutableAppContext> for ViewContext<'_, M> {
4306 fn as_mut(&mut self) -> &mut MutableAppContext {
4307 self.app
4308 }
4309}
4310
4311impl<V> ReadModel for ViewContext<'_, V> {
4312 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
4313 self.app.read_model(handle)
4314 }
4315}
4316
4317impl<V> UpgradeModelHandle for ViewContext<'_, V> {
4318 fn upgrade_model_handle<T: Entity>(
4319 &self,
4320 handle: &WeakModelHandle<T>,
4321 ) -> Option<ModelHandle<T>> {
4322 self.cx.upgrade_model_handle(handle)
4323 }
4324
4325 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
4326 self.cx.model_handle_is_upgradable(handle)
4327 }
4328
4329 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
4330 self.cx.upgrade_any_model_handle(handle)
4331 }
4332}
4333
4334impl<V> UpgradeViewHandle for ViewContext<'_, V> {
4335 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
4336 self.cx.upgrade_view_handle(handle)
4337 }
4338
4339 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
4340 self.cx.upgrade_any_view_handle(handle)
4341 }
4342}
4343
4344impl<V: View> UpgradeViewHandle for RenderContext<'_, V> {
4345 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
4346 self.cx.upgrade_view_handle(handle)
4347 }
4348
4349 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
4350 self.cx.upgrade_any_view_handle(handle)
4351 }
4352}
4353
4354impl<V: View> UpdateModel for ViewContext<'_, V> {
4355 fn update_model<T: Entity, O>(
4356 &mut self,
4357 handle: &ModelHandle<T>,
4358 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
4359 ) -> O {
4360 self.app.update_model(handle, update)
4361 }
4362}
4363
4364impl<V: View> ReadView for ViewContext<'_, V> {
4365 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
4366 self.app.read_view(handle)
4367 }
4368}
4369
4370impl<V: View> UpdateView for ViewContext<'_, V> {
4371 fn update_view<T, S>(
4372 &mut self,
4373 handle: &ViewHandle<T>,
4374 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
4375 ) -> S
4376 where
4377 T: View,
4378 {
4379 self.app.update_view(handle, update)
4380 }
4381}
4382
4383pub trait Handle<T> {
4384 type Weak: 'static;
4385 fn id(&self) -> usize;
4386 fn location(&self) -> EntityLocation;
4387 fn downgrade(&self) -> Self::Weak;
4388 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4389 where
4390 Self: Sized;
4391}
4392
4393pub trait WeakHandle {
4394 fn id(&self) -> usize;
4395}
4396
4397#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
4398pub enum EntityLocation {
4399 Model(usize),
4400 View(usize, usize),
4401}
4402
4403pub struct ModelHandle<T: Entity> {
4404 model_id: usize,
4405 model_type: PhantomData<T>,
4406 ref_counts: Arc<Mutex<RefCounts>>,
4407
4408 #[cfg(any(test, feature = "test-support"))]
4409 handle_id: usize,
4410}
4411
4412impl<T: Entity> ModelHandle<T> {
4413 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4414 ref_counts.lock().inc_model(model_id);
4415
4416 #[cfg(any(test, feature = "test-support"))]
4417 let handle_id = ref_counts
4418 .lock()
4419 .leak_detector
4420 .lock()
4421 .handle_created(Some(type_name::<T>()), model_id);
4422
4423 Self {
4424 model_id,
4425 model_type: PhantomData,
4426 ref_counts: ref_counts.clone(),
4427
4428 #[cfg(any(test, feature = "test-support"))]
4429 handle_id,
4430 }
4431 }
4432
4433 pub fn downgrade(&self) -> WeakModelHandle<T> {
4434 WeakModelHandle::new(self.model_id)
4435 }
4436
4437 pub fn id(&self) -> usize {
4438 self.model_id
4439 }
4440
4441 pub fn read<'a, C: ReadModel>(&self, cx: &'a C) -> &'a T {
4442 cx.read_model(self)
4443 }
4444
4445 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
4446 where
4447 C: ReadModelWith,
4448 F: FnOnce(&T, &AppContext) -> S,
4449 {
4450 let mut read = Some(read);
4451 cx.read_model_with(self, &mut |model, cx| {
4452 let read = read.take().unwrap();
4453 read(model, cx)
4454 })
4455 }
4456
4457 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
4458 where
4459 C: UpdateModel,
4460 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
4461 {
4462 let mut update = Some(update);
4463 cx.update_model(self, &mut |model, cx| {
4464 let update = update.take().unwrap();
4465 update(model, cx)
4466 })
4467 }
4468}
4469
4470impl<T: Entity> Clone for ModelHandle<T> {
4471 fn clone(&self) -> Self {
4472 Self::new(self.model_id, &self.ref_counts)
4473 }
4474}
4475
4476impl<T: Entity> PartialEq for ModelHandle<T> {
4477 fn eq(&self, other: &Self) -> bool {
4478 self.model_id == other.model_id
4479 }
4480}
4481
4482impl<T: Entity> Eq for ModelHandle<T> {}
4483
4484impl<T: Entity> PartialEq<WeakModelHandle<T>> for ModelHandle<T> {
4485 fn eq(&self, other: &WeakModelHandle<T>) -> bool {
4486 self.model_id == other.model_id
4487 }
4488}
4489
4490impl<T: Entity> Hash for ModelHandle<T> {
4491 fn hash<H: Hasher>(&self, state: &mut H) {
4492 self.model_id.hash(state);
4493 }
4494}
4495
4496impl<T: Entity> std::borrow::Borrow<usize> for ModelHandle<T> {
4497 fn borrow(&self) -> &usize {
4498 &self.model_id
4499 }
4500}
4501
4502impl<T: Entity> Debug for ModelHandle<T> {
4503 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4504 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
4505 .field(&self.model_id)
4506 .finish()
4507 }
4508}
4509
4510unsafe impl<T: Entity> Send for ModelHandle<T> {}
4511unsafe impl<T: Entity> Sync for ModelHandle<T> {}
4512
4513impl<T: Entity> Drop for ModelHandle<T> {
4514 fn drop(&mut self) {
4515 let mut ref_counts = self.ref_counts.lock();
4516 ref_counts.dec_model(self.model_id);
4517
4518 #[cfg(any(test, feature = "test-support"))]
4519 ref_counts
4520 .leak_detector
4521 .lock()
4522 .handle_dropped(self.model_id, self.handle_id);
4523 }
4524}
4525
4526impl<T: Entity> Handle<T> for ModelHandle<T> {
4527 type Weak = WeakModelHandle<T>;
4528
4529 fn id(&self) -> usize {
4530 self.model_id
4531 }
4532
4533 fn location(&self) -> EntityLocation {
4534 EntityLocation::Model(self.model_id)
4535 }
4536
4537 fn downgrade(&self) -> Self::Weak {
4538 self.downgrade()
4539 }
4540
4541 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4542 where
4543 Self: Sized,
4544 {
4545 weak.upgrade(cx)
4546 }
4547}
4548
4549pub struct WeakModelHandle<T> {
4550 model_id: usize,
4551 model_type: PhantomData<T>,
4552}
4553
4554impl<T> WeakHandle for WeakModelHandle<T> {
4555 fn id(&self) -> usize {
4556 self.model_id
4557 }
4558}
4559
4560unsafe impl<T> Send for WeakModelHandle<T> {}
4561unsafe impl<T> Sync for WeakModelHandle<T> {}
4562
4563impl<T: Entity> WeakModelHandle<T> {
4564 fn new(model_id: usize) -> Self {
4565 Self {
4566 model_id,
4567 model_type: PhantomData,
4568 }
4569 }
4570
4571 pub fn id(&self) -> usize {
4572 self.model_id
4573 }
4574
4575 pub fn is_upgradable(&self, cx: &impl UpgradeModelHandle) -> bool {
4576 cx.model_handle_is_upgradable(self)
4577 }
4578
4579 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<ModelHandle<T>> {
4580 cx.upgrade_model_handle(self)
4581 }
4582}
4583
4584impl<T> Hash for WeakModelHandle<T> {
4585 fn hash<H: Hasher>(&self, state: &mut H) {
4586 self.model_id.hash(state)
4587 }
4588}
4589
4590impl<T> PartialEq for WeakModelHandle<T> {
4591 fn eq(&self, other: &Self) -> bool {
4592 self.model_id == other.model_id
4593 }
4594}
4595
4596impl<T> Eq for WeakModelHandle<T> {}
4597
4598impl<T: Entity> PartialEq<ModelHandle<T>> for WeakModelHandle<T> {
4599 fn eq(&self, other: &ModelHandle<T>) -> bool {
4600 self.model_id == other.model_id
4601 }
4602}
4603
4604impl<T> Clone for WeakModelHandle<T> {
4605 fn clone(&self) -> Self {
4606 Self {
4607 model_id: self.model_id,
4608 model_type: PhantomData,
4609 }
4610 }
4611}
4612
4613impl<T> Copy for WeakModelHandle<T> {}
4614
4615pub struct ViewHandle<T> {
4616 window_id: usize,
4617 view_id: usize,
4618 view_type: PhantomData<T>,
4619 ref_counts: Arc<Mutex<RefCounts>>,
4620 #[cfg(any(test, feature = "test-support"))]
4621 handle_id: usize,
4622}
4623
4624impl<T: View> ViewHandle<T> {
4625 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4626 ref_counts.lock().inc_view(window_id, view_id);
4627 #[cfg(any(test, feature = "test-support"))]
4628 let handle_id = ref_counts
4629 .lock()
4630 .leak_detector
4631 .lock()
4632 .handle_created(Some(type_name::<T>()), view_id);
4633
4634 Self {
4635 window_id,
4636 view_id,
4637 view_type: PhantomData,
4638 ref_counts: ref_counts.clone(),
4639
4640 #[cfg(any(test, feature = "test-support"))]
4641 handle_id,
4642 }
4643 }
4644
4645 pub fn downgrade(&self) -> WeakViewHandle<T> {
4646 WeakViewHandle::new(self.window_id, self.view_id)
4647 }
4648
4649 pub fn window_id(&self) -> usize {
4650 self.window_id
4651 }
4652
4653 pub fn id(&self) -> usize {
4654 self.view_id
4655 }
4656
4657 pub fn read<'a, C: ReadView>(&self, cx: &'a C) -> &'a T {
4658 cx.read_view(self)
4659 }
4660
4661 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
4662 where
4663 C: ReadViewWith,
4664 F: FnOnce(&T, &AppContext) -> S,
4665 {
4666 let mut read = Some(read);
4667 cx.read_view_with(self, &mut |view, cx| {
4668 let read = read.take().unwrap();
4669 read(view, cx)
4670 })
4671 }
4672
4673 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
4674 where
4675 C: UpdateView,
4676 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
4677 {
4678 let mut update = Some(update);
4679 cx.update_view(self, &mut |view, cx| {
4680 let update = update.take().unwrap();
4681 update(view, cx)
4682 })
4683 }
4684
4685 pub fn defer<C, F>(&self, cx: &mut C, update: F)
4686 where
4687 C: AsMut<MutableAppContext>,
4688 F: 'static + FnOnce(&mut T, &mut ViewContext<T>),
4689 {
4690 let this = self.clone();
4691 cx.as_mut().defer(move |cx| {
4692 this.update(cx, |view, cx| update(view, cx));
4693 });
4694 }
4695
4696 pub fn is_focused(&self, cx: &AppContext) -> bool {
4697 cx.focused_view_id(self.window_id)
4698 .map_or(false, |focused_id| focused_id == self.view_id)
4699 }
4700}
4701
4702impl<T: View> Clone for ViewHandle<T> {
4703 fn clone(&self) -> Self {
4704 ViewHandle::new(self.window_id, self.view_id, &self.ref_counts)
4705 }
4706}
4707
4708impl<T> PartialEq for ViewHandle<T> {
4709 fn eq(&self, other: &Self) -> bool {
4710 self.window_id == other.window_id && self.view_id == other.view_id
4711 }
4712}
4713
4714impl<T> PartialEq<WeakViewHandle<T>> for ViewHandle<T> {
4715 fn eq(&self, other: &WeakViewHandle<T>) -> bool {
4716 self.window_id == other.window_id && self.view_id == other.view_id
4717 }
4718}
4719
4720impl<T> PartialEq<ViewHandle<T>> for WeakViewHandle<T> {
4721 fn eq(&self, other: &ViewHandle<T>) -> bool {
4722 self.window_id == other.window_id && self.view_id == other.view_id
4723 }
4724}
4725
4726impl<T> Eq for ViewHandle<T> {}
4727
4728impl<T> Hash for ViewHandle<T> {
4729 fn hash<H: Hasher>(&self, state: &mut H) {
4730 self.window_id.hash(state);
4731 self.view_id.hash(state);
4732 }
4733}
4734
4735impl<T> Debug for ViewHandle<T> {
4736 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4737 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
4738 .field("window_id", &self.window_id)
4739 .field("view_id", &self.view_id)
4740 .finish()
4741 }
4742}
4743
4744impl<T> Drop for ViewHandle<T> {
4745 fn drop(&mut self) {
4746 self.ref_counts
4747 .lock()
4748 .dec_view(self.window_id, self.view_id);
4749 #[cfg(any(test, feature = "test-support"))]
4750 self.ref_counts
4751 .lock()
4752 .leak_detector
4753 .lock()
4754 .handle_dropped(self.view_id, self.handle_id);
4755 }
4756}
4757
4758impl<T: View> Handle<T> for ViewHandle<T> {
4759 type Weak = WeakViewHandle<T>;
4760
4761 fn id(&self) -> usize {
4762 self.view_id
4763 }
4764
4765 fn location(&self) -> EntityLocation {
4766 EntityLocation::View(self.window_id, self.view_id)
4767 }
4768
4769 fn downgrade(&self) -> Self::Weak {
4770 self.downgrade()
4771 }
4772
4773 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4774 where
4775 Self: Sized,
4776 {
4777 weak.upgrade(cx)
4778 }
4779}
4780
4781pub struct AnyViewHandle {
4782 window_id: usize,
4783 view_id: usize,
4784 view_type: TypeId,
4785 ref_counts: Arc<Mutex<RefCounts>>,
4786
4787 #[cfg(any(test, feature = "test-support"))]
4788 handle_id: usize,
4789}
4790
4791impl AnyViewHandle {
4792 fn new(
4793 window_id: usize,
4794 view_id: usize,
4795 view_type: TypeId,
4796 ref_counts: Arc<Mutex<RefCounts>>,
4797 ) -> Self {
4798 ref_counts.lock().inc_view(window_id, view_id);
4799
4800 #[cfg(any(test, feature = "test-support"))]
4801 let handle_id = ref_counts
4802 .lock()
4803 .leak_detector
4804 .lock()
4805 .handle_created(None, view_id);
4806
4807 Self {
4808 window_id,
4809 view_id,
4810 view_type,
4811 ref_counts,
4812 #[cfg(any(test, feature = "test-support"))]
4813 handle_id,
4814 }
4815 }
4816
4817 pub fn window_id(&self) -> usize {
4818 self.window_id
4819 }
4820
4821 pub fn id(&self) -> usize {
4822 self.view_id
4823 }
4824
4825 pub fn is<T: 'static>(&self) -> bool {
4826 TypeId::of::<T>() == self.view_type
4827 }
4828
4829 pub fn is_focused(&self, cx: &AppContext) -> bool {
4830 cx.focused_view_id(self.window_id)
4831 .map_or(false, |focused_id| focused_id == self.view_id)
4832 }
4833
4834 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
4835 if self.is::<T>() {
4836 let result = Some(ViewHandle {
4837 window_id: self.window_id,
4838 view_id: self.view_id,
4839 ref_counts: self.ref_counts.clone(),
4840 view_type: PhantomData,
4841 #[cfg(any(test, feature = "test-support"))]
4842 handle_id: self.handle_id,
4843 });
4844 unsafe {
4845 Arc::decrement_strong_count(Arc::as_ptr(&self.ref_counts));
4846 }
4847 std::mem::forget(self);
4848 result
4849 } else {
4850 None
4851 }
4852 }
4853
4854 pub fn downgrade(&self) -> AnyWeakViewHandle {
4855 AnyWeakViewHandle {
4856 window_id: self.window_id,
4857 view_id: self.view_id,
4858 view_type: self.view_type,
4859 }
4860 }
4861
4862 pub fn view_type(&self) -> TypeId {
4863 self.view_type
4864 }
4865
4866 pub fn debug_json(&self, cx: &AppContext) -> serde_json::Value {
4867 cx.views
4868 .get(&(self.window_id, self.view_id))
4869 .map_or_else(|| serde_json::Value::Null, |view| view.debug_json(cx))
4870 }
4871}
4872
4873impl Clone for AnyViewHandle {
4874 fn clone(&self) -> Self {
4875 Self::new(
4876 self.window_id,
4877 self.view_id,
4878 self.view_type,
4879 self.ref_counts.clone(),
4880 )
4881 }
4882}
4883
4884impl From<&AnyViewHandle> for AnyViewHandle {
4885 fn from(handle: &AnyViewHandle) -> Self {
4886 handle.clone()
4887 }
4888}
4889
4890impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
4891 fn from(handle: &ViewHandle<T>) -> Self {
4892 Self::new(
4893 handle.window_id,
4894 handle.view_id,
4895 TypeId::of::<T>(),
4896 handle.ref_counts.clone(),
4897 )
4898 }
4899}
4900
4901impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
4902 fn from(handle: ViewHandle<T>) -> Self {
4903 let any_handle = AnyViewHandle {
4904 window_id: handle.window_id,
4905 view_id: handle.view_id,
4906 view_type: TypeId::of::<T>(),
4907 ref_counts: handle.ref_counts.clone(),
4908 #[cfg(any(test, feature = "test-support"))]
4909 handle_id: handle.handle_id,
4910 };
4911
4912 unsafe {
4913 Arc::decrement_strong_count(Arc::as_ptr(&handle.ref_counts));
4914 }
4915 std::mem::forget(handle);
4916 any_handle
4917 }
4918}
4919
4920impl<T> PartialEq<ViewHandle<T>> for AnyViewHandle {
4921 fn eq(&self, other: &ViewHandle<T>) -> bool {
4922 self.window_id == other.window_id && self.view_id == other.view_id
4923 }
4924}
4925
4926impl Drop for AnyViewHandle {
4927 fn drop(&mut self) {
4928 self.ref_counts
4929 .lock()
4930 .dec_view(self.window_id, self.view_id);
4931 #[cfg(any(test, feature = "test-support"))]
4932 self.ref_counts
4933 .lock()
4934 .leak_detector
4935 .lock()
4936 .handle_dropped(self.view_id, self.handle_id);
4937 }
4938}
4939
4940pub struct AnyModelHandle {
4941 model_id: usize,
4942 model_type: TypeId,
4943 ref_counts: Arc<Mutex<RefCounts>>,
4944
4945 #[cfg(any(test, feature = "test-support"))]
4946 handle_id: usize,
4947}
4948
4949impl AnyModelHandle {
4950 fn new(model_id: usize, model_type: TypeId, ref_counts: Arc<Mutex<RefCounts>>) -> Self {
4951 ref_counts.lock().inc_model(model_id);
4952
4953 #[cfg(any(test, feature = "test-support"))]
4954 let handle_id = ref_counts
4955 .lock()
4956 .leak_detector
4957 .lock()
4958 .handle_created(None, model_id);
4959
4960 Self {
4961 model_id,
4962 model_type,
4963 ref_counts,
4964
4965 #[cfg(any(test, feature = "test-support"))]
4966 handle_id,
4967 }
4968 }
4969
4970 pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> {
4971 if self.is::<T>() {
4972 let result = Some(ModelHandle {
4973 model_id: self.model_id,
4974 model_type: PhantomData,
4975 ref_counts: self.ref_counts.clone(),
4976
4977 #[cfg(any(test, feature = "test-support"))]
4978 handle_id: self.handle_id,
4979 });
4980 unsafe {
4981 Arc::decrement_strong_count(Arc::as_ptr(&self.ref_counts));
4982 }
4983 std::mem::forget(self);
4984 result
4985 } else {
4986 None
4987 }
4988 }
4989
4990 pub fn downgrade(&self) -> AnyWeakModelHandle {
4991 AnyWeakModelHandle {
4992 model_id: self.model_id,
4993 model_type: self.model_type,
4994 }
4995 }
4996
4997 pub fn is<T: Entity>(&self) -> bool {
4998 self.model_type == TypeId::of::<T>()
4999 }
5000
5001 pub fn model_type(&self) -> TypeId {
5002 self.model_type
5003 }
5004}
5005
5006impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
5007 fn from(handle: ModelHandle<T>) -> Self {
5008 Self::new(
5009 handle.model_id,
5010 TypeId::of::<T>(),
5011 handle.ref_counts.clone(),
5012 )
5013 }
5014}
5015
5016impl Clone for AnyModelHandle {
5017 fn clone(&self) -> Self {
5018 Self::new(self.model_id, self.model_type, self.ref_counts.clone())
5019 }
5020}
5021
5022impl Drop for AnyModelHandle {
5023 fn drop(&mut self) {
5024 let mut ref_counts = self.ref_counts.lock();
5025 ref_counts.dec_model(self.model_id);
5026
5027 #[cfg(any(test, feature = "test-support"))]
5028 ref_counts
5029 .leak_detector
5030 .lock()
5031 .handle_dropped(self.model_id, self.handle_id);
5032 }
5033}
5034
5035#[derive(Hash, PartialEq, Eq, Debug)]
5036pub struct AnyWeakModelHandle {
5037 model_id: usize,
5038 model_type: TypeId,
5039}
5040
5041impl AnyWeakModelHandle {
5042 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<AnyModelHandle> {
5043 cx.upgrade_any_model_handle(self)
5044 }
5045 pub fn model_type(&self) -> TypeId {
5046 self.model_type
5047 }
5048
5049 fn is<T: 'static>(&self) -> bool {
5050 TypeId::of::<T>() == self.model_type
5051 }
5052
5053 pub fn downcast<T: Entity>(&self) -> Option<WeakModelHandle<T>> {
5054 if self.is::<T>() {
5055 let result = Some(WeakModelHandle {
5056 model_id: self.model_id,
5057 model_type: PhantomData,
5058 });
5059
5060 result
5061 } else {
5062 None
5063 }
5064 }
5065}
5066
5067impl<T: Entity> From<WeakModelHandle<T>> for AnyWeakModelHandle {
5068 fn from(handle: WeakModelHandle<T>) -> Self {
5069 AnyWeakModelHandle {
5070 model_id: handle.model_id,
5071 model_type: TypeId::of::<T>(),
5072 }
5073 }
5074}
5075
5076#[derive(Debug)]
5077pub struct WeakViewHandle<T> {
5078 window_id: usize,
5079 view_id: usize,
5080 view_type: PhantomData<T>,
5081}
5082
5083impl<T> WeakHandle for WeakViewHandle<T> {
5084 fn id(&self) -> usize {
5085 self.view_id
5086 }
5087}
5088
5089impl<T: View> WeakViewHandle<T> {
5090 fn new(window_id: usize, view_id: usize) -> Self {
5091 Self {
5092 window_id,
5093 view_id,
5094 view_type: PhantomData,
5095 }
5096 }
5097
5098 pub fn id(&self) -> usize {
5099 self.view_id
5100 }
5101
5102 pub fn window_id(&self) -> usize {
5103 self.window_id
5104 }
5105
5106 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<ViewHandle<T>> {
5107 cx.upgrade_view_handle(self)
5108 }
5109}
5110
5111impl<T> Clone for WeakViewHandle<T> {
5112 fn clone(&self) -> Self {
5113 Self {
5114 window_id: self.window_id,
5115 view_id: self.view_id,
5116 view_type: PhantomData,
5117 }
5118 }
5119}
5120
5121impl<T> PartialEq for WeakViewHandle<T> {
5122 fn eq(&self, other: &Self) -> bool {
5123 self.window_id == other.window_id && self.view_id == other.view_id
5124 }
5125}
5126
5127impl<T> Eq for WeakViewHandle<T> {}
5128
5129impl<T> Hash for WeakViewHandle<T> {
5130 fn hash<H: Hasher>(&self, state: &mut H) {
5131 self.window_id.hash(state);
5132 self.view_id.hash(state);
5133 }
5134}
5135
5136pub struct AnyWeakViewHandle {
5137 window_id: usize,
5138 view_id: usize,
5139 view_type: TypeId,
5140}
5141
5142impl AnyWeakViewHandle {
5143 pub fn id(&self) -> usize {
5144 self.view_id
5145 }
5146
5147 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<AnyViewHandle> {
5148 cx.upgrade_any_view_handle(self)
5149 }
5150}
5151
5152impl<T: View> From<WeakViewHandle<T>> for AnyWeakViewHandle {
5153 fn from(handle: WeakViewHandle<T>) -> Self {
5154 AnyWeakViewHandle {
5155 window_id: handle.window_id,
5156 view_id: handle.view_id,
5157 view_type: TypeId::of::<T>(),
5158 }
5159 }
5160}
5161
5162#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
5163pub struct ElementStateId {
5164 view_id: usize,
5165 element_id: usize,
5166 tag: TypeId,
5167}
5168
5169pub struct ElementStateHandle<T> {
5170 value_type: PhantomData<T>,
5171 id: ElementStateId,
5172 ref_counts: Weak<Mutex<RefCounts>>,
5173}
5174
5175impl<T: 'static> ElementStateHandle<T> {
5176 fn new(id: ElementStateId, frame_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
5177 ref_counts.lock().inc_element_state(id, frame_id);
5178 Self {
5179 value_type: PhantomData,
5180 id,
5181 ref_counts: Arc::downgrade(ref_counts),
5182 }
5183 }
5184
5185 pub fn id(&self) -> ElementStateId {
5186 self.id
5187 }
5188
5189 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
5190 cx.element_states
5191 .get(&self.id)
5192 .unwrap()
5193 .downcast_ref()
5194 .unwrap()
5195 }
5196
5197 pub fn update<C, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R
5198 where
5199 C: DerefMut<Target = MutableAppContext>,
5200 {
5201 let mut element_state = cx.deref_mut().cx.element_states.remove(&self.id).unwrap();
5202 let result = f(element_state.downcast_mut().unwrap(), cx);
5203 cx.deref_mut()
5204 .cx
5205 .element_states
5206 .insert(self.id, element_state);
5207 result
5208 }
5209}
5210
5211impl<T> Drop for ElementStateHandle<T> {
5212 fn drop(&mut self) {
5213 if let Some(ref_counts) = self.ref_counts.upgrade() {
5214 ref_counts.lock().dec_element_state(self.id);
5215 }
5216 }
5217}
5218
5219#[must_use]
5220pub enum Subscription {
5221 Subscription(callback_collection::Subscription<usize, SubscriptionCallback>),
5222 Observation(callback_collection::Subscription<usize, ObservationCallback>),
5223 GlobalSubscription(callback_collection::Subscription<TypeId, GlobalSubscriptionCallback>),
5224 GlobalObservation(callback_collection::Subscription<TypeId, GlobalObservationCallback>),
5225 FocusObservation(callback_collection::Subscription<usize, FocusObservationCallback>),
5226 WindowActivationObservation(callback_collection::Subscription<usize, WindowActivationCallback>),
5227 WindowFullscreenObservation(callback_collection::Subscription<usize, WindowFullscreenCallback>),
5228 WindowBoundsObservation(callback_collection::Subscription<usize, WindowBoundsCallback>),
5229 KeystrokeObservation(callback_collection::Subscription<usize, KeystrokeCallback>),
5230 ReleaseObservation(callback_collection::Subscription<usize, ReleaseObservationCallback>),
5231 ActionObservation(callback_collection::Subscription<(), ActionObservationCallback>),
5232}
5233
5234impl Subscription {
5235 pub fn id(&self) -> usize {
5236 match self {
5237 Subscription::Subscription(subscription) => subscription.id(),
5238 Subscription::Observation(subscription) => subscription.id(),
5239 Subscription::GlobalSubscription(subscription) => subscription.id(),
5240 Subscription::GlobalObservation(subscription) => subscription.id(),
5241 Subscription::FocusObservation(subscription) => subscription.id(),
5242 Subscription::WindowActivationObservation(subscription) => subscription.id(),
5243 Subscription::WindowFullscreenObservation(subscription) => subscription.id(),
5244 Subscription::WindowBoundsObservation(subscription) => subscription.id(),
5245 Subscription::KeystrokeObservation(subscription) => subscription.id(),
5246 Subscription::ReleaseObservation(subscription) => subscription.id(),
5247 Subscription::ActionObservation(subscription) => subscription.id(),
5248 }
5249 }
5250
5251 pub fn detach(&mut self) {
5252 match self {
5253 Subscription::Subscription(subscription) => subscription.detach(),
5254 Subscription::GlobalSubscription(subscription) => subscription.detach(),
5255 Subscription::Observation(subscription) => subscription.detach(),
5256 Subscription::GlobalObservation(subscription) => subscription.detach(),
5257 Subscription::FocusObservation(subscription) => subscription.detach(),
5258 Subscription::KeystrokeObservation(subscription) => subscription.detach(),
5259 Subscription::WindowActivationObservation(subscription) => subscription.detach(),
5260 Subscription::WindowFullscreenObservation(subscription) => subscription.detach(),
5261 Subscription::WindowBoundsObservation(subscription) => subscription.detach(),
5262 Subscription::ReleaseObservation(subscription) => subscription.detach(),
5263 Subscription::ActionObservation(subscription) => subscription.detach(),
5264 }
5265 }
5266}
5267
5268lazy_static! {
5269 static ref LEAK_BACKTRACE: bool =
5270 std::env::var("LEAK_BACKTRACE").map_or(false, |b| !b.is_empty());
5271}
5272
5273#[cfg(any(test, feature = "test-support"))]
5274#[derive(Default)]
5275pub struct LeakDetector {
5276 next_handle_id: usize,
5277 #[allow(clippy::type_complexity)]
5278 handle_backtraces: HashMap<
5279 usize,
5280 (
5281 Option<&'static str>,
5282 HashMap<usize, Option<backtrace::Backtrace>>,
5283 ),
5284 >,
5285}
5286
5287#[cfg(any(test, feature = "test-support"))]
5288impl LeakDetector {
5289 fn handle_created(&mut self, type_name: Option<&'static str>, entity_id: usize) -> usize {
5290 let handle_id = post_inc(&mut self.next_handle_id);
5291 let entry = self.handle_backtraces.entry(entity_id).or_default();
5292 let backtrace = if *LEAK_BACKTRACE {
5293 Some(backtrace::Backtrace::new_unresolved())
5294 } else {
5295 None
5296 };
5297 if let Some(type_name) = type_name {
5298 entry.0.get_or_insert(type_name);
5299 }
5300 entry.1.insert(handle_id, backtrace);
5301 handle_id
5302 }
5303
5304 fn handle_dropped(&mut self, entity_id: usize, handle_id: usize) {
5305 if let Some((_, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
5306 assert!(backtraces.remove(&handle_id).is_some());
5307 if backtraces.is_empty() {
5308 self.handle_backtraces.remove(&entity_id);
5309 }
5310 }
5311 }
5312
5313 pub fn assert_dropped(&mut self, entity_id: usize) {
5314 if let Some((type_name, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
5315 for trace in backtraces.values_mut().flatten() {
5316 trace.resolve();
5317 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
5318 }
5319
5320 let hint = if *LEAK_BACKTRACE {
5321 ""
5322 } else {
5323 " – set LEAK_BACKTRACE=1 for more information"
5324 };
5325
5326 panic!(
5327 "{} handles to {} {} still exist{}",
5328 backtraces.len(),
5329 type_name.unwrap_or("entity"),
5330 entity_id,
5331 hint
5332 );
5333 }
5334 }
5335
5336 pub fn detect(&mut self) {
5337 let mut found_leaks = false;
5338 for (id, (type_name, backtraces)) in self.handle_backtraces.iter_mut() {
5339 eprintln!(
5340 "leaked {} handles to {} {}",
5341 backtraces.len(),
5342 type_name.unwrap_or("entity"),
5343 id
5344 );
5345 for trace in backtraces.values_mut().flatten() {
5346 trace.resolve();
5347 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
5348 }
5349 found_leaks = true;
5350 }
5351
5352 let hint = if *LEAK_BACKTRACE {
5353 ""
5354 } else {
5355 " – set LEAK_BACKTRACE=1 for more information"
5356 };
5357 assert!(!found_leaks, "detected leaked handles{}", hint);
5358 }
5359}
5360
5361#[derive(Default)]
5362struct RefCounts {
5363 entity_counts: HashMap<usize, usize>,
5364 element_state_counts: HashMap<ElementStateId, ElementStateRefCount>,
5365 dropped_models: HashSet<usize>,
5366 dropped_views: HashSet<(usize, usize)>,
5367 dropped_element_states: HashSet<ElementStateId>,
5368
5369 #[cfg(any(test, feature = "test-support"))]
5370 leak_detector: Arc<Mutex<LeakDetector>>,
5371}
5372
5373struct ElementStateRefCount {
5374 ref_count: usize,
5375 frame_id: usize,
5376}
5377
5378impl RefCounts {
5379 fn inc_model(&mut self, model_id: usize) {
5380 match self.entity_counts.entry(model_id) {
5381 Entry::Occupied(mut entry) => {
5382 *entry.get_mut() += 1;
5383 }
5384 Entry::Vacant(entry) => {
5385 entry.insert(1);
5386 self.dropped_models.remove(&model_id);
5387 }
5388 }
5389 }
5390
5391 fn inc_view(&mut self, window_id: usize, view_id: usize) {
5392 match self.entity_counts.entry(view_id) {
5393 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
5394 Entry::Vacant(entry) => {
5395 entry.insert(1);
5396 self.dropped_views.remove(&(window_id, view_id));
5397 }
5398 }
5399 }
5400
5401 fn inc_element_state(&mut self, id: ElementStateId, frame_id: usize) {
5402 match self.element_state_counts.entry(id) {
5403 Entry::Occupied(mut entry) => {
5404 let entry = entry.get_mut();
5405 if entry.frame_id == frame_id || entry.ref_count >= 2 {
5406 panic!("used the same element state more than once in the same frame");
5407 }
5408 entry.ref_count += 1;
5409 entry.frame_id = frame_id;
5410 }
5411 Entry::Vacant(entry) => {
5412 entry.insert(ElementStateRefCount {
5413 ref_count: 1,
5414 frame_id,
5415 });
5416 self.dropped_element_states.remove(&id);
5417 }
5418 }
5419 }
5420
5421 fn dec_model(&mut self, model_id: usize) {
5422 let count = self.entity_counts.get_mut(&model_id).unwrap();
5423 *count -= 1;
5424 if *count == 0 {
5425 self.entity_counts.remove(&model_id);
5426 self.dropped_models.insert(model_id);
5427 }
5428 }
5429
5430 fn dec_view(&mut self, window_id: usize, view_id: usize) {
5431 let count = self.entity_counts.get_mut(&view_id).unwrap();
5432 *count -= 1;
5433 if *count == 0 {
5434 self.entity_counts.remove(&view_id);
5435 self.dropped_views.insert((window_id, view_id));
5436 }
5437 }
5438
5439 fn dec_element_state(&mut self, id: ElementStateId) {
5440 let entry = self.element_state_counts.get_mut(&id).unwrap();
5441 entry.ref_count -= 1;
5442 if entry.ref_count == 0 {
5443 self.element_state_counts.remove(&id);
5444 self.dropped_element_states.insert(id);
5445 }
5446 }
5447
5448 fn is_entity_alive(&self, entity_id: usize) -> bool {
5449 self.entity_counts.contains_key(&entity_id)
5450 }
5451
5452 fn take_dropped(
5453 &mut self,
5454 ) -> (
5455 HashSet<usize>,
5456 HashSet<(usize, usize)>,
5457 HashSet<ElementStateId>,
5458 ) {
5459 (
5460 std::mem::take(&mut self.dropped_models),
5461 std::mem::take(&mut self.dropped_views),
5462 std::mem::take(&mut self.dropped_element_states),
5463 )
5464 }
5465}
5466
5467#[cfg(test)]
5468mod tests {
5469 use super::*;
5470 use crate::{actions, elements::*, impl_actions, MouseButton, MouseButtonEvent};
5471 use serde::Deserialize;
5472 use smol::future::poll_once;
5473 use std::{
5474 cell::Cell,
5475 sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
5476 };
5477
5478 #[crate::test(self)]
5479 fn test_model_handles(cx: &mut MutableAppContext) {
5480 struct Model {
5481 other: Option<ModelHandle<Model>>,
5482 events: Vec<String>,
5483 }
5484
5485 impl Entity for Model {
5486 type Event = usize;
5487 }
5488
5489 impl Model {
5490 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
5491 if let Some(other) = other.as_ref() {
5492 cx.observe(other, |me, _, _| {
5493 me.events.push("notified".into());
5494 })
5495 .detach();
5496 cx.subscribe(other, |me, _, event, _| {
5497 me.events.push(format!("observed event {}", event));
5498 })
5499 .detach();
5500 }
5501
5502 Self {
5503 other,
5504 events: Vec::new(),
5505 }
5506 }
5507 }
5508
5509 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
5510 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
5511 assert_eq!(cx.cx.models.len(), 2);
5512
5513 handle_1.update(cx, |model, cx| {
5514 model.events.push("updated".into());
5515 cx.emit(1);
5516 cx.notify();
5517 cx.emit(2);
5518 });
5519 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5520 assert_eq!(
5521 handle_2.read(cx).events,
5522 vec![
5523 "observed event 1".to_string(),
5524 "notified".to_string(),
5525 "observed event 2".to_string(),
5526 ]
5527 );
5528
5529 handle_2.update(cx, |model, _| {
5530 drop(handle_1);
5531 model.other.take();
5532 });
5533
5534 assert_eq!(cx.cx.models.len(), 1);
5535 assert!(cx.subscriptions.is_empty());
5536 assert!(cx.observations.is_empty());
5537 }
5538
5539 #[crate::test(self)]
5540 fn test_model_events(cx: &mut MutableAppContext) {
5541 #[derive(Default)]
5542 struct Model {
5543 events: Vec<usize>,
5544 }
5545
5546 impl Entity for Model {
5547 type Event = usize;
5548 }
5549
5550 let handle_1 = cx.add_model(|_| Model::default());
5551 let handle_2 = cx.add_model(|_| Model::default());
5552
5553 handle_1.update(cx, |_, cx| {
5554 cx.subscribe(&handle_2, move |model: &mut Model, emitter, event, cx| {
5555 model.events.push(*event);
5556
5557 cx.subscribe(&emitter, |model, _, event, _| {
5558 model.events.push(*event * 2);
5559 })
5560 .detach();
5561 })
5562 .detach();
5563 });
5564
5565 handle_2.update(cx, |_, c| c.emit(7));
5566 assert_eq!(handle_1.read(cx).events, vec![7]);
5567
5568 handle_2.update(cx, |_, c| c.emit(5));
5569 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
5570 }
5571
5572 #[crate::test(self)]
5573 fn test_model_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
5574 #[derive(Default)]
5575 struct Model;
5576
5577 impl Entity for Model {
5578 type Event = ();
5579 }
5580
5581 let events = Rc::new(RefCell::new(Vec::new()));
5582 cx.add_model(|cx| {
5583 drop(cx.subscribe(&cx.handle(), {
5584 let events = events.clone();
5585 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
5586 }));
5587 cx.subscribe(&cx.handle(), {
5588 let events = events.clone();
5589 move |_, _, _, _| events.borrow_mut().push("before emit")
5590 })
5591 .detach();
5592 cx.emit(());
5593 cx.subscribe(&cx.handle(), {
5594 let events = events.clone();
5595 move |_, _, _, _| events.borrow_mut().push("after emit")
5596 })
5597 .detach();
5598 Model
5599 });
5600 assert_eq!(*events.borrow(), ["before emit"]);
5601 }
5602
5603 #[crate::test(self)]
5604 fn test_observe_and_notify_from_model(cx: &mut MutableAppContext) {
5605 #[derive(Default)]
5606 struct Model {
5607 count: usize,
5608 events: Vec<usize>,
5609 }
5610
5611 impl Entity for Model {
5612 type Event = ();
5613 }
5614
5615 let handle_1 = cx.add_model(|_| Model::default());
5616 let handle_2 = cx.add_model(|_| Model::default());
5617
5618 handle_1.update(cx, |_, c| {
5619 c.observe(&handle_2, move |model, observed, c| {
5620 model.events.push(observed.read(c).count);
5621 c.observe(&observed, |model, observed, c| {
5622 model.events.push(observed.read(c).count * 2);
5623 })
5624 .detach();
5625 })
5626 .detach();
5627 });
5628
5629 handle_2.update(cx, |model, c| {
5630 model.count = 7;
5631 c.notify()
5632 });
5633 assert_eq!(handle_1.read(cx).events, vec![7]);
5634
5635 handle_2.update(cx, |model, c| {
5636 model.count = 5;
5637 c.notify()
5638 });
5639 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10])
5640 }
5641
5642 #[crate::test(self)]
5643 fn test_model_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
5644 #[derive(Default)]
5645 struct Model;
5646
5647 impl Entity for Model {
5648 type Event = ();
5649 }
5650
5651 let events = Rc::new(RefCell::new(Vec::new()));
5652 cx.add_model(|cx| {
5653 drop(cx.observe(&cx.handle(), {
5654 let events = events.clone();
5655 move |_, _, _| events.borrow_mut().push("dropped before flush")
5656 }));
5657 cx.observe(&cx.handle(), {
5658 let events = events.clone();
5659 move |_, _, _| events.borrow_mut().push("before notify")
5660 })
5661 .detach();
5662 cx.notify();
5663 cx.observe(&cx.handle(), {
5664 let events = events.clone();
5665 move |_, _, _| events.borrow_mut().push("after notify")
5666 })
5667 .detach();
5668 Model
5669 });
5670 assert_eq!(*events.borrow(), ["before notify"]);
5671 }
5672
5673 #[crate::test(self)]
5674 fn test_defer_and_after_window_update(cx: &mut MutableAppContext) {
5675 struct View {
5676 render_count: usize,
5677 }
5678
5679 impl Entity for View {
5680 type Event = usize;
5681 }
5682
5683 impl super::View for View {
5684 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5685 post_inc(&mut self.render_count);
5686 Empty::new().boxed()
5687 }
5688
5689 fn ui_name() -> &'static str {
5690 "View"
5691 }
5692 }
5693
5694 let (_, view) = cx.add_window(Default::default(), |_| View { render_count: 0 });
5695 let called_defer = Rc::new(AtomicBool::new(false));
5696 let called_after_window_update = Rc::new(AtomicBool::new(false));
5697
5698 view.update(cx, |this, cx| {
5699 assert_eq!(this.render_count, 1);
5700 cx.defer({
5701 let called_defer = called_defer.clone();
5702 move |this, _| {
5703 assert_eq!(this.render_count, 1);
5704 called_defer.store(true, SeqCst);
5705 }
5706 });
5707 cx.after_window_update({
5708 let called_after_window_update = called_after_window_update.clone();
5709 move |this, cx| {
5710 assert_eq!(this.render_count, 2);
5711 called_after_window_update.store(true, SeqCst);
5712 cx.notify();
5713 }
5714 });
5715 assert!(!called_defer.load(SeqCst));
5716 assert!(!called_after_window_update.load(SeqCst));
5717 cx.notify();
5718 });
5719
5720 assert!(called_defer.load(SeqCst));
5721 assert!(called_after_window_update.load(SeqCst));
5722 assert_eq!(view.read(cx).render_count, 3);
5723 }
5724
5725 #[crate::test(self)]
5726 fn test_view_handles(cx: &mut MutableAppContext) {
5727 struct View {
5728 other: Option<ViewHandle<View>>,
5729 events: Vec<String>,
5730 }
5731
5732 impl Entity for View {
5733 type Event = usize;
5734 }
5735
5736 impl super::View for View {
5737 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5738 Empty::new().boxed()
5739 }
5740
5741 fn ui_name() -> &'static str {
5742 "View"
5743 }
5744 }
5745
5746 impl View {
5747 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
5748 if let Some(other) = other.as_ref() {
5749 cx.subscribe(other, |me, _, event, _| {
5750 me.events.push(format!("observed event {}", event));
5751 })
5752 .detach();
5753 }
5754 Self {
5755 other,
5756 events: Vec::new(),
5757 }
5758 }
5759 }
5760
5761 let (_, root_view) = cx.add_window(Default::default(), |cx| View::new(None, cx));
5762 let handle_1 = cx.add_view(&root_view, |cx| View::new(None, cx));
5763 let handle_2 = cx.add_view(&root_view, |cx| View::new(Some(handle_1.clone()), cx));
5764 assert_eq!(cx.cx.views.len(), 3);
5765
5766 handle_1.update(cx, |view, cx| {
5767 view.events.push("updated".into());
5768 cx.emit(1);
5769 cx.emit(2);
5770 });
5771 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5772 assert_eq!(
5773 handle_2.read(cx).events,
5774 vec![
5775 "observed event 1".to_string(),
5776 "observed event 2".to_string(),
5777 ]
5778 );
5779
5780 handle_2.update(cx, |view, _| {
5781 drop(handle_1);
5782 view.other.take();
5783 });
5784
5785 assert_eq!(cx.cx.views.len(), 2);
5786 assert!(cx.subscriptions.is_empty());
5787 assert!(cx.observations.is_empty());
5788 }
5789
5790 #[crate::test(self)]
5791 fn test_add_window(cx: &mut MutableAppContext) {
5792 struct View {
5793 mouse_down_count: Arc<AtomicUsize>,
5794 }
5795
5796 impl Entity for View {
5797 type Event = ();
5798 }
5799
5800 impl super::View for View {
5801 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
5802 enum Handler {}
5803 let mouse_down_count = self.mouse_down_count.clone();
5804 MouseEventHandler::<Handler>::new(0, cx, |_, _| Empty::new().boxed())
5805 .on_down(MouseButton::Left, move |_, _| {
5806 mouse_down_count.fetch_add(1, SeqCst);
5807 })
5808 .boxed()
5809 }
5810
5811 fn ui_name() -> &'static str {
5812 "View"
5813 }
5814 }
5815
5816 let mouse_down_count = Arc::new(AtomicUsize::new(0));
5817 let (window_id, _) = cx.add_window(Default::default(), |_| View {
5818 mouse_down_count: mouse_down_count.clone(),
5819 });
5820 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
5821 // Ensure window's root element is in a valid lifecycle state.
5822 presenter.borrow_mut().dispatch_event(
5823 Event::MouseDown(MouseButtonEvent {
5824 position: Default::default(),
5825 button: MouseButton::Left,
5826 modifiers: Default::default(),
5827 click_count: 1,
5828 }),
5829 false,
5830 cx,
5831 );
5832 assert_eq!(mouse_down_count.load(SeqCst), 1);
5833 }
5834
5835 #[crate::test(self)]
5836 fn test_entity_release_hooks(cx: &mut MutableAppContext) {
5837 struct Model {
5838 released: Rc<Cell<bool>>,
5839 }
5840
5841 struct View {
5842 released: Rc<Cell<bool>>,
5843 }
5844
5845 impl Entity for Model {
5846 type Event = ();
5847
5848 fn release(&mut self, _: &mut MutableAppContext) {
5849 self.released.set(true);
5850 }
5851 }
5852
5853 impl Entity for View {
5854 type Event = ();
5855
5856 fn release(&mut self, _: &mut MutableAppContext) {
5857 self.released.set(true);
5858 }
5859 }
5860
5861 impl super::View for View {
5862 fn ui_name() -> &'static str {
5863 "View"
5864 }
5865
5866 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5867 Empty::new().boxed()
5868 }
5869 }
5870
5871 let model_released = Rc::new(Cell::new(false));
5872 let model_release_observed = Rc::new(Cell::new(false));
5873 let view_released = Rc::new(Cell::new(false));
5874 let view_release_observed = Rc::new(Cell::new(false));
5875
5876 let model = cx.add_model(|_| Model {
5877 released: model_released.clone(),
5878 });
5879 let (window_id, view) = cx.add_window(Default::default(), |_| View {
5880 released: view_released.clone(),
5881 });
5882 assert!(!model_released.get());
5883 assert!(!view_released.get());
5884
5885 cx.observe_release(&model, {
5886 let model_release_observed = model_release_observed.clone();
5887 move |_, _| model_release_observed.set(true)
5888 })
5889 .detach();
5890 cx.observe_release(&view, {
5891 let view_release_observed = view_release_observed.clone();
5892 move |_, _| view_release_observed.set(true)
5893 })
5894 .detach();
5895
5896 cx.update(move |_| {
5897 drop(model);
5898 });
5899 assert!(model_released.get());
5900 assert!(model_release_observed.get());
5901
5902 drop(view);
5903 cx.remove_window(window_id);
5904 assert!(view_released.get());
5905 assert!(view_release_observed.get());
5906 }
5907
5908 #[crate::test(self)]
5909 fn test_view_events(cx: &mut MutableAppContext) {
5910 struct Model;
5911
5912 impl Entity for Model {
5913 type Event = String;
5914 }
5915
5916 let (_, handle_1) = cx.add_window(Default::default(), |_| TestView::default());
5917 let handle_2 = cx.add_view(&handle_1, |_| TestView::default());
5918 let handle_3 = cx.add_model(|_| Model);
5919
5920 handle_1.update(cx, |_, cx| {
5921 cx.subscribe(&handle_2, move |me, emitter, event, cx| {
5922 me.events.push(event.clone());
5923
5924 cx.subscribe(&emitter, |me, _, event, _| {
5925 me.events.push(format!("{event} from inner"));
5926 })
5927 .detach();
5928 })
5929 .detach();
5930
5931 cx.subscribe(&handle_3, |me, _, event, _| {
5932 me.events.push(event.clone());
5933 })
5934 .detach();
5935 });
5936
5937 handle_2.update(cx, |_, c| c.emit("7".into()));
5938 assert_eq!(handle_1.read(cx).events, vec!["7"]);
5939
5940 handle_2.update(cx, |_, c| c.emit("5".into()));
5941 assert_eq!(handle_1.read(cx).events, vec!["7", "5", "5 from inner"]);
5942
5943 handle_3.update(cx, |_, c| c.emit("9".into()));
5944 assert_eq!(
5945 handle_1.read(cx).events,
5946 vec!["7", "5", "5 from inner", "9"]
5947 );
5948 }
5949
5950 #[crate::test(self)]
5951 fn test_global_events(cx: &mut MutableAppContext) {
5952 #[derive(Clone, Debug, Eq, PartialEq)]
5953 struct GlobalEvent(u64);
5954
5955 let events = Rc::new(RefCell::new(Vec::new()));
5956 let first_subscription;
5957 let second_subscription;
5958
5959 {
5960 let events = events.clone();
5961 first_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
5962 events.borrow_mut().push(("First", e.clone()));
5963 });
5964 }
5965
5966 {
5967 let events = events.clone();
5968 second_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
5969 events.borrow_mut().push(("Second", e.clone()));
5970 });
5971 }
5972
5973 cx.update(|cx| {
5974 cx.emit_global(GlobalEvent(1));
5975 cx.emit_global(GlobalEvent(2));
5976 });
5977
5978 drop(first_subscription);
5979
5980 cx.update(|cx| {
5981 cx.emit_global(GlobalEvent(3));
5982 });
5983
5984 drop(second_subscription);
5985
5986 cx.update(|cx| {
5987 cx.emit_global(GlobalEvent(4));
5988 });
5989
5990 assert_eq!(
5991 &*events.borrow(),
5992 &[
5993 ("First", GlobalEvent(1)),
5994 ("Second", GlobalEvent(1)),
5995 ("First", GlobalEvent(2)),
5996 ("Second", GlobalEvent(2)),
5997 ("Second", GlobalEvent(3)),
5998 ]
5999 );
6000 }
6001
6002 #[crate::test(self)]
6003 fn test_global_events_emitted_before_subscription_in_same_update_cycle(
6004 cx: &mut MutableAppContext,
6005 ) {
6006 let events = Rc::new(RefCell::new(Vec::new()));
6007 cx.update(|cx| {
6008 {
6009 let events = events.clone();
6010 drop(cx.subscribe_global(move |_: &(), _| {
6011 events.borrow_mut().push("dropped before emit");
6012 }));
6013 }
6014
6015 {
6016 let events = events.clone();
6017 cx.subscribe_global(move |_: &(), _| {
6018 events.borrow_mut().push("before emit");
6019 })
6020 .detach();
6021 }
6022
6023 cx.emit_global(());
6024
6025 {
6026 let events = events.clone();
6027 cx.subscribe_global(move |_: &(), _| {
6028 events.borrow_mut().push("after emit");
6029 })
6030 .detach();
6031 }
6032 });
6033
6034 assert_eq!(*events.borrow(), ["before emit"]);
6035 }
6036
6037 #[crate::test(self)]
6038 fn test_global_nested_events(cx: &mut MutableAppContext) {
6039 #[derive(Clone, Debug, Eq, PartialEq)]
6040 struct GlobalEvent(u64);
6041
6042 let events = Rc::new(RefCell::new(Vec::new()));
6043
6044 {
6045 let events = events.clone();
6046 cx.subscribe_global(move |e: &GlobalEvent, cx| {
6047 events.borrow_mut().push(("Outer", e.clone()));
6048
6049 if e.0 == 1 {
6050 let events = events.clone();
6051 cx.subscribe_global(move |e: &GlobalEvent, _| {
6052 events.borrow_mut().push(("Inner", e.clone()));
6053 })
6054 .detach();
6055 }
6056 })
6057 .detach();
6058 }
6059
6060 cx.update(|cx| {
6061 cx.emit_global(GlobalEvent(1));
6062 cx.emit_global(GlobalEvent(2));
6063 cx.emit_global(GlobalEvent(3));
6064 });
6065 cx.update(|cx| {
6066 cx.emit_global(GlobalEvent(4));
6067 });
6068
6069 assert_eq!(
6070 &*events.borrow(),
6071 &[
6072 ("Outer", GlobalEvent(1)),
6073 ("Outer", GlobalEvent(2)),
6074 ("Outer", GlobalEvent(3)),
6075 ("Outer", GlobalEvent(4)),
6076 ("Inner", GlobalEvent(4)),
6077 ]
6078 );
6079 }
6080
6081 #[crate::test(self)]
6082 fn test_global(cx: &mut MutableAppContext) {
6083 type Global = usize;
6084
6085 let observation_count = Rc::new(RefCell::new(0));
6086 let subscription = cx.observe_global::<Global, _>({
6087 let observation_count = observation_count.clone();
6088 move |_| {
6089 *observation_count.borrow_mut() += 1;
6090 }
6091 });
6092
6093 assert!(!cx.has_global::<Global>());
6094 assert_eq!(cx.default_global::<Global>(), &0);
6095 assert_eq!(*observation_count.borrow(), 1);
6096 assert!(cx.has_global::<Global>());
6097 assert_eq!(
6098 cx.update_global::<Global, _, _>(|global, _| {
6099 *global = 1;
6100 "Update Result"
6101 }),
6102 "Update Result"
6103 );
6104 assert_eq!(*observation_count.borrow(), 2);
6105 assert_eq!(cx.global::<Global>(), &1);
6106
6107 drop(subscription);
6108 cx.update_global::<Global, _, _>(|global, _| {
6109 *global = 2;
6110 });
6111 assert_eq!(*observation_count.borrow(), 2);
6112
6113 type OtherGlobal = f32;
6114
6115 let observation_count = Rc::new(RefCell::new(0));
6116 cx.observe_global::<OtherGlobal, _>({
6117 let observation_count = observation_count.clone();
6118 move |_| {
6119 *observation_count.borrow_mut() += 1;
6120 }
6121 })
6122 .detach();
6123
6124 assert_eq!(
6125 cx.update_default_global::<OtherGlobal, _, _>(|global, _| {
6126 assert_eq!(global, &0.0);
6127 *global = 2.0;
6128 "Default update result"
6129 }),
6130 "Default update result"
6131 );
6132 assert_eq!(cx.global::<OtherGlobal>(), &2.0);
6133 assert_eq!(*observation_count.borrow(), 1);
6134 }
6135
6136 #[crate::test(self)]
6137 fn test_dropping_subscribers(cx: &mut MutableAppContext) {
6138 struct Model;
6139
6140 impl Entity for Model {
6141 type Event = ();
6142 }
6143
6144 let (_, root_view) = cx.add_window(Default::default(), |_| TestView::default());
6145 let observing_view = cx.add_view(&root_view, |_| TestView::default());
6146 let emitting_view = cx.add_view(&root_view, |_| TestView::default());
6147 let observing_model = cx.add_model(|_| Model);
6148 let observed_model = cx.add_model(|_| Model);
6149
6150 observing_view.update(cx, |_, cx| {
6151 cx.subscribe(&emitting_view, |_, _, _, _| {}).detach();
6152 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
6153 });
6154 observing_model.update(cx, |_, cx| {
6155 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
6156 });
6157
6158 cx.update(|_| {
6159 drop(observing_view);
6160 drop(observing_model);
6161 });
6162
6163 emitting_view.update(cx, |_, cx| cx.emit(Default::default()));
6164 observed_model.update(cx, |_, cx| cx.emit(()));
6165 }
6166
6167 #[crate::test(self)]
6168 fn test_view_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
6169 let (_, view) = cx.add_window::<TestView, _>(Default::default(), |cx| {
6170 drop(cx.subscribe(&cx.handle(), {
6171 move |this, _, _, _| this.events.push("dropped before flush".into())
6172 }));
6173 cx.subscribe(&cx.handle(), {
6174 move |this, _, _, _| this.events.push("before emit".into())
6175 })
6176 .detach();
6177 cx.emit("the event".into());
6178 cx.subscribe(&cx.handle(), {
6179 move |this, _, _, _| this.events.push("after emit".into())
6180 })
6181 .detach();
6182 TestView { events: Vec::new() }
6183 });
6184
6185 assert_eq!(view.read(cx).events, ["before emit"]);
6186 }
6187
6188 #[crate::test(self)]
6189 fn test_observe_and_notify_from_view(cx: &mut MutableAppContext) {
6190 #[derive(Default)]
6191 struct Model {
6192 state: String,
6193 }
6194
6195 impl Entity for Model {
6196 type Event = ();
6197 }
6198
6199 let (_, view) = cx.add_window(Default::default(), |_| TestView::default());
6200 let model = cx.add_model(|_| Model {
6201 state: "old-state".into(),
6202 });
6203
6204 view.update(cx, |_, c| {
6205 c.observe(&model, |me, observed, c| {
6206 me.events.push(observed.read(c).state.clone())
6207 })
6208 .detach();
6209 });
6210
6211 model.update(cx, |model, cx| {
6212 model.state = "new-state".into();
6213 cx.notify();
6214 });
6215 assert_eq!(view.read(cx).events, vec!["new-state"]);
6216 }
6217
6218 #[crate::test(self)]
6219 fn test_view_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
6220 let (_, view) = cx.add_window::<TestView, _>(Default::default(), |cx| {
6221 drop(cx.observe(&cx.handle(), {
6222 move |this, _, _| this.events.push("dropped before flush".into())
6223 }));
6224 cx.observe(&cx.handle(), {
6225 move |this, _, _| this.events.push("before notify".into())
6226 })
6227 .detach();
6228 cx.notify();
6229 cx.observe(&cx.handle(), {
6230 move |this, _, _| this.events.push("after notify".into())
6231 })
6232 .detach();
6233 TestView { events: Vec::new() }
6234 });
6235
6236 assert_eq!(view.read(cx).events, ["before notify"]);
6237 }
6238
6239 #[crate::test(self)]
6240 fn test_notify_and_drop_observe_subscription_in_same_update_cycle(cx: &mut MutableAppContext) {
6241 struct Model;
6242 impl Entity for Model {
6243 type Event = ();
6244 }
6245
6246 let model = cx.add_model(|_| Model);
6247 let (_, view) = cx.add_window(Default::default(), |_| TestView::default());
6248
6249 view.update(cx, |_, cx| {
6250 model.update(cx, |_, cx| cx.notify());
6251 drop(cx.observe(&model, move |this, _, _| {
6252 this.events.push("model notified".into());
6253 }));
6254 model.update(cx, |_, cx| cx.notify());
6255 });
6256
6257 for _ in 0..3 {
6258 model.update(cx, |_, cx| cx.notify());
6259 }
6260
6261 assert_eq!(view.read(cx).events, Vec::<String>::new());
6262 }
6263
6264 #[crate::test(self)]
6265 fn test_dropping_observers(cx: &mut MutableAppContext) {
6266 struct Model;
6267
6268 impl Entity for Model {
6269 type Event = ();
6270 }
6271
6272 let (_, root_view) = cx.add_window(Default::default(), |_| TestView::default());
6273 let observing_view = cx.add_view(root_view, |_| TestView::default());
6274 let observing_model = cx.add_model(|_| Model);
6275 let observed_model = cx.add_model(|_| Model);
6276
6277 observing_view.update(cx, |_, cx| {
6278 cx.observe(&observed_model, |_, _, _| {}).detach();
6279 });
6280 observing_model.update(cx, |_, cx| {
6281 cx.observe(&observed_model, |_, _, _| {}).detach();
6282 });
6283
6284 cx.update(|_| {
6285 drop(observing_view);
6286 drop(observing_model);
6287 });
6288
6289 observed_model.update(cx, |_, cx| cx.notify());
6290 }
6291
6292 #[crate::test(self)]
6293 fn test_dropping_subscriptions_during_callback(cx: &mut MutableAppContext) {
6294 struct Model;
6295
6296 impl Entity for Model {
6297 type Event = u64;
6298 }
6299
6300 // Events
6301 let observing_model = cx.add_model(|_| Model);
6302 let observed_model = cx.add_model(|_| Model);
6303
6304 let events = Rc::new(RefCell::new(Vec::new()));
6305
6306 observing_model.update(cx, |_, cx| {
6307 let events = events.clone();
6308 let subscription = Rc::new(RefCell::new(None));
6309 *subscription.borrow_mut() = Some(cx.subscribe(&observed_model, {
6310 let subscription = subscription.clone();
6311 move |_, _, e, _| {
6312 subscription.borrow_mut().take();
6313 events.borrow_mut().push(*e);
6314 }
6315 }));
6316 });
6317
6318 observed_model.update(cx, |_, cx| {
6319 cx.emit(1);
6320 cx.emit(2);
6321 });
6322
6323 assert_eq!(*events.borrow(), [1]);
6324
6325 // Global Events
6326 #[derive(Clone, Debug, Eq, PartialEq)]
6327 struct GlobalEvent(u64);
6328
6329 let events = Rc::new(RefCell::new(Vec::new()));
6330
6331 {
6332 let events = events.clone();
6333 let subscription = Rc::new(RefCell::new(None));
6334 *subscription.borrow_mut() = Some(cx.subscribe_global({
6335 let subscription = subscription.clone();
6336 move |e: &GlobalEvent, _| {
6337 subscription.borrow_mut().take();
6338 events.borrow_mut().push(e.clone());
6339 }
6340 }));
6341 }
6342
6343 cx.update(|cx| {
6344 cx.emit_global(GlobalEvent(1));
6345 cx.emit_global(GlobalEvent(2));
6346 });
6347
6348 assert_eq!(*events.borrow(), [GlobalEvent(1)]);
6349
6350 // Model Observation
6351 let observing_model = cx.add_model(|_| Model);
6352 let observed_model = cx.add_model(|_| Model);
6353
6354 let observation_count = Rc::new(RefCell::new(0));
6355
6356 observing_model.update(cx, |_, cx| {
6357 let observation_count = observation_count.clone();
6358 let subscription = Rc::new(RefCell::new(None));
6359 *subscription.borrow_mut() = Some(cx.observe(&observed_model, {
6360 let subscription = subscription.clone();
6361 move |_, _, _| {
6362 subscription.borrow_mut().take();
6363 *observation_count.borrow_mut() += 1;
6364 }
6365 }));
6366 });
6367
6368 observed_model.update(cx, |_, cx| {
6369 cx.notify();
6370 });
6371
6372 observed_model.update(cx, |_, cx| {
6373 cx.notify();
6374 });
6375
6376 assert_eq!(*observation_count.borrow(), 1);
6377
6378 // View Observation
6379 struct View;
6380
6381 impl Entity for View {
6382 type Event = ();
6383 }
6384
6385 impl super::View for View {
6386 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6387 Empty::new().boxed()
6388 }
6389
6390 fn ui_name() -> &'static str {
6391 "View"
6392 }
6393 }
6394
6395 let (_, root_view) = cx.add_window(Default::default(), |_| View);
6396 let observing_view = cx.add_view(&root_view, |_| View);
6397 let observed_view = cx.add_view(&root_view, |_| View);
6398
6399 let observation_count = Rc::new(RefCell::new(0));
6400 observing_view.update(cx, |_, cx| {
6401 let observation_count = observation_count.clone();
6402 let subscription = Rc::new(RefCell::new(None));
6403 *subscription.borrow_mut() = Some(cx.observe(&observed_view, {
6404 let subscription = subscription.clone();
6405 move |_, _, _| {
6406 subscription.borrow_mut().take();
6407 *observation_count.borrow_mut() += 1;
6408 }
6409 }));
6410 });
6411
6412 observed_view.update(cx, |_, cx| {
6413 cx.notify();
6414 });
6415
6416 observed_view.update(cx, |_, cx| {
6417 cx.notify();
6418 });
6419
6420 assert_eq!(*observation_count.borrow(), 1);
6421
6422 // Global Observation
6423 let observation_count = Rc::new(RefCell::new(0));
6424 let subscription = Rc::new(RefCell::new(None));
6425 *subscription.borrow_mut() = Some(cx.observe_global::<(), _>({
6426 let observation_count = observation_count.clone();
6427 let subscription = subscription.clone();
6428 move |_| {
6429 subscription.borrow_mut().take();
6430 *observation_count.borrow_mut() += 1;
6431 }
6432 }));
6433
6434 cx.default_global::<()>();
6435 cx.set_global(());
6436 assert_eq!(*observation_count.borrow(), 1);
6437 }
6438
6439 #[crate::test(self)]
6440 fn test_focus(cx: &mut MutableAppContext) {
6441 struct View {
6442 name: String,
6443 events: Arc<Mutex<Vec<String>>>,
6444 }
6445
6446 impl Entity for View {
6447 type Event = ();
6448 }
6449
6450 impl super::View for View {
6451 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6452 Empty::new().boxed()
6453 }
6454
6455 fn ui_name() -> &'static str {
6456 "View"
6457 }
6458
6459 fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
6460 if cx.handle().id() == focused.id() {
6461 self.events.lock().push(format!("{} focused", &self.name));
6462 }
6463 }
6464
6465 fn focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
6466 if cx.handle().id() == blurred.id() {
6467 self.events.lock().push(format!("{} blurred", &self.name));
6468 }
6469 }
6470 }
6471
6472 let view_events: Arc<Mutex<Vec<String>>> = Default::default();
6473 let (_, view_1) = cx.add_window(Default::default(), |_| View {
6474 events: view_events.clone(),
6475 name: "view 1".to_string(),
6476 });
6477 let view_2 = cx.add_view(&view_1, |_| View {
6478 events: view_events.clone(),
6479 name: "view 2".to_string(),
6480 });
6481
6482 let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
6483 view_1.update(cx, |_, cx| {
6484 cx.observe_focus(&view_2, {
6485 let observed_events = observed_events.clone();
6486 move |this, view, focused, cx| {
6487 let label = if focused { "focus" } else { "blur" };
6488 observed_events.lock().push(format!(
6489 "{} observed {}'s {}",
6490 this.name,
6491 view.read(cx).name,
6492 label
6493 ))
6494 }
6495 })
6496 .detach();
6497 });
6498 view_2.update(cx, |_, cx| {
6499 cx.observe_focus(&view_1, {
6500 let observed_events = observed_events.clone();
6501 move |this, view, focused, cx| {
6502 let label = if focused { "focus" } else { "blur" };
6503 observed_events.lock().push(format!(
6504 "{} observed {}'s {}",
6505 this.name,
6506 view.read(cx).name,
6507 label
6508 ))
6509 }
6510 })
6511 .detach();
6512 });
6513 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
6514 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
6515
6516 view_1.update(cx, |_, cx| {
6517 // Ensure focus events are sent for all intermediate focuses
6518 cx.focus(&view_2);
6519 cx.focus(&view_1);
6520 cx.focus(&view_2);
6521 });
6522 assert!(cx.is_child_focused(view_1.clone()));
6523 assert!(!cx.is_child_focused(view_2.clone()));
6524 assert_eq!(
6525 mem::take(&mut *view_events.lock()),
6526 [
6527 "view 1 blurred",
6528 "view 2 focused",
6529 "view 2 blurred",
6530 "view 1 focused",
6531 "view 1 blurred",
6532 "view 2 focused"
6533 ],
6534 );
6535 assert_eq!(
6536 mem::take(&mut *observed_events.lock()),
6537 [
6538 "view 2 observed view 1's blur",
6539 "view 1 observed view 2's focus",
6540 "view 1 observed view 2's blur",
6541 "view 2 observed view 1's focus",
6542 "view 2 observed view 1's blur",
6543 "view 1 observed view 2's focus"
6544 ]
6545 );
6546
6547 view_1.update(cx, |_, cx| cx.focus(&view_1));
6548 assert!(!cx.is_child_focused(view_1.clone()));
6549 assert!(!cx.is_child_focused(view_2.clone()));
6550 assert_eq!(
6551 mem::take(&mut *view_events.lock()),
6552 ["view 2 blurred", "view 1 focused"],
6553 );
6554 assert_eq!(
6555 mem::take(&mut *observed_events.lock()),
6556 [
6557 "view 1 observed view 2's blur",
6558 "view 2 observed view 1's focus"
6559 ]
6560 );
6561
6562 view_1.update(cx, |_, cx| cx.focus(&view_2));
6563 assert_eq!(
6564 mem::take(&mut *view_events.lock()),
6565 ["view 1 blurred", "view 2 focused"],
6566 );
6567 assert_eq!(
6568 mem::take(&mut *observed_events.lock()),
6569 [
6570 "view 2 observed view 1's blur",
6571 "view 1 observed view 2's focus"
6572 ]
6573 );
6574
6575 view_1.update(cx, |_, _| drop(view_2));
6576 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
6577 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
6578 }
6579
6580 #[crate::test(self)]
6581 fn test_deserialize_actions(cx: &mut MutableAppContext) {
6582 #[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
6583 pub struct ComplexAction {
6584 arg: String,
6585 count: usize,
6586 }
6587
6588 actions!(test::something, [SimpleAction]);
6589 impl_actions!(test::something, [ComplexAction]);
6590
6591 cx.add_global_action(move |_: &SimpleAction, _: &mut MutableAppContext| {});
6592 cx.add_global_action(move |_: &ComplexAction, _: &mut MutableAppContext| {});
6593
6594 let action1 = cx
6595 .deserialize_action(
6596 "test::something::ComplexAction",
6597 Some(r#"{"arg": "a", "count": 5}"#),
6598 )
6599 .unwrap();
6600 let action2 = cx
6601 .deserialize_action("test::something::SimpleAction", None)
6602 .unwrap();
6603 assert_eq!(
6604 action1.as_any().downcast_ref::<ComplexAction>().unwrap(),
6605 &ComplexAction {
6606 arg: "a".to_string(),
6607 count: 5,
6608 }
6609 );
6610 assert_eq!(
6611 action2.as_any().downcast_ref::<SimpleAction>().unwrap(),
6612 &SimpleAction
6613 );
6614 }
6615
6616 #[crate::test(self)]
6617 fn test_dispatch_action(cx: &mut MutableAppContext) {
6618 struct ViewA {
6619 id: usize,
6620 }
6621
6622 impl Entity for ViewA {
6623 type Event = ();
6624 }
6625
6626 impl View for ViewA {
6627 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6628 Empty::new().boxed()
6629 }
6630
6631 fn ui_name() -> &'static str {
6632 "View"
6633 }
6634 }
6635
6636 struct ViewB {
6637 id: usize,
6638 }
6639
6640 impl Entity for ViewB {
6641 type Event = ();
6642 }
6643
6644 impl View for ViewB {
6645 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6646 Empty::new().boxed()
6647 }
6648
6649 fn ui_name() -> &'static str {
6650 "View"
6651 }
6652 }
6653
6654 #[derive(Clone, Default, Deserialize, PartialEq)]
6655 pub struct Action(pub String);
6656
6657 impl_actions!(test, [Action]);
6658
6659 let actions = Rc::new(RefCell::new(Vec::new()));
6660
6661 cx.add_global_action({
6662 let actions = actions.clone();
6663 move |_: &Action, _: &mut MutableAppContext| {
6664 actions.borrow_mut().push("global".to_string());
6665 }
6666 });
6667
6668 cx.add_action({
6669 let actions = actions.clone();
6670 move |view: &mut ViewA, action: &Action, cx| {
6671 assert_eq!(action.0, "bar");
6672 cx.propagate_action();
6673 actions.borrow_mut().push(format!("{} a", view.id));
6674 }
6675 });
6676
6677 cx.add_action({
6678 let actions = actions.clone();
6679 move |view: &mut ViewA, _: &Action, cx| {
6680 if view.id != 1 {
6681 cx.add_view(|cx| {
6682 cx.propagate_action(); // Still works on a nested ViewContext
6683 ViewB { id: 5 }
6684 });
6685 }
6686 actions.borrow_mut().push(format!("{} b", view.id));
6687 }
6688 });
6689
6690 cx.add_action({
6691 let actions = actions.clone();
6692 move |view: &mut ViewB, _: &Action, cx| {
6693 cx.propagate_action();
6694 actions.borrow_mut().push(format!("{} c", view.id));
6695 }
6696 });
6697
6698 cx.add_action({
6699 let actions = actions.clone();
6700 move |view: &mut ViewB, _: &Action, cx| {
6701 cx.propagate_action();
6702 actions.borrow_mut().push(format!("{} d", view.id));
6703 }
6704 });
6705
6706 cx.capture_action({
6707 let actions = actions.clone();
6708 move |view: &mut ViewA, _: &Action, cx| {
6709 cx.propagate_action();
6710 actions.borrow_mut().push(format!("{} capture", view.id));
6711 }
6712 });
6713
6714 let observed_actions = Rc::new(RefCell::new(Vec::new()));
6715 cx.observe_actions({
6716 let observed_actions = observed_actions.clone();
6717 move |action_id, _| observed_actions.borrow_mut().push(action_id)
6718 })
6719 .detach();
6720
6721 let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 });
6722 let view_2 = cx.add_view(&view_1, |_| ViewB { id: 2 });
6723 let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 });
6724 let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 });
6725
6726 cx.handle_dispatch_action_from_effect(
6727 window_id,
6728 Some(view_4.id()),
6729 &Action("bar".to_string()),
6730 );
6731
6732 assert_eq!(
6733 *actions.borrow(),
6734 vec![
6735 "1 capture",
6736 "3 capture",
6737 "4 d",
6738 "4 c",
6739 "3 b",
6740 "3 a",
6741 "2 d",
6742 "2 c",
6743 "1 b"
6744 ]
6745 );
6746 assert_eq!(*observed_actions.borrow(), [Action::default().id()]);
6747
6748 // Remove view_1, which doesn't propagate the action
6749
6750 let (window_id, view_2) = cx.add_window(Default::default(), |_| ViewB { id: 2 });
6751 let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 });
6752 let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 });
6753
6754 actions.borrow_mut().clear();
6755 cx.handle_dispatch_action_from_effect(
6756 window_id,
6757 Some(view_4.id()),
6758 &Action("bar".to_string()),
6759 );
6760
6761 assert_eq!(
6762 *actions.borrow(),
6763 vec![
6764 "3 capture",
6765 "4 d",
6766 "4 c",
6767 "3 b",
6768 "3 a",
6769 "2 d",
6770 "2 c",
6771 "global"
6772 ]
6773 );
6774 assert_eq!(
6775 *observed_actions.borrow(),
6776 [Action::default().id(), Action::default().id()]
6777 );
6778 }
6779
6780 #[crate::test(self)]
6781 fn test_dispatch_keystroke(cx: &mut MutableAppContext) {
6782 #[derive(Clone, Deserialize, PartialEq)]
6783 pub struct Action(String);
6784
6785 impl_actions!(test, [Action]);
6786
6787 struct View {
6788 id: usize,
6789 keymap_context: KeymapContext,
6790 }
6791
6792 impl Entity for View {
6793 type Event = ();
6794 }
6795
6796 impl super::View for View {
6797 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6798 Empty::new().boxed()
6799 }
6800
6801 fn ui_name() -> &'static str {
6802 "View"
6803 }
6804
6805 fn keymap_context(&self, _: &AppContext) -> KeymapContext {
6806 self.keymap_context.clone()
6807 }
6808 }
6809
6810 impl View {
6811 fn new(id: usize) -> Self {
6812 View {
6813 id,
6814 keymap_context: KeymapContext::default(),
6815 }
6816 }
6817 }
6818
6819 let mut view_1 = View::new(1);
6820 let mut view_2 = View::new(2);
6821 let mut view_3 = View::new(3);
6822 view_1.keymap_context.set.insert("a".into());
6823 view_2.keymap_context.set.insert("a".into());
6824 view_2.keymap_context.set.insert("b".into());
6825 view_3.keymap_context.set.insert("a".into());
6826 view_3.keymap_context.set.insert("b".into());
6827 view_3.keymap_context.set.insert("c".into());
6828
6829 let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1);
6830 let view_2 = cx.add_view(&view_1, |_| view_2);
6831 let _view_3 = cx.add_view(&view_2, |cx| {
6832 cx.focus_self();
6833 view_3
6834 });
6835
6836 // This binding only dispatches an action on view 2 because that view will have
6837 // "a" and "b" in its context, but not "c".
6838 cx.add_bindings(vec![Binding::new(
6839 "a",
6840 Action("a".to_string()),
6841 Some("a && b && !c"),
6842 )]);
6843
6844 cx.add_bindings(vec![Binding::new("b", Action("b".to_string()), None)]);
6845
6846 // This binding only dispatches an action on views 2 and 3, because they have
6847 // a parent view with a in its context
6848 cx.add_bindings(vec![Binding::new(
6849 "c",
6850 Action("c".to_string()),
6851 Some("b > c"),
6852 )]);
6853
6854 // This binding only dispatches an action on view 2, because they have
6855 // a parent view with a in its context
6856 cx.add_bindings(vec![Binding::new(
6857 "d",
6858 Action("d".to_string()),
6859 Some("a && !b > b"),
6860 )]);
6861
6862 let actions = Rc::new(RefCell::new(Vec::new()));
6863 cx.add_action({
6864 let actions = actions.clone();
6865 move |view: &mut View, action: &Action, cx| {
6866 actions
6867 .borrow_mut()
6868 .push(format!("{} {}", view.id, action.0));
6869
6870 if action.0 == "b" {
6871 cx.propagate_action();
6872 }
6873 }
6874 });
6875
6876 cx.add_global_action({
6877 let actions = actions.clone();
6878 move |action: &Action, _| {
6879 actions.borrow_mut().push(format!("global {}", action.0));
6880 }
6881 });
6882
6883 cx.dispatch_keystroke(window_id, &Keystroke::parse("a").unwrap());
6884 assert_eq!(&*actions.borrow(), &["2 a"]);
6885 actions.borrow_mut().clear();
6886
6887 cx.dispatch_keystroke(window_id, &Keystroke::parse("b").unwrap());
6888 assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
6889 actions.borrow_mut().clear();
6890
6891 cx.dispatch_keystroke(window_id, &Keystroke::parse("c").unwrap());
6892 assert_eq!(&*actions.borrow(), &["3 c"]);
6893 actions.borrow_mut().clear();
6894
6895 cx.dispatch_keystroke(window_id, &Keystroke::parse("d").unwrap());
6896 assert_eq!(&*actions.borrow(), &["2 d"]);
6897 actions.borrow_mut().clear();
6898 }
6899
6900 #[crate::test(self)]
6901 async fn test_model_condition(cx: &mut TestAppContext) {
6902 struct Counter(usize);
6903
6904 impl super::Entity for Counter {
6905 type Event = ();
6906 }
6907
6908 impl Counter {
6909 fn inc(&mut self, cx: &mut ModelContext<Self>) {
6910 self.0 += 1;
6911 cx.notify();
6912 }
6913 }
6914
6915 let model = cx.add_model(|_| Counter(0));
6916
6917 let condition1 = model.condition(cx, |model, _| model.0 == 2);
6918 let condition2 = model.condition(cx, |model, _| model.0 == 3);
6919 smol::pin!(condition1, condition2);
6920
6921 model.update(cx, |model, cx| model.inc(cx));
6922 assert_eq!(poll_once(&mut condition1).await, None);
6923 assert_eq!(poll_once(&mut condition2).await, None);
6924
6925 model.update(cx, |model, cx| model.inc(cx));
6926 assert_eq!(poll_once(&mut condition1).await, Some(()));
6927 assert_eq!(poll_once(&mut condition2).await, None);
6928
6929 model.update(cx, |model, cx| model.inc(cx));
6930 assert_eq!(poll_once(&mut condition2).await, Some(()));
6931
6932 model.update(cx, |_, cx| cx.notify());
6933 }
6934
6935 #[crate::test(self)]
6936 #[should_panic]
6937 async fn test_model_condition_timeout(cx: &mut TestAppContext) {
6938 struct Model;
6939
6940 impl super::Entity for Model {
6941 type Event = ();
6942 }
6943
6944 let model = cx.add_model(|_| Model);
6945 model.condition(cx, |_, _| false).await;
6946 }
6947
6948 #[crate::test(self)]
6949 #[should_panic(expected = "model dropped with pending condition")]
6950 async fn test_model_condition_panic_on_drop(cx: &mut TestAppContext) {
6951 struct Model;
6952
6953 impl super::Entity for Model {
6954 type Event = ();
6955 }
6956
6957 let model = cx.add_model(|_| Model);
6958 let condition = model.condition(cx, |_, _| false);
6959 cx.update(|_| drop(model));
6960 condition.await;
6961 }
6962
6963 #[crate::test(self)]
6964 async fn test_view_condition(cx: &mut TestAppContext) {
6965 struct Counter(usize);
6966
6967 impl super::Entity for Counter {
6968 type Event = ();
6969 }
6970
6971 impl super::View for Counter {
6972 fn ui_name() -> &'static str {
6973 "test view"
6974 }
6975
6976 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6977 Empty::new().boxed()
6978 }
6979 }
6980
6981 impl Counter {
6982 fn inc(&mut self, cx: &mut ViewContext<Self>) {
6983 self.0 += 1;
6984 cx.notify();
6985 }
6986 }
6987
6988 let (_, view) = cx.add_window(|_| Counter(0));
6989
6990 let condition1 = view.condition(cx, |view, _| view.0 == 2);
6991 let condition2 = view.condition(cx, |view, _| view.0 == 3);
6992 smol::pin!(condition1, condition2);
6993
6994 view.update(cx, |view, cx| view.inc(cx));
6995 assert_eq!(poll_once(&mut condition1).await, None);
6996 assert_eq!(poll_once(&mut condition2).await, None);
6997
6998 view.update(cx, |view, cx| view.inc(cx));
6999 assert_eq!(poll_once(&mut condition1).await, Some(()));
7000 assert_eq!(poll_once(&mut condition2).await, None);
7001
7002 view.update(cx, |view, cx| view.inc(cx));
7003 assert_eq!(poll_once(&mut condition2).await, Some(()));
7004 view.update(cx, |_, cx| cx.notify());
7005 }
7006
7007 #[crate::test(self)]
7008 #[should_panic]
7009 async fn test_view_condition_timeout(cx: &mut TestAppContext) {
7010 let (_, view) = cx.add_window(|_| TestView::default());
7011 view.condition(cx, |_, _| false).await;
7012 }
7013
7014 #[crate::test(self)]
7015 #[should_panic(expected = "view dropped with pending condition")]
7016 async fn test_view_condition_panic_on_drop(cx: &mut TestAppContext) {
7017 let (_, root_view) = cx.add_window(|_| TestView::default());
7018 let view = cx.add_view(&root_view, |_| TestView::default());
7019
7020 let condition = view.condition(cx, |_, _| false);
7021 cx.update(|_| drop(view));
7022 condition.await;
7023 }
7024
7025 #[crate::test(self)]
7026 fn test_refresh_windows(cx: &mut MutableAppContext) {
7027 struct View(usize);
7028
7029 impl super::Entity for View {
7030 type Event = ();
7031 }
7032
7033 impl super::View for View {
7034 fn ui_name() -> &'static str {
7035 "test view"
7036 }
7037
7038 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7039 Empty::new().named(format!("render count: {}", post_inc(&mut self.0)))
7040 }
7041 }
7042
7043 let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0));
7044 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
7045
7046 assert_eq!(
7047 presenter.borrow().rendered_views[&root_view.id()].name(),
7048 Some("render count: 0")
7049 );
7050
7051 let view = cx.add_view(&root_view, |cx| {
7052 cx.refresh_windows();
7053 View(0)
7054 });
7055
7056 assert_eq!(
7057 presenter.borrow().rendered_views[&root_view.id()].name(),
7058 Some("render count: 1")
7059 );
7060 assert_eq!(
7061 presenter.borrow().rendered_views[&view.id()].name(),
7062 Some("render count: 0")
7063 );
7064
7065 cx.update(|cx| cx.refresh_windows());
7066 assert_eq!(
7067 presenter.borrow().rendered_views[&root_view.id()].name(),
7068 Some("render count: 2")
7069 );
7070 assert_eq!(
7071 presenter.borrow().rendered_views[&view.id()].name(),
7072 Some("render count: 1")
7073 );
7074
7075 cx.update(|cx| {
7076 cx.refresh_windows();
7077 drop(view);
7078 });
7079 assert_eq!(
7080 presenter.borrow().rendered_views[&root_view.id()].name(),
7081 Some("render count: 3")
7082 );
7083 assert_eq!(presenter.borrow().rendered_views.len(), 1);
7084 }
7085
7086 #[crate::test(self)]
7087 async fn test_window_activation(cx: &mut TestAppContext) {
7088 struct View(&'static str);
7089
7090 impl super::Entity for View {
7091 type Event = ();
7092 }
7093
7094 impl super::View for View {
7095 fn ui_name() -> &'static str {
7096 "test view"
7097 }
7098
7099 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7100 Empty::new().boxed()
7101 }
7102 }
7103
7104 let events = Rc::new(RefCell::new(Vec::new()));
7105 let (window_1, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7106 cx.observe_window_activation({
7107 let events = events.clone();
7108 move |this, active, _| events.borrow_mut().push((this.0, active))
7109 })
7110 .detach();
7111 View("window 1")
7112 });
7113 assert_eq!(mem::take(&mut *events.borrow_mut()), [("window 1", true)]);
7114
7115 let (window_2, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7116 cx.observe_window_activation({
7117 let events = events.clone();
7118 move |this, active, _| events.borrow_mut().push((this.0, active))
7119 })
7120 .detach();
7121 View("window 2")
7122 });
7123 assert_eq!(
7124 mem::take(&mut *events.borrow_mut()),
7125 [("window 1", false), ("window 2", true)]
7126 );
7127
7128 let (window_3, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7129 cx.observe_window_activation({
7130 let events = events.clone();
7131 move |this, active, _| events.borrow_mut().push((this.0, active))
7132 })
7133 .detach();
7134 View("window 3")
7135 });
7136 assert_eq!(
7137 mem::take(&mut *events.borrow_mut()),
7138 [("window 2", false), ("window 3", true)]
7139 );
7140
7141 cx.simulate_window_activation(Some(window_2));
7142 assert_eq!(
7143 mem::take(&mut *events.borrow_mut()),
7144 [("window 3", false), ("window 2", true)]
7145 );
7146
7147 cx.simulate_window_activation(Some(window_1));
7148 assert_eq!(
7149 mem::take(&mut *events.borrow_mut()),
7150 [("window 2", false), ("window 1", true)]
7151 );
7152
7153 cx.simulate_window_activation(Some(window_3));
7154 assert_eq!(
7155 mem::take(&mut *events.borrow_mut()),
7156 [("window 1", false), ("window 3", true)]
7157 );
7158
7159 cx.simulate_window_activation(Some(window_3));
7160 assert_eq!(mem::take(&mut *events.borrow_mut()), []);
7161 }
7162
7163 #[crate::test(self)]
7164 fn test_child_view(cx: &mut MutableAppContext) {
7165 struct Child {
7166 rendered: Rc<Cell<bool>>,
7167 dropped: Rc<Cell<bool>>,
7168 }
7169
7170 impl super::Entity for Child {
7171 type Event = ();
7172 }
7173
7174 impl super::View for Child {
7175 fn ui_name() -> &'static str {
7176 "child view"
7177 }
7178
7179 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7180 self.rendered.set(true);
7181 Empty::new().boxed()
7182 }
7183 }
7184
7185 impl Drop for Child {
7186 fn drop(&mut self) {
7187 self.dropped.set(true);
7188 }
7189 }
7190
7191 struct Parent {
7192 child: Option<ViewHandle<Child>>,
7193 }
7194
7195 impl super::Entity for Parent {
7196 type Event = ();
7197 }
7198
7199 impl super::View for Parent {
7200 fn ui_name() -> &'static str {
7201 "parent view"
7202 }
7203
7204 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
7205 if let Some(child) = self.child.as_ref() {
7206 ChildView::new(child, cx).boxed()
7207 } else {
7208 Empty::new().boxed()
7209 }
7210 }
7211 }
7212
7213 let child_rendered = Rc::new(Cell::new(false));
7214 let child_dropped = Rc::new(Cell::new(false));
7215 let (_, root_view) = cx.add_window(Default::default(), |cx| Parent {
7216 child: Some(cx.add_view(|_| Child {
7217 rendered: child_rendered.clone(),
7218 dropped: child_dropped.clone(),
7219 })),
7220 });
7221 assert!(child_rendered.take());
7222 assert!(!child_dropped.take());
7223
7224 root_view.update(cx, |view, cx| {
7225 view.child.take();
7226 cx.notify();
7227 });
7228 assert!(!child_rendered.take());
7229 assert!(child_dropped.take());
7230 }
7231
7232 #[derive(Default)]
7233 struct TestView {
7234 events: Vec<String>,
7235 }
7236
7237 impl Entity for TestView {
7238 type Event = String;
7239 }
7240
7241 impl View for TestView {
7242 fn ui_name() -> &'static str {
7243 "TestView"
7244 }
7245
7246 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7247 Empty::new().boxed()
7248 }
7249 }
7250}