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