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