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