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