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