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