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