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