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