1use crate::{
2 elements::ElementBox,
3 executor,
4 keymap::{self, Keystroke},
5 platform::{self, Platform, PromptLevel, WindowOptions},
6 presenter::Presenter,
7 util::{post_inc, timeout},
8 AssetCache, AssetSource, ClipboardItem, EventContext, FontCache, PathPromptOptions,
9 TextLayoutCache,
10};
11use anyhow::{anyhow, Result};
12use async_task::Task;
13use keymap::MatchResult;
14use parking_lot::{Mutex, RwLock};
15use platform::Event;
16use postage::{mpsc, sink::Sink as _, stream::Stream as _};
17use smol::prelude::*;
18use std::{
19 any::{type_name, Any, TypeId},
20 cell::RefCell,
21 collections::{hash_map::Entry, HashMap, HashSet, VecDeque},
22 fmt::{self, Debug},
23 hash::{Hash, Hasher},
24 marker::PhantomData,
25 ops::{Deref, DerefMut},
26 path::{Path, PathBuf},
27 rc::{self, Rc},
28 sync::{Arc, Weak},
29 time::Duration,
30};
31
32pub trait Entity: 'static + Send + Sync {
33 type Event;
34
35 fn release(&mut self, _: &mut MutableAppContext) {}
36}
37
38pub trait View: Entity + Sized {
39 fn ui_name() -> &'static str;
40 fn render(&self, cx: &RenderContext<'_, Self>) -> ElementBox;
41 fn on_focus(&mut self, _: &mut ViewContext<Self>) {}
42 fn on_blur(&mut self, _: &mut ViewContext<Self>) {}
43 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
44 Self::default_keymap_context()
45 }
46 fn default_keymap_context() -> keymap::Context {
47 let mut cx = keymap::Context::default();
48 cx.set.insert(Self::ui_name().into());
49 cx
50 }
51}
52
53pub trait ReadModel {
54 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T;
55}
56
57pub trait ReadModelWith {
58 fn read_model_with<E: Entity, F: FnOnce(&E, &AppContext) -> T, T>(
59 &self,
60 handle: &ModelHandle<E>,
61 read: F,
62 ) -> T;
63}
64
65pub trait UpdateModel {
66 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
67 where
68 T: Entity,
69 F: FnOnce(&mut T, &mut ModelContext<T>) -> S;
70}
71
72pub trait ReadView {
73 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T;
74}
75
76pub trait ReadViewWith {
77 fn read_view_with<V, F, T>(&self, handle: &ViewHandle<V>, read: F) -> T
78 where
79 V: View,
80 F: FnOnce(&V, &AppContext) -> T;
81}
82
83pub trait UpdateView {
84 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
85 where
86 T: View,
87 F: FnOnce(&mut T, &mut ViewContext<T>) -> S;
88}
89
90pub struct Menu<'a> {
91 pub name: &'a str,
92 pub items: Vec<MenuItem<'a>>,
93}
94
95pub enum MenuItem<'a> {
96 Action {
97 name: &'a str,
98 keystroke: Option<&'a str>,
99 action: &'a str,
100 arg: Option<Box<dyn Any + 'static>>,
101 },
102 Separator,
103}
104
105#[derive(Clone)]
106pub struct App(Rc<RefCell<MutableAppContext>>);
107
108#[derive(Clone)]
109pub struct AsyncAppContext(Rc<RefCell<MutableAppContext>>);
110
111pub struct BackgroundAppContext(*const RefCell<MutableAppContext>);
112
113#[derive(Clone)]
114pub struct TestAppContext {
115 cx: Rc<RefCell<MutableAppContext>>,
116 foreground_platform: Rc<platform::test::ForegroundPlatform>,
117}
118
119impl App {
120 pub fn new(asset_source: impl AssetSource) -> Result<Self> {
121 let platform = platform::current::platform();
122 let foreground_platform = platform::current::foreground_platform();
123 let foreground = Rc::new(executor::Foreground::platform(platform.dispatcher())?);
124 let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
125 foreground,
126 Arc::new(executor::Background::new()),
127 platform.clone(),
128 foreground_platform.clone(),
129 Arc::new(FontCache::new(platform.fonts())),
130 asset_source,
131 ))));
132
133 let cx = app.0.clone();
134 foreground_platform.on_menu_command(Box::new(move |command, arg| {
135 let mut cx = cx.borrow_mut();
136 if let Some(key_window_id) = cx.cx.platform.key_window_id() {
137 if let Some((presenter, _)) = cx.presenters_and_platform_windows.get(&key_window_id)
138 {
139 let presenter = presenter.clone();
140 let path = presenter.borrow().dispatch_path(cx.as_ref());
141 cx.dispatch_action_any(key_window_id, &path, command, arg.unwrap_or(&()));
142 } else {
143 cx.dispatch_global_action_any(command, arg.unwrap_or(&()));
144 }
145 } else {
146 cx.dispatch_global_action_any(command, arg.unwrap_or(&()));
147 }
148 }));
149
150 app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
151 Ok(app)
152 }
153
154 pub fn on_become_active<F>(self, mut callback: F) -> Self
155 where
156 F: 'static + FnMut(&mut MutableAppContext),
157 {
158 let cx = self.0.clone();
159 self.0
160 .borrow_mut()
161 .foreground_platform
162 .on_become_active(Box::new(move || callback(&mut *cx.borrow_mut())));
163 self
164 }
165
166 pub fn on_resign_active<F>(self, mut callback: F) -> Self
167 where
168 F: 'static + FnMut(&mut MutableAppContext),
169 {
170 let cx = self.0.clone();
171 self.0
172 .borrow_mut()
173 .foreground_platform
174 .on_resign_active(Box::new(move || callback(&mut *cx.borrow_mut())));
175 self
176 }
177
178 pub fn on_event<F>(self, mut callback: F) -> Self
179 where
180 F: 'static + FnMut(Event, &mut MutableAppContext) -> bool,
181 {
182 let cx = self.0.clone();
183 self.0
184 .borrow_mut()
185 .foreground_platform
186 .on_event(Box::new(move |event| {
187 callback(event, &mut *cx.borrow_mut())
188 }));
189 self
190 }
191
192 pub fn on_open_files<F>(self, mut callback: F) -> Self
193 where
194 F: 'static + FnMut(Vec<PathBuf>, &mut MutableAppContext),
195 {
196 let cx = self.0.clone();
197 self.0
198 .borrow_mut()
199 .foreground_platform
200 .on_open_files(Box::new(move |paths| {
201 callback(paths, &mut *cx.borrow_mut())
202 }));
203 self
204 }
205
206 pub fn run<F>(self, on_finish_launching: F)
207 where
208 F: 'static + FnOnce(&mut MutableAppContext),
209 {
210 let platform = self.0.borrow().foreground_platform.clone();
211 platform.run(Box::new(move || {
212 let mut cx = self.0.borrow_mut();
213 on_finish_launching(&mut *cx);
214 }))
215 }
216
217 pub fn font_cache(&self) -> Arc<FontCache> {
218 self.0.borrow().cx.font_cache.clone()
219 }
220
221 fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
222 let mut state = self.0.borrow_mut();
223 state.pending_flushes += 1;
224 let result = callback(&mut *state);
225 state.flush_effects();
226 result
227 }
228}
229
230impl TestAppContext {
231 pub fn new(
232 foreground_platform: Rc<platform::test::ForegroundPlatform>,
233 platform: Arc<dyn Platform>,
234 foreground: Rc<executor::Foreground>,
235 background: Arc<executor::Background>,
236 font_cache: Arc<FontCache>,
237 first_entity_id: usize,
238 ) -> Self {
239 let mut cx = MutableAppContext::new(
240 foreground.clone(),
241 background,
242 platform,
243 foreground_platform.clone(),
244 font_cache,
245 (),
246 );
247 cx.next_entity_id = first_entity_id;
248 let cx = TestAppContext {
249 cx: Rc::new(RefCell::new(cx)),
250 foreground_platform,
251 };
252 cx.cx.borrow_mut().weak_self = Some(Rc::downgrade(&cx.cx));
253 cx
254 }
255
256 pub fn dispatch_action<T: 'static + Any>(
257 &self,
258 window_id: usize,
259 responder_chain: Vec<usize>,
260 name: &str,
261 arg: T,
262 ) {
263 self.cx.borrow_mut().dispatch_action_any(
264 window_id,
265 &responder_chain,
266 name,
267 Box::new(arg).as_ref(),
268 );
269 }
270
271 pub fn dispatch_global_action<T: 'static + Any>(&self, name: &str, arg: T) {
272 self.cx.borrow_mut().dispatch_global_action(name, arg);
273 }
274
275 pub fn dispatch_keystroke(
276 &self,
277 window_id: usize,
278 responder_chain: Vec<usize>,
279 keystroke: &Keystroke,
280 ) -> Result<bool> {
281 let mut state = self.cx.borrow_mut();
282 state.dispatch_keystroke(window_id, responder_chain, keystroke)
283 }
284
285 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
286 where
287 T: Entity,
288 F: FnOnce(&mut ModelContext<T>) -> T,
289 {
290 let mut state = self.cx.borrow_mut();
291 state.pending_flushes += 1;
292 let handle = state.add_model(build_model);
293 state.flush_effects();
294 handle
295 }
296
297 pub fn add_window<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>)
298 where
299 T: View,
300 F: FnOnce(&mut ViewContext<T>) -> T,
301 {
302 self.cx
303 .borrow_mut()
304 .add_window(Default::default(), build_root_view)
305 }
306
307 pub fn window_ids(&self) -> Vec<usize> {
308 self.cx.borrow().window_ids().collect()
309 }
310
311 pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
312 self.cx.borrow().root_view(window_id)
313 }
314
315 pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
316 where
317 T: View,
318 F: FnOnce(&mut ViewContext<T>) -> T,
319 {
320 let mut state = self.cx.borrow_mut();
321 state.pending_flushes += 1;
322 let handle = state.add_view(window_id, build_view);
323 state.flush_effects();
324 handle
325 }
326
327 pub fn add_option_view<T, F>(
328 &mut self,
329 window_id: usize,
330 build_view: F,
331 ) -> Option<ViewHandle<T>>
332 where
333 T: View,
334 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
335 {
336 let mut state = self.cx.borrow_mut();
337 state.pending_flushes += 1;
338 let handle = state.add_option_view(window_id, build_view);
339 state.flush_effects();
340 handle
341 }
342
343 pub fn read<T, F: FnOnce(&AppContext) -> T>(&self, callback: F) -> T {
344 callback(self.cx.borrow().as_ref())
345 }
346
347 pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
348 let mut state = self.cx.borrow_mut();
349 // Don't increment pending flushes in order to effects to be flushed before the callback
350 // completes, which is helpful in tests.
351 let result = callback(&mut *state);
352 // Flush effects after the callback just in case there are any. This can happen in edge
353 // cases such as the closure dropping handles.
354 state.flush_effects();
355 result
356 }
357
358 pub fn to_async(&self) -> AsyncAppContext {
359 AsyncAppContext(self.cx.clone())
360 }
361
362 pub fn font_cache(&self) -> Arc<FontCache> {
363 self.cx.borrow().cx.font_cache.clone()
364 }
365
366 pub fn platform(&self) -> Arc<dyn platform::Platform> {
367 self.cx.borrow().cx.platform.clone()
368 }
369
370 pub fn foreground(&self) -> Rc<executor::Foreground> {
371 self.cx.borrow().foreground().clone()
372 }
373
374 pub fn background(&self) -> Arc<executor::Background> {
375 self.cx.borrow().background().clone()
376 }
377
378 pub fn simulate_new_path_selection(&self, result: impl FnOnce(PathBuf) -> Option<PathBuf>) {
379 self.foreground_platform.simulate_new_path_selection(result);
380 }
381
382 pub fn did_prompt_for_new_path(&self) -> bool {
383 self.foreground_platform.as_ref().did_prompt_for_new_path()
384 }
385
386 pub fn simulate_prompt_answer(&self, window_id: usize, answer: usize) {
387 let mut state = self.cx.borrow_mut();
388 let (_, window) = state
389 .presenters_and_platform_windows
390 .get_mut(&window_id)
391 .unwrap();
392 let test_window = window
393 .as_any_mut()
394 .downcast_mut::<platform::test::Window>()
395 .unwrap();
396 let callback = test_window
397 .last_prompt
398 .take()
399 .expect("prompt was not called");
400 (callback)(answer);
401 }
402}
403
404impl AsyncAppContext {
405 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
406 where
407 F: FnOnce(AsyncAppContext) -> Fut,
408 Fut: 'static + Future<Output = T>,
409 T: 'static,
410 {
411 self.0.borrow().foreground.spawn(f(self.clone()))
412 }
413
414 pub fn read<T, F: FnOnce(&AppContext) -> T>(&mut self, callback: F) -> T {
415 callback(self.0.borrow().as_ref())
416 }
417
418 pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
419 let mut state = self.0.borrow_mut();
420 state.pending_flushes += 1;
421 let result = callback(&mut *state);
422 state.flush_effects();
423 result
424 }
425
426 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
427 where
428 T: Entity,
429 F: FnOnce(&mut ModelContext<T>) -> T,
430 {
431 self.update(|cx| cx.add_model(build_model))
432 }
433
434 pub fn platform(&self) -> Arc<dyn Platform> {
435 self.0.borrow().platform()
436 }
437
438 pub fn foreground(&self) -> Rc<executor::Foreground> {
439 self.0.borrow().foreground.clone()
440 }
441
442 pub fn background(&self) -> Arc<executor::Background> {
443 self.0.borrow().cx.background.clone()
444 }
445}
446
447impl UpdateModel for AsyncAppContext {
448 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
449 where
450 T: Entity,
451 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
452 {
453 let mut state = self.0.borrow_mut();
454 state.pending_flushes += 1;
455 let result = state.update_model(handle, update);
456 state.flush_effects();
457 result
458 }
459}
460
461impl ReadModelWith for AsyncAppContext {
462 fn read_model_with<E: Entity, F: FnOnce(&E, &AppContext) -> T, T>(
463 &self,
464 handle: &ModelHandle<E>,
465 read: F,
466 ) -> T {
467 let cx = self.0.borrow();
468 let cx = cx.as_ref();
469 read(handle.read(cx), cx)
470 }
471}
472
473impl UpdateView for AsyncAppContext {
474 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
475 where
476 T: View,
477 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
478 {
479 let mut state = self.0.borrow_mut();
480 state.pending_flushes += 1;
481 let result = state.update_view(handle, update);
482 state.flush_effects();
483 result
484 }
485}
486
487impl ReadViewWith for AsyncAppContext {
488 fn read_view_with<V, F, T>(&self, handle: &ViewHandle<V>, read: F) -> T
489 where
490 V: View,
491 F: FnOnce(&V, &AppContext) -> T,
492 {
493 let cx = self.0.borrow();
494 let cx = cx.as_ref();
495 read(handle.read(cx), cx)
496 }
497}
498
499impl UpdateModel for TestAppContext {
500 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
501 where
502 T: Entity,
503 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
504 {
505 let mut state = self.cx.borrow_mut();
506 state.pending_flushes += 1;
507 let result = state.update_model(handle, update);
508 state.flush_effects();
509 result
510 }
511}
512
513impl ReadModelWith for TestAppContext {
514 fn read_model_with<E: Entity, F: FnOnce(&E, &AppContext) -> T, T>(
515 &self,
516 handle: &ModelHandle<E>,
517 read: F,
518 ) -> T {
519 let cx = self.cx.borrow();
520 let cx = cx.as_ref();
521 read(handle.read(cx), cx)
522 }
523}
524
525impl UpdateView for TestAppContext {
526 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
527 where
528 T: View,
529 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
530 {
531 let mut state = self.cx.borrow_mut();
532 state.pending_flushes += 1;
533 let result = state.update_view(handle, update);
534 state.flush_effects();
535 result
536 }
537}
538
539impl ReadViewWith for TestAppContext {
540 fn read_view_with<V, F, T>(&self, handle: &ViewHandle<V>, read: F) -> T
541 where
542 V: View,
543 F: FnOnce(&V, &AppContext) -> T,
544 {
545 let cx = self.cx.borrow();
546 let cx = cx.as_ref();
547 read(handle.read(cx), cx)
548 }
549}
550
551type ActionCallback =
552 dyn FnMut(&mut dyn AnyView, &dyn Any, &mut MutableAppContext, usize, usize) -> bool;
553
554type GlobalActionCallback = dyn FnMut(&dyn Any, &mut MutableAppContext);
555
556pub struct MutableAppContext {
557 weak_self: Option<rc::Weak<RefCell<Self>>>,
558 foreground_platform: Rc<dyn platform::ForegroundPlatform>,
559 assets: Arc<AssetCache>,
560 cx: AppContext,
561 actions: HashMap<TypeId, HashMap<String, Vec<Box<ActionCallback>>>>,
562 global_actions: HashMap<String, Vec<Box<GlobalActionCallback>>>,
563 keystroke_matcher: keymap::Matcher,
564 next_entity_id: usize,
565 next_window_id: usize,
566 subscriptions: HashMap<usize, Vec<Subscription>>,
567 model_observations: HashMap<usize, Vec<ModelObservation>>,
568 view_observations: HashMap<usize, Vec<ViewObservation>>,
569 presenters_and_platform_windows:
570 HashMap<usize, (Rc<RefCell<Presenter>>, Box<dyn platform::Window>)>,
571 debug_elements_callbacks: HashMap<usize, Box<dyn Fn(&AppContext) -> crate::json::Value>>,
572 foreground: Rc<executor::Foreground>,
573 pending_effects: VecDeque<Effect>,
574 pending_flushes: usize,
575 flushing_effects: bool,
576}
577
578impl MutableAppContext {
579 fn new(
580 foreground: Rc<executor::Foreground>,
581 background: Arc<executor::Background>,
582 platform: Arc<dyn platform::Platform>,
583 foreground_platform: Rc<dyn platform::ForegroundPlatform>,
584 font_cache: Arc<FontCache>,
585 asset_source: impl AssetSource,
586 ) -> Self {
587 Self {
588 weak_self: None,
589 foreground_platform,
590 assets: Arc::new(AssetCache::new(asset_source)),
591 cx: AppContext {
592 models: Default::default(),
593 views: Default::default(),
594 windows: Default::default(),
595 values: Default::default(),
596 ref_counts: Arc::new(Mutex::new(RefCounts::default())),
597 background,
598 font_cache,
599 platform,
600 },
601 actions: HashMap::new(),
602 global_actions: HashMap::new(),
603 keystroke_matcher: keymap::Matcher::default(),
604 next_entity_id: 0,
605 next_window_id: 0,
606 subscriptions: HashMap::new(),
607 model_observations: HashMap::new(),
608 view_observations: HashMap::new(),
609 presenters_and_platform_windows: HashMap::new(),
610 debug_elements_callbacks: HashMap::new(),
611 foreground,
612 pending_effects: VecDeque::new(),
613 pending_flushes: 0,
614 flushing_effects: false,
615 }
616 }
617
618 pub fn upgrade(&self) -> App {
619 App(self.weak_self.as_ref().unwrap().upgrade().unwrap())
620 }
621
622 pub fn platform(&self) -> Arc<dyn platform::Platform> {
623 self.cx.platform.clone()
624 }
625
626 pub fn font_cache(&self) -> &Arc<FontCache> {
627 &self.cx.font_cache
628 }
629
630 pub fn foreground(&self) -> &Rc<executor::Foreground> {
631 &self.foreground
632 }
633
634 pub fn background(&self) -> &Arc<executor::Background> {
635 &self.cx.background
636 }
637
638 pub fn on_debug_elements<F>(&mut self, window_id: usize, callback: F)
639 where
640 F: 'static + Fn(&AppContext) -> crate::json::Value,
641 {
642 self.debug_elements_callbacks
643 .insert(window_id, Box::new(callback));
644 }
645
646 pub fn debug_elements(&self, window_id: usize) -> Option<crate::json::Value> {
647 self.debug_elements_callbacks
648 .get(&window_id)
649 .map(|debug_elements| debug_elements(&self.cx))
650 }
651
652 pub fn add_action<S, V, T, F>(&mut self, name: S, mut handler: F)
653 where
654 S: Into<String>,
655 V: View,
656 T: Any,
657 F: 'static + FnMut(&mut V, &T, &mut ViewContext<V>),
658 {
659 let name = name.into();
660 let name_clone = name.clone();
661 let handler = Box::new(
662 move |view: &mut dyn AnyView,
663 arg: &dyn Any,
664 cx: &mut MutableAppContext,
665 window_id: usize,
666 view_id: usize| {
667 match arg.downcast_ref() {
668 Some(arg) => {
669 let mut cx = ViewContext::new(cx, window_id, view_id);
670 handler(
671 view.as_any_mut()
672 .downcast_mut()
673 .expect("downcast is type safe"),
674 arg,
675 &mut cx,
676 );
677 cx.halt_action_dispatch
678 }
679 None => {
680 log::error!("Could not downcast argument for action {}", name_clone);
681 false
682 }
683 }
684 },
685 );
686
687 self.actions
688 .entry(TypeId::of::<V>())
689 .or_default()
690 .entry(name)
691 .or_default()
692 .push(handler);
693 }
694
695 pub fn add_global_action<S, T, F>(&mut self, name: S, mut handler: F)
696 where
697 S: Into<String>,
698 T: 'static + Any,
699 F: 'static + FnMut(&T, &mut MutableAppContext),
700 {
701 let name = name.into();
702 let name_clone = name.clone();
703 let handler = Box::new(move |arg: &dyn Any, cx: &mut MutableAppContext| {
704 if let Some(arg) = arg.downcast_ref() {
705 handler(arg, cx);
706 } else {
707 log::error!(
708 "Could not downcast argument for global action {}",
709 name_clone
710 );
711 }
712 });
713
714 self.global_actions.entry(name).or_default().push(handler);
715 }
716
717 pub fn window_ids(&self) -> impl Iterator<Item = usize> + '_ {
718 self.cx.windows.keys().cloned()
719 }
720
721 pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
722 self.cx
723 .windows
724 .get(&window_id)
725 .and_then(|window| window.root_view.clone().downcast::<T>())
726 }
727
728 pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
729 self.cx.root_view_id(window_id)
730 }
731
732 pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
733 self.cx.focused_view_id(window_id)
734 }
735
736 pub fn render_view(&self, window_id: usize, view_id: usize) -> Result<ElementBox> {
737 self.cx.render_view(window_id, view_id)
738 }
739
740 pub fn render_views(&self, window_id: usize) -> HashMap<usize, ElementBox> {
741 self.cx.render_views(window_id)
742 }
743
744 pub fn update<T, F: FnOnce() -> T>(&mut self, callback: F) -> T {
745 self.pending_flushes += 1;
746 let result = callback();
747 self.flush_effects();
748 result
749 }
750
751 pub fn set_menus(&mut self, menus: Vec<Menu>) {
752 self.foreground_platform.set_menus(menus);
753 }
754
755 fn prompt<F>(
756 &self,
757 window_id: usize,
758 level: PromptLevel,
759 msg: &str,
760 answers: &[&str],
761 done_fn: F,
762 ) where
763 F: 'static + FnOnce(usize, &mut MutableAppContext),
764 {
765 let app = self.weak_self.as_ref().unwrap().upgrade().unwrap();
766 let foreground = self.foreground.clone();
767 let (_, window) = &self.presenters_and_platform_windows[&window_id];
768 window.prompt(
769 level,
770 msg,
771 answers,
772 Box::new(move |answer| {
773 foreground
774 .spawn(async move { (done_fn)(answer, &mut *app.borrow_mut()) })
775 .detach();
776 }),
777 );
778 }
779
780 pub fn prompt_for_paths<F>(&self, options: PathPromptOptions, done_fn: F)
781 where
782 F: 'static + FnOnce(Option<Vec<PathBuf>>, &mut MutableAppContext),
783 {
784 let app = self.weak_self.as_ref().unwrap().upgrade().unwrap();
785 let foreground = self.foreground.clone();
786 self.foreground_platform.prompt_for_paths(
787 options,
788 Box::new(move |paths| {
789 foreground
790 .spawn(async move { (done_fn)(paths, &mut *app.borrow_mut()) })
791 .detach();
792 }),
793 );
794 }
795
796 pub fn prompt_for_new_path<F>(&self, directory: &Path, done_fn: F)
797 where
798 F: 'static + FnOnce(Option<PathBuf>, &mut MutableAppContext),
799 {
800 let app = self.weak_self.as_ref().unwrap().upgrade().unwrap();
801 let foreground = self.foreground.clone();
802 self.foreground_platform.prompt_for_new_path(
803 directory,
804 Box::new(move |path| {
805 foreground
806 .spawn(async move { (done_fn)(path, &mut *app.borrow_mut()) })
807 .detach();
808 }),
809 );
810 }
811
812 pub(crate) fn notify_view(&mut self, window_id: usize, view_id: usize) {
813 self.pending_effects
814 .push_back(Effect::ViewNotification { window_id, view_id });
815 }
816
817 pub(crate) fn notify_all_views(&mut self) {
818 let notifications = self
819 .views
820 .keys()
821 .copied()
822 .map(|(window_id, view_id)| Effect::ViewNotification { window_id, view_id })
823 .collect::<Vec<_>>();
824 self.pending_effects.extend(notifications);
825 }
826
827 pub fn dispatch_action<T: 'static + Any>(
828 &mut self,
829 window_id: usize,
830 responder_chain: Vec<usize>,
831 name: &str,
832 arg: T,
833 ) {
834 self.dispatch_action_any(window_id, &responder_chain, name, Box::new(arg).as_ref());
835 }
836
837 pub(crate) fn dispatch_action_any(
838 &mut self,
839 window_id: usize,
840 path: &[usize],
841 name: &str,
842 arg: &dyn Any,
843 ) -> bool {
844 self.pending_flushes += 1;
845 let mut halted_dispatch = false;
846
847 for view_id in path.iter().rev() {
848 if let Some(mut view) = self.cx.views.remove(&(window_id, *view_id)) {
849 let type_id = view.as_any().type_id();
850
851 if let Some((name, mut handlers)) = self
852 .actions
853 .get_mut(&type_id)
854 .and_then(|h| h.remove_entry(name))
855 {
856 for handler in handlers.iter_mut().rev() {
857 let halt_dispatch = handler(view.as_mut(), arg, self, window_id, *view_id);
858 if halt_dispatch {
859 halted_dispatch = true;
860 break;
861 }
862 }
863 self.actions
864 .get_mut(&type_id)
865 .unwrap()
866 .insert(name, handlers);
867 }
868
869 self.cx.views.insert((window_id, *view_id), view);
870
871 if halted_dispatch {
872 break;
873 }
874 }
875 }
876
877 if !halted_dispatch {
878 self.dispatch_global_action_any(name, arg);
879 }
880
881 self.flush_effects();
882 halted_dispatch
883 }
884
885 pub fn dispatch_global_action<T: 'static + Any>(&mut self, name: &str, arg: T) {
886 self.dispatch_global_action_any(name, Box::new(arg).as_ref());
887 }
888
889 fn dispatch_global_action_any(&mut self, name: &str, arg: &dyn Any) {
890 if let Some((name, mut handlers)) = self.global_actions.remove_entry(name) {
891 self.pending_flushes += 1;
892 for handler in handlers.iter_mut().rev() {
893 handler(arg, self);
894 }
895 self.global_actions.insert(name, handlers);
896 self.flush_effects();
897 }
898 }
899
900 pub fn add_bindings<T: IntoIterator<Item = keymap::Binding>>(&mut self, bindings: T) {
901 self.keystroke_matcher.add_bindings(bindings);
902 }
903
904 pub fn dispatch_keystroke(
905 &mut self,
906 window_id: usize,
907 responder_chain: Vec<usize>,
908 keystroke: &Keystroke,
909 ) -> Result<bool> {
910 let mut context_chain = Vec::new();
911 let mut context = keymap::Context::default();
912 for view_id in &responder_chain {
913 if let Some(view) = self.cx.views.get(&(window_id, *view_id)) {
914 context.extend(view.keymap_context(self.as_ref()));
915 context_chain.push(context.clone());
916 } else {
917 return Err(anyhow!(
918 "View {} in responder chain does not exist",
919 view_id
920 ));
921 }
922 }
923
924 let mut pending = false;
925 for (i, cx) in context_chain.iter().enumerate().rev() {
926 match self
927 .keystroke_matcher
928 .push_keystroke(keystroke.clone(), responder_chain[i], cx)
929 {
930 MatchResult::None => {}
931 MatchResult::Pending => pending = true,
932 MatchResult::Action { name, arg } => {
933 if self.dispatch_action_any(
934 window_id,
935 &responder_chain[0..=i],
936 &name,
937 arg.as_ref().map(|arg| arg.as_ref()).unwrap_or(&()),
938 ) {
939 return Ok(true);
940 }
941 }
942 }
943 }
944
945 Ok(pending)
946 }
947
948 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
949 where
950 T: Entity,
951 F: FnOnce(&mut ModelContext<T>) -> T,
952 {
953 self.pending_flushes += 1;
954 let model_id = post_inc(&mut self.next_entity_id);
955 let handle = ModelHandle::new(model_id, &self.cx.ref_counts);
956 let mut cx = ModelContext::new(self, model_id);
957 let model = build_model(&mut cx);
958 self.cx.models.insert(model_id, Box::new(model));
959 self.flush_effects();
960 handle
961 }
962
963 pub fn add_window<T, F>(
964 &mut self,
965 window_options: WindowOptions,
966 build_root_view: F,
967 ) -> (usize, ViewHandle<T>)
968 where
969 T: View,
970 F: FnOnce(&mut ViewContext<T>) -> T,
971 {
972 self.pending_flushes += 1;
973 let window_id = post_inc(&mut self.next_window_id);
974 let root_view = self.add_view(window_id, build_root_view);
975
976 self.cx.windows.insert(
977 window_id,
978 Window {
979 root_view: root_view.clone().into(),
980 focused_view_id: root_view.id(),
981 invalidation: None,
982 },
983 );
984 self.open_platform_window(window_id, window_options);
985 root_view.update(self, |view, cx| {
986 view.on_focus(cx);
987 cx.notify();
988 });
989 self.flush_effects();
990
991 (window_id, root_view)
992 }
993
994 pub fn remove_window(&mut self, window_id: usize) {
995 self.cx.windows.remove(&window_id);
996 self.presenters_and_platform_windows.remove(&window_id);
997 self.remove_dropped_entities();
998 }
999
1000 fn open_platform_window(&mut self, window_id: usize, window_options: WindowOptions) {
1001 let mut window =
1002 self.cx
1003 .platform
1004 .open_window(window_id, window_options, self.foreground.clone());
1005 let text_layout_cache = TextLayoutCache::new(self.cx.platform.fonts());
1006 let presenter = Rc::new(RefCell::new(Presenter::new(
1007 window_id,
1008 self.cx.font_cache.clone(),
1009 text_layout_cache,
1010 self.assets.clone(),
1011 self,
1012 )));
1013
1014 {
1015 let mut app = self.upgrade();
1016 let presenter = presenter.clone();
1017 window.on_event(Box::new(move |event| {
1018 app.update(|cx| {
1019 if let Event::KeyDown { keystroke, .. } = &event {
1020 if cx
1021 .dispatch_keystroke(
1022 window_id,
1023 presenter.borrow().dispatch_path(cx.as_ref()),
1024 keystroke,
1025 )
1026 .unwrap()
1027 {
1028 return;
1029 }
1030 }
1031
1032 presenter.borrow_mut().dispatch_event(event, cx);
1033 })
1034 }));
1035 }
1036
1037 {
1038 let mut app = self.upgrade();
1039 let presenter = presenter.clone();
1040 window.on_resize(Box::new(move |window| {
1041 app.update(|cx| {
1042 let scene = presenter.borrow_mut().build_scene(
1043 window.size(),
1044 window.scale_factor(),
1045 cx,
1046 );
1047 window.present_scene(scene);
1048 })
1049 }));
1050 }
1051
1052 {
1053 let mut app = self.upgrade();
1054 window.on_close(Box::new(move || {
1055 app.update(|cx| cx.remove_window(window_id));
1056 }));
1057 }
1058
1059 self.presenters_and_platform_windows
1060 .insert(window_id, (presenter.clone(), window));
1061
1062 self.on_debug_elements(window_id, move |cx| {
1063 presenter.borrow().debug_elements(cx).unwrap()
1064 });
1065 }
1066
1067 pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
1068 where
1069 T: View,
1070 F: FnOnce(&mut ViewContext<T>) -> T,
1071 {
1072 self.add_option_view(window_id, |cx| Some(build_view(cx)))
1073 .unwrap()
1074 }
1075
1076 pub fn add_option_view<T, F>(
1077 &mut self,
1078 window_id: usize,
1079 build_view: F,
1080 ) -> Option<ViewHandle<T>>
1081 where
1082 T: View,
1083 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
1084 {
1085 let view_id = post_inc(&mut self.next_entity_id);
1086 self.pending_flushes += 1;
1087 let handle = ViewHandle::new(window_id, view_id, &self.cx.ref_counts);
1088 let mut cx = ViewContext::new(self, window_id, view_id);
1089 let handle = if let Some(view) = build_view(&mut cx) {
1090 self.cx.views.insert((window_id, view_id), Box::new(view));
1091 if let Some(window) = self.cx.windows.get_mut(&window_id) {
1092 window
1093 .invalidation
1094 .get_or_insert_with(Default::default)
1095 .updated
1096 .insert(view_id);
1097 }
1098 Some(handle)
1099 } else {
1100 None
1101 };
1102 self.flush_effects();
1103 handle
1104 }
1105
1106 fn remove_dropped_entities(&mut self) {
1107 loop {
1108 let (dropped_models, dropped_views, dropped_values) =
1109 self.cx.ref_counts.lock().take_dropped();
1110 if dropped_models.is_empty() && dropped_views.is_empty() && dropped_values.is_empty() {
1111 break;
1112 }
1113
1114 for model_id in dropped_models {
1115 self.subscriptions.remove(&model_id);
1116 self.model_observations.remove(&model_id);
1117 let mut model = self.cx.models.remove(&model_id).unwrap();
1118 model.release(self);
1119 }
1120
1121 for (window_id, view_id) in dropped_views {
1122 self.subscriptions.remove(&view_id);
1123 self.model_observations.remove(&view_id);
1124 let mut view = self.cx.views.remove(&(window_id, view_id)).unwrap();
1125 view.release(self);
1126 let change_focus_to = self.cx.windows.get_mut(&window_id).and_then(|window| {
1127 window
1128 .invalidation
1129 .get_or_insert_with(Default::default)
1130 .removed
1131 .push(view_id);
1132 if window.focused_view_id == view_id {
1133 Some(window.root_view.id())
1134 } else {
1135 None
1136 }
1137 });
1138
1139 if let Some(view_id) = change_focus_to {
1140 self.focus(window_id, view_id);
1141 }
1142 }
1143
1144 let mut values = self.cx.values.write();
1145 for key in dropped_values {
1146 values.remove(&key);
1147 }
1148 }
1149 }
1150
1151 fn flush_effects(&mut self) {
1152 self.pending_flushes = self.pending_flushes.saturating_sub(1);
1153
1154 if !self.flushing_effects && self.pending_flushes == 0 {
1155 self.flushing_effects = true;
1156
1157 loop {
1158 if let Some(effect) = self.pending_effects.pop_front() {
1159 match effect {
1160 Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload),
1161 Effect::ModelNotification { model_id } => {
1162 self.notify_model_observers(model_id)
1163 }
1164 Effect::ViewNotification { window_id, view_id } => {
1165 self.notify_view_observers(window_id, view_id)
1166 }
1167 Effect::Focus { window_id, view_id } => {
1168 self.focus(window_id, view_id);
1169 }
1170 }
1171 self.remove_dropped_entities();
1172 } else {
1173 self.remove_dropped_entities();
1174 self.update_windows();
1175
1176 if self.pending_effects.is_empty() {
1177 self.flushing_effects = false;
1178 break;
1179 }
1180 }
1181 }
1182 }
1183 }
1184
1185 fn update_windows(&mut self) {
1186 let mut invalidations = HashMap::new();
1187 for (window_id, window) in &mut self.cx.windows {
1188 if let Some(invalidation) = window.invalidation.take() {
1189 invalidations.insert(*window_id, invalidation);
1190 }
1191 }
1192
1193 for (window_id, invalidation) in invalidations {
1194 if let Some((presenter, mut window)) =
1195 self.presenters_and_platform_windows.remove(&window_id)
1196 {
1197 {
1198 let mut presenter = presenter.borrow_mut();
1199 presenter.invalidate(invalidation, self.as_ref());
1200 let scene = presenter.build_scene(window.size(), window.scale_factor(), self);
1201 window.present_scene(scene);
1202 }
1203 self.presenters_and_platform_windows
1204 .insert(window_id, (presenter, window));
1205 }
1206 }
1207 }
1208
1209 fn emit_event(&mut self, entity_id: usize, payload: Box<dyn Any>) {
1210 if let Some(subscriptions) = self.subscriptions.remove(&entity_id) {
1211 for mut subscription in subscriptions {
1212 let alive = match &mut subscription {
1213 Subscription::FromModel { model_id, callback } => {
1214 if let Some(mut model) = self.cx.models.remove(model_id) {
1215 callback(model.as_any_mut(), payload.as_ref(), self, *model_id);
1216 self.cx.models.insert(*model_id, model);
1217 true
1218 } else {
1219 false
1220 }
1221 }
1222 Subscription::FromView {
1223 window_id,
1224 view_id,
1225 callback,
1226 } => {
1227 if let Some(mut view) = self.cx.views.remove(&(*window_id, *view_id)) {
1228 callback(
1229 view.as_any_mut(),
1230 payload.as_ref(),
1231 self,
1232 *window_id,
1233 *view_id,
1234 );
1235 self.cx.views.insert((*window_id, *view_id), view);
1236 true
1237 } else {
1238 false
1239 }
1240 }
1241 };
1242
1243 if alive {
1244 self.subscriptions
1245 .entry(entity_id)
1246 .or_default()
1247 .push(subscription);
1248 }
1249 }
1250 }
1251 }
1252
1253 fn notify_model_observers(&mut self, observed_id: usize) {
1254 if let Some(observations) = self.model_observations.remove(&observed_id) {
1255 if self.cx.models.contains_key(&observed_id) {
1256 for mut observation in observations {
1257 let alive = match &mut observation {
1258 ModelObservation::FromModel { model_id, callback } => {
1259 if let Some(mut model) = self.cx.models.remove(model_id) {
1260 callback(model.as_any_mut(), observed_id, self, *model_id);
1261 self.cx.models.insert(*model_id, model);
1262 true
1263 } else {
1264 false
1265 }
1266 }
1267 ModelObservation::FromView {
1268 window_id,
1269 view_id,
1270 callback,
1271 } => {
1272 if let Some(mut view) = self.cx.views.remove(&(*window_id, *view_id)) {
1273 callback(
1274 view.as_any_mut(),
1275 observed_id,
1276 self,
1277 *window_id,
1278 *view_id,
1279 );
1280 self.cx.views.insert((*window_id, *view_id), view);
1281 true
1282 } else {
1283 false
1284 }
1285 }
1286 };
1287
1288 if alive {
1289 self.model_observations
1290 .entry(observed_id)
1291 .or_default()
1292 .push(observation);
1293 }
1294 }
1295 }
1296 }
1297 }
1298
1299 fn notify_view_observers(&mut self, window_id: usize, view_id: usize) {
1300 if let Some(window) = self.cx.windows.get_mut(&window_id) {
1301 window
1302 .invalidation
1303 .get_or_insert_with(Default::default)
1304 .updated
1305 .insert(view_id);
1306 }
1307
1308 if let Some(observations) = self.view_observations.remove(&view_id) {
1309 if self.cx.views.contains_key(&(window_id, view_id)) {
1310 for mut observation in observations {
1311 let alive = if let Some(mut view) = self
1312 .cx
1313 .views
1314 .remove(&(observation.window_id, observation.view_id))
1315 {
1316 (observation.callback)(
1317 view.as_any_mut(),
1318 view_id,
1319 window_id,
1320 self,
1321 observation.window_id,
1322 observation.view_id,
1323 );
1324 self.cx
1325 .views
1326 .insert((observation.window_id, observation.view_id), view);
1327 true
1328 } else {
1329 false
1330 };
1331
1332 if alive {
1333 self.view_observations
1334 .entry(view_id)
1335 .or_default()
1336 .push(observation);
1337 }
1338 }
1339 }
1340 }
1341 }
1342
1343 fn focus(&mut self, window_id: usize, focused_id: usize) {
1344 if self
1345 .cx
1346 .windows
1347 .get(&window_id)
1348 .map(|w| w.focused_view_id)
1349 .map_or(false, |cur_focused| cur_focused == focused_id)
1350 {
1351 return;
1352 }
1353
1354 self.pending_flushes += 1;
1355
1356 let blurred_id = self.cx.windows.get_mut(&window_id).map(|window| {
1357 let blurred_id = window.focused_view_id;
1358 window.focused_view_id = focused_id;
1359 blurred_id
1360 });
1361
1362 if let Some(blurred_id) = blurred_id {
1363 if let Some(mut blurred_view) = self.cx.views.remove(&(window_id, blurred_id)) {
1364 blurred_view.on_blur(self, window_id, blurred_id);
1365 self.cx.views.insert((window_id, blurred_id), blurred_view);
1366 }
1367 }
1368
1369 if let Some(mut focused_view) = self.cx.views.remove(&(window_id, focused_id)) {
1370 focused_view.on_focus(self, window_id, focused_id);
1371 self.cx.views.insert((window_id, focused_id), focused_view);
1372 }
1373
1374 self.flush_effects();
1375 }
1376
1377 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
1378 where
1379 F: FnOnce(AsyncAppContext) -> Fut,
1380 Fut: 'static + Future<Output = T>,
1381 T: 'static,
1382 {
1383 let cx = self.to_async();
1384 self.foreground.spawn(f(cx))
1385 }
1386
1387 pub fn to_async(&self) -> AsyncAppContext {
1388 AsyncAppContext(self.weak_self.as_ref().unwrap().upgrade().unwrap())
1389 }
1390
1391 pub fn write_to_clipboard(&self, item: ClipboardItem) {
1392 self.cx.platform.write_to_clipboard(item);
1393 }
1394
1395 pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {
1396 self.cx.platform.read_from_clipboard()
1397 }
1398}
1399
1400impl ReadModel for MutableAppContext {
1401 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1402 if let Some(model) = self.cx.models.get(&handle.model_id) {
1403 model
1404 .as_any()
1405 .downcast_ref()
1406 .expect("downcast is type safe")
1407 } else {
1408 panic!("circular model reference");
1409 }
1410 }
1411}
1412
1413impl UpdateModel for MutableAppContext {
1414 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1415 where
1416 T: Entity,
1417 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1418 {
1419 if let Some(mut model) = self.cx.models.remove(&handle.model_id) {
1420 self.pending_flushes += 1;
1421 let mut cx = ModelContext::new(self, handle.model_id);
1422 let result = update(
1423 model
1424 .as_any_mut()
1425 .downcast_mut()
1426 .expect("downcast is type safe"),
1427 &mut cx,
1428 );
1429 self.cx.models.insert(handle.model_id, model);
1430 self.flush_effects();
1431 result
1432 } else {
1433 panic!("circular model update");
1434 }
1435 }
1436}
1437
1438impl ReadView for MutableAppContext {
1439 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1440 if let Some(view) = self.cx.views.get(&(handle.window_id, handle.view_id)) {
1441 view.as_any().downcast_ref().expect("downcast is type safe")
1442 } else {
1443 panic!("circular view reference");
1444 }
1445 }
1446}
1447
1448impl UpdateView for MutableAppContext {
1449 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
1450 where
1451 T: View,
1452 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
1453 {
1454 self.pending_flushes += 1;
1455 let mut view = self
1456 .cx
1457 .views
1458 .remove(&(handle.window_id, handle.view_id))
1459 .expect("circular view update");
1460
1461 let mut cx = ViewContext::new(self, handle.window_id, handle.view_id);
1462 let result = update(
1463 view.as_any_mut()
1464 .downcast_mut()
1465 .expect("downcast is type safe"),
1466 &mut cx,
1467 );
1468 self.cx
1469 .views
1470 .insert((handle.window_id, handle.view_id), view);
1471 self.flush_effects();
1472 result
1473 }
1474}
1475
1476impl AsRef<AppContext> for MutableAppContext {
1477 fn as_ref(&self) -> &AppContext {
1478 &self.cx
1479 }
1480}
1481
1482impl Deref for MutableAppContext {
1483 type Target = AppContext;
1484
1485 fn deref(&self) -> &Self::Target {
1486 &self.cx
1487 }
1488}
1489
1490pub struct AppContext {
1491 models: HashMap<usize, Box<dyn AnyModel>>,
1492 views: HashMap<(usize, usize), Box<dyn AnyView>>,
1493 windows: HashMap<usize, Window>,
1494 values: RwLock<HashMap<(TypeId, usize), Box<dyn Any>>>,
1495 background: Arc<executor::Background>,
1496 ref_counts: Arc<Mutex<RefCounts>>,
1497 font_cache: Arc<FontCache>,
1498 platform: Arc<dyn Platform>,
1499}
1500
1501impl AppContext {
1502 pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
1503 self.windows
1504 .get(&window_id)
1505 .map(|window| window.root_view.id())
1506 }
1507
1508 pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
1509 self.windows
1510 .get(&window_id)
1511 .map(|window| window.focused_view_id)
1512 }
1513
1514 pub fn render_view(&self, window_id: usize, view_id: usize) -> Result<ElementBox> {
1515 self.views
1516 .get(&(window_id, view_id))
1517 .map(|v| v.render(window_id, view_id, self))
1518 .ok_or(anyhow!("view not found"))
1519 }
1520
1521 pub fn render_views(&self, window_id: usize) -> HashMap<usize, ElementBox> {
1522 self.views
1523 .iter()
1524 .filter_map(|((win_id, view_id), view)| {
1525 if *win_id == window_id {
1526 Some((*view_id, view.render(*win_id, *view_id, self)))
1527 } else {
1528 None
1529 }
1530 })
1531 .collect::<HashMap<_, ElementBox>>()
1532 }
1533
1534 pub fn background(&self) -> &Arc<executor::Background> {
1535 &self.background
1536 }
1537
1538 pub fn font_cache(&self) -> &Arc<FontCache> {
1539 &self.font_cache
1540 }
1541
1542 pub fn platform(&self) -> &Arc<dyn Platform> {
1543 &self.platform
1544 }
1545
1546 pub fn value<Tag: 'static, T: 'static + Default>(&self, id: usize) -> ValueHandle<T> {
1547 let key = (TypeId::of::<Tag>(), id);
1548 self.values
1549 .write()
1550 .entry(key)
1551 .or_insert_with(|| Box::new(T::default()));
1552 ValueHandle::new(TypeId::of::<Tag>(), id, &self.ref_counts)
1553 }
1554}
1555
1556impl ReadModel for AppContext {
1557 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1558 if let Some(model) = self.models.get(&handle.model_id) {
1559 model
1560 .as_any()
1561 .downcast_ref()
1562 .expect("downcast should be type safe")
1563 } else {
1564 panic!("circular model reference");
1565 }
1566 }
1567}
1568
1569impl ReadView for AppContext {
1570 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1571 if let Some(view) = self.views.get(&(handle.window_id, handle.view_id)) {
1572 view.as_any()
1573 .downcast_ref()
1574 .expect("downcast should be type safe")
1575 } else {
1576 panic!("circular view reference");
1577 }
1578 }
1579}
1580
1581struct Window {
1582 root_view: AnyViewHandle,
1583 focused_view_id: usize,
1584 invalidation: Option<WindowInvalidation>,
1585}
1586
1587#[derive(Default, Clone)]
1588pub struct WindowInvalidation {
1589 pub updated: HashSet<usize>,
1590 pub removed: Vec<usize>,
1591}
1592
1593pub enum Effect {
1594 Event {
1595 entity_id: usize,
1596 payload: Box<dyn Any>,
1597 },
1598 ModelNotification {
1599 model_id: usize,
1600 },
1601 ViewNotification {
1602 window_id: usize,
1603 view_id: usize,
1604 },
1605 Focus {
1606 window_id: usize,
1607 view_id: usize,
1608 },
1609}
1610
1611impl Debug for Effect {
1612 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1613 match self {
1614 Effect::Event { entity_id, .. } => f
1615 .debug_struct("Effect::Event")
1616 .field("entity_id", entity_id)
1617 .finish(),
1618 Effect::ModelNotification { model_id } => f
1619 .debug_struct("Effect::ModelNotification")
1620 .field("model_id", model_id)
1621 .finish(),
1622 Effect::ViewNotification { window_id, view_id } => f
1623 .debug_struct("Effect::ViewNotification")
1624 .field("window_id", window_id)
1625 .field("view_id", view_id)
1626 .finish(),
1627 Effect::Focus { window_id, view_id } => f
1628 .debug_struct("Effect::Focus")
1629 .field("window_id", window_id)
1630 .field("view_id", view_id)
1631 .finish(),
1632 }
1633 }
1634}
1635
1636pub trait AnyModel: Send + Sync {
1637 fn as_any(&self) -> &dyn Any;
1638 fn as_any_mut(&mut self) -> &mut dyn Any;
1639 fn release(&mut self, cx: &mut MutableAppContext);
1640}
1641
1642impl<T> AnyModel for T
1643where
1644 T: Entity,
1645{
1646 fn as_any(&self) -> &dyn Any {
1647 self
1648 }
1649
1650 fn as_any_mut(&mut self) -> &mut dyn Any {
1651 self
1652 }
1653
1654 fn release(&mut self, cx: &mut MutableAppContext) {
1655 self.release(cx);
1656 }
1657}
1658
1659pub trait AnyView: Send + Sync {
1660 fn as_any(&self) -> &dyn Any;
1661 fn as_any_mut(&mut self) -> &mut dyn Any;
1662 fn release(&mut self, cx: &mut MutableAppContext);
1663 fn ui_name(&self) -> &'static str;
1664 fn render<'a>(&self, window_id: usize, view_id: usize, cx: &AppContext) -> ElementBox;
1665 fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize);
1666 fn on_blur(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize);
1667 fn keymap_context(&self, cx: &AppContext) -> keymap::Context;
1668}
1669
1670impl<T> AnyView for T
1671where
1672 T: View,
1673{
1674 fn as_any(&self) -> &dyn Any {
1675 self
1676 }
1677
1678 fn as_any_mut(&mut self) -> &mut dyn Any {
1679 self
1680 }
1681
1682 fn release(&mut self, cx: &mut MutableAppContext) {
1683 self.release(cx);
1684 }
1685
1686 fn ui_name(&self) -> &'static str {
1687 T::ui_name()
1688 }
1689
1690 fn render<'a>(&self, window_id: usize, view_id: usize, cx: &AppContext) -> ElementBox {
1691 View::render(
1692 self,
1693 &RenderContext {
1694 window_id,
1695 view_id,
1696 app: cx,
1697 view_type: PhantomData::<T>,
1698 },
1699 )
1700 }
1701
1702 fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) {
1703 let mut cx = ViewContext::new(cx, window_id, view_id);
1704 View::on_focus(self, &mut cx);
1705 }
1706
1707 fn on_blur(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) {
1708 let mut cx = ViewContext::new(cx, window_id, view_id);
1709 View::on_blur(self, &mut cx);
1710 }
1711
1712 fn keymap_context(&self, cx: &AppContext) -> keymap::Context {
1713 View::keymap_context(self, cx)
1714 }
1715}
1716
1717pub struct ModelContext<'a, T: ?Sized> {
1718 app: &'a mut MutableAppContext,
1719 model_id: usize,
1720 model_type: PhantomData<T>,
1721 halt_stream: bool,
1722}
1723
1724impl<'a, T: Entity> ModelContext<'a, T> {
1725 fn new(app: &'a mut MutableAppContext, model_id: usize) -> Self {
1726 Self {
1727 app,
1728 model_id,
1729 model_type: PhantomData,
1730 halt_stream: false,
1731 }
1732 }
1733
1734 pub fn background(&self) -> &Arc<executor::Background> {
1735 &self.app.cx.background
1736 }
1737
1738 pub fn halt_stream(&mut self) {
1739 self.halt_stream = true;
1740 }
1741
1742 pub fn model_id(&self) -> usize {
1743 self.model_id
1744 }
1745
1746 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
1747 where
1748 S: Entity,
1749 F: FnOnce(&mut ModelContext<S>) -> S,
1750 {
1751 self.app.add_model(build_model)
1752 }
1753
1754 pub fn subscribe<S: Entity, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1755 where
1756 S::Event: 'static,
1757 F: 'static + FnMut(&mut T, &S::Event, &mut ModelContext<T>),
1758 {
1759 self.app
1760 .subscriptions
1761 .entry(handle.model_id)
1762 .or_default()
1763 .push(Subscription::FromModel {
1764 model_id: self.model_id,
1765 callback: Box::new(move |model, payload, app, model_id| {
1766 let model = model.downcast_mut().expect("downcast is type safe");
1767 let payload = payload.downcast_ref().expect("downcast is type safe");
1768 let mut cx = ModelContext::new(app, model_id);
1769 callback(model, payload, &mut cx);
1770 }),
1771 });
1772 }
1773
1774 pub fn emit(&mut self, payload: T::Event) {
1775 self.app.pending_effects.push_back(Effect::Event {
1776 entity_id: self.model_id,
1777 payload: Box::new(payload),
1778 });
1779 }
1780
1781 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1782 where
1783 S: Entity,
1784 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ModelContext<T>),
1785 {
1786 self.app
1787 .model_observations
1788 .entry(handle.model_id)
1789 .or_default()
1790 .push(ModelObservation::FromModel {
1791 model_id: self.model_id,
1792 callback: Box::new(move |model, observed_id, app, model_id| {
1793 let model = model.downcast_mut().expect("downcast is type safe");
1794 let observed = ModelHandle::new(observed_id, &app.cx.ref_counts);
1795 let mut cx = ModelContext::new(app, model_id);
1796 callback(model, observed, &mut cx);
1797 }),
1798 });
1799 }
1800
1801 pub fn notify(&mut self) {
1802 self.app
1803 .pending_effects
1804 .push_back(Effect::ModelNotification {
1805 model_id: self.model_id,
1806 });
1807 }
1808
1809 pub fn handle(&self) -> ModelHandle<T> {
1810 ModelHandle::new(self.model_id, &self.app.cx.ref_counts)
1811 }
1812
1813 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
1814 where
1815 F: FnOnce(ModelHandle<T>, AsyncAppContext) -> Fut,
1816 Fut: 'static + Future<Output = S>,
1817 S: 'static,
1818 {
1819 let handle = self.handle();
1820 self.app.spawn(|cx| f(handle, cx))
1821 }
1822
1823 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
1824 where
1825 F: FnOnce(WeakModelHandle<T>, AsyncAppContext) -> Fut,
1826 Fut: 'static + Future<Output = S>,
1827 S: 'static,
1828 {
1829 let handle = self.handle().downgrade();
1830 self.app.spawn(|cx| f(handle, cx))
1831 }
1832}
1833
1834impl<M> AsRef<AppContext> for ModelContext<'_, M> {
1835 fn as_ref(&self) -> &AppContext {
1836 &self.app.cx
1837 }
1838}
1839
1840impl<M> AsMut<MutableAppContext> for ModelContext<'_, M> {
1841 fn as_mut(&mut self) -> &mut MutableAppContext {
1842 self.app
1843 }
1844}
1845
1846impl<M> ReadModel for ModelContext<'_, M> {
1847 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1848 self.app.read_model(handle)
1849 }
1850}
1851
1852impl<M> UpdateModel for ModelContext<'_, M> {
1853 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1854 where
1855 T: Entity,
1856 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1857 {
1858 self.app.update_model(handle, update)
1859 }
1860}
1861
1862impl<M> Deref for ModelContext<'_, M> {
1863 type Target = MutableAppContext;
1864
1865 fn deref(&self) -> &Self::Target {
1866 &self.app
1867 }
1868}
1869
1870impl<M> DerefMut for ModelContext<'_, M> {
1871 fn deref_mut(&mut self) -> &mut Self::Target {
1872 &mut self.app
1873 }
1874}
1875
1876pub struct ViewContext<'a, T: ?Sized> {
1877 app: &'a mut MutableAppContext,
1878 window_id: usize,
1879 view_id: usize,
1880 view_type: PhantomData<T>,
1881 halt_action_dispatch: bool,
1882}
1883
1884impl<'a, T: View> ViewContext<'a, T> {
1885 fn new(app: &'a mut MutableAppContext, window_id: usize, view_id: usize) -> Self {
1886 Self {
1887 app,
1888 window_id,
1889 view_id,
1890 view_type: PhantomData,
1891 halt_action_dispatch: true,
1892 }
1893 }
1894
1895 pub fn handle(&self) -> ViewHandle<T> {
1896 ViewHandle::new(self.window_id, self.view_id, &self.app.cx.ref_counts)
1897 }
1898
1899 pub fn window_id(&self) -> usize {
1900 self.window_id
1901 }
1902
1903 pub fn view_id(&self) -> usize {
1904 self.view_id
1905 }
1906
1907 pub fn foreground(&self) -> &Rc<executor::Foreground> {
1908 self.app.foreground()
1909 }
1910
1911 pub fn background_executor(&self) -> &Arc<executor::Background> {
1912 &self.app.cx.background
1913 }
1914
1915 pub fn platform(&self) -> Arc<dyn Platform> {
1916 self.app.platform()
1917 }
1918
1919 pub fn prompt<F>(&self, level: PromptLevel, msg: &str, answers: &[&str], done_fn: F)
1920 where
1921 F: 'static + FnOnce(usize, &mut MutableAppContext),
1922 {
1923 self.app
1924 .prompt(self.window_id, level, msg, answers, done_fn)
1925 }
1926
1927 pub fn prompt_for_paths<F>(&self, options: PathPromptOptions, done_fn: F)
1928 where
1929 F: 'static + FnOnce(Option<Vec<PathBuf>>, &mut MutableAppContext),
1930 {
1931 self.app.prompt_for_paths(options, done_fn)
1932 }
1933
1934 pub fn prompt_for_new_path<F>(&self, directory: &Path, done_fn: F)
1935 where
1936 F: 'static + FnOnce(Option<PathBuf>, &mut MutableAppContext),
1937 {
1938 self.app.prompt_for_new_path(directory, done_fn)
1939 }
1940
1941 pub fn debug_elements(&self) -> crate::json::Value {
1942 self.app.debug_elements(self.window_id).unwrap()
1943 }
1944
1945 pub fn focus<S>(&mut self, handle: S)
1946 where
1947 S: Into<AnyViewHandle>,
1948 {
1949 let handle = handle.into();
1950 self.app.pending_effects.push_back(Effect::Focus {
1951 window_id: handle.window_id,
1952 view_id: handle.view_id,
1953 });
1954 }
1955
1956 pub fn focus_self(&mut self) {
1957 self.app.pending_effects.push_back(Effect::Focus {
1958 window_id: self.window_id,
1959 view_id: self.view_id,
1960 });
1961 }
1962
1963 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
1964 where
1965 S: Entity,
1966 F: FnOnce(&mut ModelContext<S>) -> S,
1967 {
1968 self.app.add_model(build_model)
1969 }
1970
1971 pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
1972 where
1973 S: View,
1974 F: FnOnce(&mut ViewContext<S>) -> S,
1975 {
1976 self.app.add_view(self.window_id, build_view)
1977 }
1978
1979 pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
1980 where
1981 S: View,
1982 F: FnOnce(&mut ViewContext<S>) -> Option<S>,
1983 {
1984 self.app.add_option_view(self.window_id, build_view)
1985 }
1986
1987 pub fn subscribe_to_model<E, F>(&mut self, handle: &ModelHandle<E>, mut callback: F)
1988 where
1989 E: Entity,
1990 E::Event: 'static,
1991 F: 'static + FnMut(&mut T, ModelHandle<E>, &E::Event, &mut ViewContext<T>),
1992 {
1993 let emitter_handle = handle.downgrade();
1994 self.subscribe(handle, move |model, payload, cx| {
1995 if let Some(emitter_handle) = emitter_handle.upgrade(cx.as_ref()) {
1996 callback(model, emitter_handle, payload, cx);
1997 }
1998 });
1999 }
2000
2001 pub fn subscribe_to_view<V, F>(&mut self, handle: &ViewHandle<V>, mut callback: F)
2002 where
2003 V: View,
2004 V::Event: 'static,
2005 F: 'static + FnMut(&mut T, ViewHandle<V>, &V::Event, &mut ViewContext<T>),
2006 {
2007 let emitter_handle = handle.downgrade();
2008 self.subscribe(handle, move |view, payload, cx| {
2009 if let Some(emitter_handle) = emitter_handle.upgrade(cx.as_ref()) {
2010 callback(view, emitter_handle, payload, cx);
2011 }
2012 });
2013 }
2014
2015 pub fn subscribe<E, F>(&mut self, handle: &impl Handle<E>, mut callback: F)
2016 where
2017 E: Entity,
2018 E::Event: 'static,
2019 F: 'static + FnMut(&mut T, &E::Event, &mut ViewContext<T>),
2020 {
2021 self.app
2022 .subscriptions
2023 .entry(handle.id())
2024 .or_default()
2025 .push(Subscription::FromView {
2026 window_id: self.window_id,
2027 view_id: self.view_id,
2028 callback: Box::new(move |entity, payload, app, window_id, view_id| {
2029 let entity = entity.downcast_mut().expect("downcast is type safe");
2030 let payload = payload.downcast_ref().expect("downcast is type safe");
2031 let mut cx = ViewContext::new(app, window_id, view_id);
2032 callback(entity, payload, &mut cx);
2033 }),
2034 });
2035 }
2036
2037 pub fn emit(&mut self, payload: T::Event) {
2038 self.app.pending_effects.push_back(Effect::Event {
2039 entity_id: self.view_id,
2040 payload: Box::new(payload),
2041 });
2042 }
2043
2044 pub fn observe_model<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
2045 where
2046 S: Entity,
2047 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ViewContext<T>),
2048 {
2049 self.app
2050 .model_observations
2051 .entry(handle.id())
2052 .or_default()
2053 .push(ModelObservation::FromView {
2054 window_id: self.window_id,
2055 view_id: self.view_id,
2056 callback: Box::new(move |view, observed_id, app, window_id, view_id| {
2057 let view = view.downcast_mut().expect("downcast is type safe");
2058 let observed = ModelHandle::new(observed_id, &app.cx.ref_counts);
2059 let mut cx = ViewContext::new(app, window_id, view_id);
2060 callback(view, observed, &mut cx);
2061 }),
2062 });
2063 }
2064
2065 pub fn observe_view<S, F>(&mut self, handle: &ViewHandle<S>, mut callback: F)
2066 where
2067 S: View,
2068 F: 'static + FnMut(&mut T, ViewHandle<S>, &mut ViewContext<T>),
2069 {
2070 self.app
2071 .view_observations
2072 .entry(handle.id())
2073 .or_default()
2074 .push(ViewObservation {
2075 window_id: self.window_id,
2076 view_id: self.view_id,
2077 callback: Box::new(
2078 move |view,
2079 observed_view_id,
2080 observed_window_id,
2081 app,
2082 observing_window_id,
2083 observing_view_id| {
2084 let view = view.downcast_mut().expect("downcast is type safe");
2085 let observed_handle = ViewHandle::new(
2086 observed_view_id,
2087 observed_window_id,
2088 &app.cx.ref_counts,
2089 );
2090 let mut cx = ViewContext::new(app, observing_window_id, observing_view_id);
2091 callback(view, observed_handle, &mut cx);
2092 },
2093 ),
2094 });
2095 }
2096
2097 pub fn notify(&mut self) {
2098 self.app.notify_view(self.window_id, self.view_id);
2099 }
2100
2101 pub fn notify_all(&mut self) {
2102 self.app.notify_all_views();
2103 }
2104
2105 pub fn propagate_action(&mut self) {
2106 self.halt_action_dispatch = false;
2107 }
2108
2109 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
2110 where
2111 F: FnOnce(ViewHandle<T>, AsyncAppContext) -> Fut,
2112 Fut: 'static + Future<Output = S>,
2113 S: 'static,
2114 {
2115 let handle = self.handle();
2116 self.app.spawn(|cx| f(handle, cx))
2117 }
2118}
2119
2120pub struct RenderContext<'a, T: View> {
2121 pub app: &'a AppContext,
2122 window_id: usize,
2123 view_id: usize,
2124 view_type: PhantomData<T>,
2125}
2126
2127impl<'a, T: View> RenderContext<'a, T> {
2128 pub fn handle(&self) -> WeakViewHandle<T> {
2129 WeakViewHandle::new(self.window_id, self.view_id)
2130 }
2131}
2132
2133impl AsRef<AppContext> for &AppContext {
2134 fn as_ref(&self) -> &AppContext {
2135 self
2136 }
2137}
2138
2139impl<V: View> Deref for RenderContext<'_, V> {
2140 type Target = AppContext;
2141
2142 fn deref(&self) -> &Self::Target {
2143 &self.app
2144 }
2145}
2146
2147impl<M> AsRef<AppContext> for ViewContext<'_, M> {
2148 fn as_ref(&self) -> &AppContext {
2149 &self.app.cx
2150 }
2151}
2152
2153impl<M> Deref for ViewContext<'_, M> {
2154 type Target = MutableAppContext;
2155
2156 fn deref(&self) -> &Self::Target {
2157 &self.app
2158 }
2159}
2160
2161impl<M> DerefMut for ViewContext<'_, M> {
2162 fn deref_mut(&mut self) -> &mut Self::Target {
2163 &mut self.app
2164 }
2165}
2166
2167impl<M> AsMut<MutableAppContext> for ViewContext<'_, M> {
2168 fn as_mut(&mut self) -> &mut MutableAppContext {
2169 self.app
2170 }
2171}
2172
2173impl<V> ReadModel for ViewContext<'_, V> {
2174 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2175 self.app.read_model(handle)
2176 }
2177}
2178
2179impl<V: View> UpdateModel for ViewContext<'_, V> {
2180 fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
2181 where
2182 T: Entity,
2183 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
2184 {
2185 self.app.update_model(handle, update)
2186 }
2187}
2188
2189impl<V: View> ReadView for ViewContext<'_, V> {
2190 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2191 self.app.read_view(handle)
2192 }
2193}
2194
2195impl<V: View> UpdateView for ViewContext<'_, V> {
2196 fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
2197 where
2198 T: View,
2199 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
2200 {
2201 self.app.update_view(handle, update)
2202 }
2203}
2204
2205pub trait Handle<T> {
2206 fn id(&self) -> usize;
2207 fn location(&self) -> EntityLocation;
2208}
2209
2210#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
2211pub enum EntityLocation {
2212 Model(usize),
2213 View(usize, usize),
2214}
2215
2216pub struct ModelHandle<T> {
2217 model_id: usize,
2218 model_type: PhantomData<T>,
2219 ref_counts: Arc<Mutex<RefCounts>>,
2220}
2221
2222impl<T: Entity> ModelHandle<T> {
2223 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
2224 ref_counts.lock().inc_model(model_id);
2225 Self {
2226 model_id,
2227 model_type: PhantomData,
2228 ref_counts: ref_counts.clone(),
2229 }
2230 }
2231
2232 pub fn downgrade(&self) -> WeakModelHandle<T> {
2233 WeakModelHandle::new(self.model_id)
2234 }
2235
2236 pub fn id(&self) -> usize {
2237 self.model_id
2238 }
2239
2240 pub fn read<'a, C: ReadModel>(&self, cx: &'a C) -> &'a T {
2241 cx.read_model(self)
2242 }
2243
2244 pub fn read_with<'a, C, F, S>(&self, cx: &C, read: F) -> S
2245 where
2246 C: ReadModelWith,
2247 F: FnOnce(&T, &AppContext) -> S,
2248 {
2249 cx.read_model_with(self, read)
2250 }
2251
2252 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
2253 where
2254 C: UpdateModel,
2255 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
2256 {
2257 cx.update_model(self, update)
2258 }
2259
2260 pub fn condition(
2261 &self,
2262 cx: &TestAppContext,
2263 mut predicate: impl FnMut(&T, &AppContext) -> bool,
2264 ) -> impl Future<Output = ()> {
2265 let (tx, mut rx) = mpsc::channel(1024);
2266
2267 let mut cx = cx.cx.borrow_mut();
2268 self.update(&mut *cx, |_, cx| {
2269 cx.observe(self, {
2270 let mut tx = tx.clone();
2271 move |_, _, _| {
2272 tx.blocking_send(()).ok();
2273 }
2274 });
2275 cx.subscribe(self, {
2276 let mut tx = tx.clone();
2277 move |_, _, _| {
2278 tx.blocking_send(()).ok();
2279 }
2280 })
2281 });
2282
2283 let cx = cx.weak_self.as_ref().unwrap().upgrade().unwrap();
2284 let handle = self.downgrade();
2285 let duration = if std::env::var("CI").is_ok() {
2286 Duration::from_secs(5)
2287 } else {
2288 Duration::from_secs(1)
2289 };
2290
2291 async move {
2292 timeout(duration, async move {
2293 loop {
2294 {
2295 let cx = cx.borrow();
2296 let cx = cx.as_ref();
2297 if predicate(
2298 handle
2299 .upgrade(cx)
2300 .expect("model dropped with pending condition")
2301 .read(cx),
2302 cx,
2303 ) {
2304 break;
2305 }
2306 }
2307
2308 rx.recv()
2309 .await
2310 .expect("model dropped with pending condition");
2311 }
2312 })
2313 .await
2314 .expect("condition timed out");
2315 }
2316 }
2317}
2318
2319impl<T> Clone for ModelHandle<T> {
2320 fn clone(&self) -> Self {
2321 self.ref_counts.lock().inc_model(self.model_id);
2322 Self {
2323 model_id: self.model_id,
2324 model_type: PhantomData,
2325 ref_counts: self.ref_counts.clone(),
2326 }
2327 }
2328}
2329
2330impl<T> PartialEq for ModelHandle<T> {
2331 fn eq(&self, other: &Self) -> bool {
2332 self.model_id == other.model_id
2333 }
2334}
2335
2336impl<T> Eq for ModelHandle<T> {}
2337
2338impl<T> Hash for ModelHandle<T> {
2339 fn hash<H: Hasher>(&self, state: &mut H) {
2340 self.model_id.hash(state);
2341 }
2342}
2343
2344impl<T> std::borrow::Borrow<usize> for ModelHandle<T> {
2345 fn borrow(&self) -> &usize {
2346 &self.model_id
2347 }
2348}
2349
2350impl<T> Debug for ModelHandle<T> {
2351 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2352 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
2353 .field(&self.model_id)
2354 .finish()
2355 }
2356}
2357
2358unsafe impl<T> Send for ModelHandle<T> {}
2359unsafe impl<T> Sync for ModelHandle<T> {}
2360
2361impl<T> Drop for ModelHandle<T> {
2362 fn drop(&mut self) {
2363 self.ref_counts.lock().dec_model(self.model_id);
2364 }
2365}
2366
2367impl<T> Handle<T> for ModelHandle<T> {
2368 fn id(&self) -> usize {
2369 self.model_id
2370 }
2371
2372 fn location(&self) -> EntityLocation {
2373 EntityLocation::Model(self.model_id)
2374 }
2375}
2376
2377pub struct WeakModelHandle<T> {
2378 model_id: usize,
2379 model_type: PhantomData<T>,
2380}
2381
2382impl<T: Entity> WeakModelHandle<T> {
2383 fn new(model_id: usize) -> Self {
2384 Self {
2385 model_id,
2386 model_type: PhantomData,
2387 }
2388 }
2389
2390 pub fn upgrade(&self, cx: impl AsRef<AppContext>) -> Option<ModelHandle<T>> {
2391 let cx = cx.as_ref();
2392 if cx.models.contains_key(&self.model_id) {
2393 Some(ModelHandle::new(self.model_id, &cx.ref_counts))
2394 } else {
2395 None
2396 }
2397 }
2398}
2399
2400impl<T> Hash for WeakModelHandle<T> {
2401 fn hash<H: Hasher>(&self, state: &mut H) {
2402 self.model_id.hash(state)
2403 }
2404}
2405
2406impl<T> PartialEq for WeakModelHandle<T> {
2407 fn eq(&self, other: &Self) -> bool {
2408 self.model_id == other.model_id
2409 }
2410}
2411
2412impl<T> Eq for WeakModelHandle<T> {}
2413
2414impl<T> Clone for WeakModelHandle<T> {
2415 fn clone(&self) -> Self {
2416 Self {
2417 model_id: self.model_id,
2418 model_type: PhantomData,
2419 }
2420 }
2421}
2422
2423pub struct ViewHandle<T> {
2424 window_id: usize,
2425 view_id: usize,
2426 view_type: PhantomData<T>,
2427 ref_counts: Arc<Mutex<RefCounts>>,
2428}
2429
2430impl<T: View> ViewHandle<T> {
2431 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
2432 ref_counts.lock().inc_view(window_id, view_id);
2433 Self {
2434 window_id,
2435 view_id,
2436 view_type: PhantomData,
2437 ref_counts: ref_counts.clone(),
2438 }
2439 }
2440
2441 pub fn downgrade(&self) -> WeakViewHandle<T> {
2442 WeakViewHandle::new(self.window_id, self.view_id)
2443 }
2444
2445 pub fn window_id(&self) -> usize {
2446 self.window_id
2447 }
2448
2449 pub fn id(&self) -> usize {
2450 self.view_id
2451 }
2452
2453 pub fn read<'a, C: ReadView>(&self, cx: &'a C) -> &'a T {
2454 cx.read_view(self)
2455 }
2456
2457 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
2458 where
2459 C: ReadViewWith,
2460 F: FnOnce(&T, &AppContext) -> S,
2461 {
2462 cx.read_view_with(self, read)
2463 }
2464
2465 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
2466 where
2467 C: UpdateView,
2468 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
2469 {
2470 cx.update_view(self, update)
2471 }
2472
2473 pub fn is_focused(&self, cx: &AppContext) -> bool {
2474 cx.focused_view_id(self.window_id)
2475 .map_or(false, |focused_id| focused_id == self.view_id)
2476 }
2477
2478 pub fn condition(
2479 &self,
2480 cx: &TestAppContext,
2481 mut predicate: impl FnMut(&T, &AppContext) -> bool,
2482 ) -> impl Future<Output = ()> {
2483 let (tx, mut rx) = mpsc::channel(1024);
2484
2485 let mut cx = cx.cx.borrow_mut();
2486 self.update(&mut *cx, |_, cx| {
2487 cx.observe_view(self, {
2488 let mut tx = tx.clone();
2489 move |_, _, _| {
2490 tx.blocking_send(()).ok();
2491 }
2492 });
2493
2494 cx.subscribe(self, {
2495 let mut tx = tx.clone();
2496 move |_, _, _| {
2497 tx.blocking_send(()).ok();
2498 }
2499 })
2500 });
2501
2502 let cx = cx.weak_self.as_ref().unwrap().upgrade().unwrap();
2503 let handle = self.downgrade();
2504 let duration = if std::env::var("CI").is_ok() {
2505 Duration::from_secs(2)
2506 } else {
2507 Duration::from_millis(500)
2508 };
2509
2510 async move {
2511 timeout(duration, async move {
2512 loop {
2513 {
2514 let cx = cx.borrow();
2515 let cx = cx.as_ref();
2516 if predicate(
2517 handle
2518 .upgrade(cx)
2519 .expect("view dropped with pending condition")
2520 .read(cx),
2521 cx,
2522 ) {
2523 break;
2524 }
2525 }
2526
2527 rx.recv()
2528 .await
2529 .expect("view dropped with pending condition");
2530 }
2531 })
2532 .await
2533 .expect("condition timed out");
2534 }
2535 }
2536}
2537
2538impl<T> Clone for ViewHandle<T> {
2539 fn clone(&self) -> Self {
2540 self.ref_counts
2541 .lock()
2542 .inc_view(self.window_id, self.view_id);
2543 Self {
2544 window_id: self.window_id,
2545 view_id: self.view_id,
2546 view_type: PhantomData,
2547 ref_counts: self.ref_counts.clone(),
2548 }
2549 }
2550}
2551
2552impl<T> PartialEq for ViewHandle<T> {
2553 fn eq(&self, other: &Self) -> bool {
2554 self.window_id == other.window_id && self.view_id == other.view_id
2555 }
2556}
2557
2558impl<T> Eq for ViewHandle<T> {}
2559
2560impl<T> Debug for ViewHandle<T> {
2561 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2562 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
2563 .field("window_id", &self.window_id)
2564 .field("view_id", &self.view_id)
2565 .finish()
2566 }
2567}
2568
2569impl<T> Drop for ViewHandle<T> {
2570 fn drop(&mut self) {
2571 self.ref_counts
2572 .lock()
2573 .dec_view(self.window_id, self.view_id);
2574 }
2575}
2576
2577impl<T> Handle<T> for ViewHandle<T> {
2578 fn id(&self) -> usize {
2579 self.view_id
2580 }
2581
2582 fn location(&self) -> EntityLocation {
2583 EntityLocation::View(self.window_id, self.view_id)
2584 }
2585}
2586
2587pub struct AnyViewHandle {
2588 window_id: usize,
2589 view_id: usize,
2590 view_type: TypeId,
2591 ref_counts: Arc<Mutex<RefCounts>>,
2592}
2593
2594impl AnyViewHandle {
2595 pub fn id(&self) -> usize {
2596 self.view_id
2597 }
2598
2599 pub fn is<T: 'static>(&self) -> bool {
2600 TypeId::of::<T>() == self.view_type
2601 }
2602
2603 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
2604 if self.is::<T>() {
2605 let result = Some(ViewHandle {
2606 window_id: self.window_id,
2607 view_id: self.view_id,
2608 ref_counts: self.ref_counts.clone(),
2609 view_type: PhantomData,
2610 });
2611 unsafe {
2612 Arc::decrement_strong_count(&self.ref_counts);
2613 }
2614 std::mem::forget(self);
2615 result
2616 } else {
2617 None
2618 }
2619 }
2620}
2621
2622impl Clone for AnyViewHandle {
2623 fn clone(&self) -> Self {
2624 self.ref_counts
2625 .lock()
2626 .inc_view(self.window_id, self.view_id);
2627 Self {
2628 window_id: self.window_id,
2629 view_id: self.view_id,
2630 view_type: self.view_type,
2631 ref_counts: self.ref_counts.clone(),
2632 }
2633 }
2634}
2635
2636impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
2637 fn from(handle: &ViewHandle<T>) -> Self {
2638 handle
2639 .ref_counts
2640 .lock()
2641 .inc_view(handle.window_id, handle.view_id);
2642 AnyViewHandle {
2643 window_id: handle.window_id,
2644 view_id: handle.view_id,
2645 view_type: TypeId::of::<T>(),
2646 ref_counts: handle.ref_counts.clone(),
2647 }
2648 }
2649}
2650
2651impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
2652 fn from(handle: ViewHandle<T>) -> Self {
2653 let any_handle = AnyViewHandle {
2654 window_id: handle.window_id,
2655 view_id: handle.view_id,
2656 view_type: TypeId::of::<T>(),
2657 ref_counts: handle.ref_counts.clone(),
2658 };
2659 unsafe {
2660 Arc::decrement_strong_count(&handle.ref_counts);
2661 }
2662 std::mem::forget(handle);
2663 any_handle
2664 }
2665}
2666
2667impl Drop for AnyViewHandle {
2668 fn drop(&mut self) {
2669 self.ref_counts
2670 .lock()
2671 .dec_view(self.window_id, self.view_id);
2672 }
2673}
2674
2675pub struct AnyModelHandle {
2676 model_id: usize,
2677 ref_counts: Arc<Mutex<RefCounts>>,
2678}
2679
2680impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
2681 fn from(handle: ModelHandle<T>) -> Self {
2682 handle.ref_counts.lock().inc_model(handle.model_id);
2683 Self {
2684 model_id: handle.model_id,
2685 ref_counts: handle.ref_counts.clone(),
2686 }
2687 }
2688}
2689
2690impl Drop for AnyModelHandle {
2691 fn drop(&mut self) {
2692 self.ref_counts.lock().dec_model(self.model_id);
2693 }
2694}
2695pub struct WeakViewHandle<T> {
2696 window_id: usize,
2697 view_id: usize,
2698 view_type: PhantomData<T>,
2699}
2700
2701impl<T: View> WeakViewHandle<T> {
2702 fn new(window_id: usize, view_id: usize) -> Self {
2703 Self {
2704 window_id,
2705 view_id,
2706 view_type: PhantomData,
2707 }
2708 }
2709
2710 pub fn upgrade(&self, cx: &AppContext) -> Option<ViewHandle<T>> {
2711 if cx.ref_counts.lock().is_entity_alive(self.view_id) {
2712 Some(ViewHandle::new(
2713 self.window_id,
2714 self.view_id,
2715 &cx.ref_counts,
2716 ))
2717 } else {
2718 None
2719 }
2720 }
2721}
2722
2723impl<T> Clone for WeakViewHandle<T> {
2724 fn clone(&self) -> Self {
2725 Self {
2726 window_id: self.window_id,
2727 view_id: self.view_id,
2728 view_type: PhantomData,
2729 }
2730 }
2731}
2732
2733pub struct ValueHandle<T> {
2734 value_type: PhantomData<T>,
2735 tag_type_id: TypeId,
2736 id: usize,
2737 ref_counts: Weak<Mutex<RefCounts>>,
2738}
2739
2740impl<T: 'static> ValueHandle<T> {
2741 fn new(tag_type_id: TypeId, id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
2742 ref_counts.lock().inc_value(tag_type_id, id);
2743 Self {
2744 value_type: PhantomData,
2745 tag_type_id,
2746 id,
2747 ref_counts: Arc::downgrade(ref_counts),
2748 }
2749 }
2750
2751 pub fn read<R>(&self, cx: &AppContext, f: impl FnOnce(&T) -> R) -> R {
2752 f(cx.values
2753 .read()
2754 .get(&(self.tag_type_id, self.id))
2755 .unwrap()
2756 .downcast_ref()
2757 .unwrap())
2758 }
2759
2760 pub fn update<R>(
2761 &self,
2762 cx: &mut EventContext,
2763 f: impl FnOnce(&mut T, &mut EventContext) -> R,
2764 ) -> R {
2765 let mut value = cx
2766 .app
2767 .cx
2768 .values
2769 .write()
2770 .remove(&(self.tag_type_id, self.id))
2771 .unwrap();
2772 let result = f(value.downcast_mut().unwrap(), cx);
2773 cx.app
2774 .cx
2775 .values
2776 .write()
2777 .insert((self.tag_type_id, self.id), value);
2778 result
2779 }
2780}
2781
2782impl<T> Drop for ValueHandle<T> {
2783 fn drop(&mut self) {
2784 if let Some(ref_counts) = self.ref_counts.upgrade() {
2785 ref_counts.lock().dec_value(self.tag_type_id, self.id);
2786 }
2787 }
2788}
2789
2790#[derive(Default)]
2791struct RefCounts {
2792 entity_counts: HashMap<usize, usize>,
2793 value_counts: HashMap<(TypeId, usize), usize>,
2794 dropped_models: HashSet<usize>,
2795 dropped_views: HashSet<(usize, usize)>,
2796 dropped_values: HashSet<(TypeId, usize)>,
2797}
2798
2799impl RefCounts {
2800 fn inc_model(&mut self, model_id: usize) {
2801 match self.entity_counts.entry(model_id) {
2802 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
2803 Entry::Vacant(entry) => {
2804 entry.insert(1);
2805 self.dropped_models.remove(&model_id);
2806 }
2807 }
2808 }
2809
2810 fn inc_view(&mut self, window_id: usize, view_id: usize) {
2811 match self.entity_counts.entry(view_id) {
2812 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
2813 Entry::Vacant(entry) => {
2814 entry.insert(1);
2815 self.dropped_views.remove(&(window_id, view_id));
2816 }
2817 }
2818 }
2819
2820 fn inc_value(&mut self, tag_type_id: TypeId, id: usize) {
2821 *self.value_counts.entry((tag_type_id, id)).or_insert(0) += 1;
2822 }
2823
2824 fn dec_model(&mut self, model_id: usize) {
2825 let count = self.entity_counts.get_mut(&model_id).unwrap();
2826 *count -= 1;
2827 if *count == 0 {
2828 self.entity_counts.remove(&model_id);
2829 self.dropped_models.insert(model_id);
2830 }
2831 }
2832
2833 fn dec_view(&mut self, window_id: usize, view_id: usize) {
2834 let count = self.entity_counts.get_mut(&view_id).unwrap();
2835 *count -= 1;
2836 if *count == 0 {
2837 self.entity_counts.remove(&view_id);
2838 self.dropped_views.insert((window_id, view_id));
2839 }
2840 }
2841
2842 fn dec_value(&mut self, tag_type_id: TypeId, id: usize) {
2843 let key = (tag_type_id, id);
2844 let count = self.value_counts.get_mut(&key).unwrap();
2845 *count -= 1;
2846 if *count == 0 {
2847 self.value_counts.remove(&key);
2848 self.dropped_values.insert(key);
2849 }
2850 }
2851
2852 fn is_entity_alive(&self, entity_id: usize) -> bool {
2853 self.entity_counts.contains_key(&entity_id)
2854 }
2855
2856 fn take_dropped(
2857 &mut self,
2858 ) -> (
2859 HashSet<usize>,
2860 HashSet<(usize, usize)>,
2861 HashSet<(TypeId, usize)>,
2862 ) {
2863 let mut dropped_models = HashSet::new();
2864 let mut dropped_views = HashSet::new();
2865 let mut dropped_values = HashSet::new();
2866 std::mem::swap(&mut self.dropped_models, &mut dropped_models);
2867 std::mem::swap(&mut self.dropped_views, &mut dropped_views);
2868 std::mem::swap(&mut self.dropped_values, &mut dropped_values);
2869 (dropped_models, dropped_views, dropped_values)
2870 }
2871}
2872
2873enum Subscription {
2874 FromModel {
2875 model_id: usize,
2876 callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize)>,
2877 },
2878 FromView {
2879 window_id: usize,
2880 view_id: usize,
2881 callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize, usize)>,
2882 },
2883}
2884
2885enum ModelObservation {
2886 FromModel {
2887 model_id: usize,
2888 callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize)>,
2889 },
2890 FromView {
2891 window_id: usize,
2892 view_id: usize,
2893 callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize, usize)>,
2894 },
2895}
2896
2897struct ViewObservation {
2898 window_id: usize,
2899 view_id: usize,
2900 callback: Box<dyn FnMut(&mut dyn Any, usize, usize, &mut MutableAppContext, usize, usize)>,
2901}
2902
2903#[cfg(test)]
2904mod tests {
2905 use super::*;
2906 use crate::elements::*;
2907 use smol::future::poll_once;
2908 use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
2909
2910 #[crate::test(self)]
2911 fn test_model_handles(cx: &mut MutableAppContext) {
2912 struct Model {
2913 other: Option<ModelHandle<Model>>,
2914 events: Vec<String>,
2915 }
2916
2917 impl Entity for Model {
2918 type Event = usize;
2919 }
2920
2921 impl Model {
2922 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
2923 if let Some(other) = other.as_ref() {
2924 cx.observe(other, |me, _, _| {
2925 me.events.push("notified".into());
2926 });
2927 cx.subscribe(other, |me, event, _| {
2928 me.events.push(format!("observed event {}", event));
2929 });
2930 }
2931
2932 Self {
2933 other,
2934 events: Vec::new(),
2935 }
2936 }
2937 }
2938
2939 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
2940 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
2941 assert_eq!(cx.cx.models.len(), 2);
2942
2943 handle_1.update(cx, |model, cx| {
2944 model.events.push("updated".into());
2945 cx.emit(1);
2946 cx.notify();
2947 cx.emit(2);
2948 });
2949 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
2950 assert_eq!(
2951 handle_2.read(cx).events,
2952 vec![
2953 "observed event 1".to_string(),
2954 "notified".to_string(),
2955 "observed event 2".to_string(),
2956 ]
2957 );
2958
2959 handle_2.update(cx, |model, _| {
2960 drop(handle_1);
2961 model.other.take();
2962 });
2963
2964 assert_eq!(cx.cx.models.len(), 1);
2965 assert!(cx.subscriptions.is_empty());
2966 assert!(cx.model_observations.is_empty());
2967 }
2968
2969 #[crate::test(self)]
2970 fn test_subscribe_and_emit_from_model(cx: &mut MutableAppContext) {
2971 #[derive(Default)]
2972 struct Model {
2973 events: Vec<usize>,
2974 }
2975
2976 impl Entity for Model {
2977 type Event = usize;
2978 }
2979
2980 let handle_1 = cx.add_model(|_| Model::default());
2981 let handle_2 = cx.add_model(|_| Model::default());
2982 let handle_2b = handle_2.clone();
2983
2984 handle_1.update(cx, |_, c| {
2985 c.subscribe(&handle_2, move |model: &mut Model, event, c| {
2986 model.events.push(*event);
2987
2988 c.subscribe(&handle_2b, |model, event, _| {
2989 model.events.push(*event * 2);
2990 });
2991 });
2992 });
2993
2994 handle_2.update(cx, |_, c| c.emit(7));
2995 assert_eq!(handle_1.read(cx).events, vec![7]);
2996
2997 handle_2.update(cx, |_, c| c.emit(5));
2998 assert_eq!(handle_1.read(cx).events, vec![7, 10, 5]);
2999 }
3000
3001 #[crate::test(self)]
3002 fn test_observe_and_notify_from_model(cx: &mut MutableAppContext) {
3003 #[derive(Default)]
3004 struct Model {
3005 count: usize,
3006 events: Vec<usize>,
3007 }
3008
3009 impl Entity for Model {
3010 type Event = ();
3011 }
3012
3013 let handle_1 = cx.add_model(|_| Model::default());
3014 let handle_2 = cx.add_model(|_| Model::default());
3015 let handle_2b = handle_2.clone();
3016
3017 handle_1.update(cx, |_, c| {
3018 c.observe(&handle_2, move |model, observed, c| {
3019 model.events.push(observed.read(c).count);
3020 c.observe(&handle_2b, |model, observed, c| {
3021 model.events.push(observed.read(c).count * 2);
3022 });
3023 });
3024 });
3025
3026 handle_2.update(cx, |model, c| {
3027 model.count = 7;
3028 c.notify()
3029 });
3030 assert_eq!(handle_1.read(cx).events, vec![7]);
3031
3032 handle_2.update(cx, |model, c| {
3033 model.count = 5;
3034 c.notify()
3035 });
3036 assert_eq!(handle_1.read(cx).events, vec![7, 10, 5])
3037 }
3038
3039 #[crate::test(self)]
3040 fn test_view_handles(cx: &mut MutableAppContext) {
3041 struct View {
3042 other: Option<ViewHandle<View>>,
3043 events: Vec<String>,
3044 }
3045
3046 impl Entity for View {
3047 type Event = usize;
3048 }
3049
3050 impl super::View for View {
3051 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3052 Empty::new().boxed()
3053 }
3054
3055 fn ui_name() -> &'static str {
3056 "View"
3057 }
3058 }
3059
3060 impl View {
3061 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
3062 if let Some(other) = other.as_ref() {
3063 cx.subscribe_to_view(other, |me, _, event, _| {
3064 me.events.push(format!("observed event {}", event));
3065 });
3066 }
3067 Self {
3068 other,
3069 events: Vec::new(),
3070 }
3071 }
3072 }
3073
3074 let (window_id, _) = cx.add_window(Default::default(), |cx| View::new(None, cx));
3075 let handle_1 = cx.add_view(window_id, |cx| View::new(None, cx));
3076 let handle_2 = cx.add_view(window_id, |cx| View::new(Some(handle_1.clone()), cx));
3077 assert_eq!(cx.cx.views.len(), 3);
3078
3079 handle_1.update(cx, |view, cx| {
3080 view.events.push("updated".into());
3081 cx.emit(1);
3082 cx.emit(2);
3083 });
3084 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
3085 assert_eq!(
3086 handle_2.read(cx).events,
3087 vec![
3088 "observed event 1".to_string(),
3089 "observed event 2".to_string(),
3090 ]
3091 );
3092
3093 handle_2.update(cx, |view, _| {
3094 drop(handle_1);
3095 view.other.take();
3096 });
3097
3098 assert_eq!(cx.cx.views.len(), 2);
3099 assert!(cx.subscriptions.is_empty());
3100 assert!(cx.model_observations.is_empty());
3101 }
3102
3103 #[crate::test(self)]
3104 fn test_add_window(cx: &mut MutableAppContext) {
3105 struct View {
3106 mouse_down_count: Arc<AtomicUsize>,
3107 }
3108
3109 impl Entity for View {
3110 type Event = ();
3111 }
3112
3113 impl super::View for View {
3114 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3115 let mouse_down_count = self.mouse_down_count.clone();
3116 EventHandler::new(Empty::new().boxed())
3117 .on_mouse_down(move |_| {
3118 mouse_down_count.fetch_add(1, SeqCst);
3119 true
3120 })
3121 .boxed()
3122 }
3123
3124 fn ui_name() -> &'static str {
3125 "View"
3126 }
3127 }
3128
3129 let mouse_down_count = Arc::new(AtomicUsize::new(0));
3130 let (window_id, _) = cx.add_window(Default::default(), |_| View {
3131 mouse_down_count: mouse_down_count.clone(),
3132 });
3133 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
3134 // Ensure window's root element is in a valid lifecycle state.
3135 presenter.borrow_mut().dispatch_event(
3136 Event::LeftMouseDown {
3137 position: Default::default(),
3138 cmd: false,
3139 },
3140 cx,
3141 );
3142 assert_eq!(mouse_down_count.load(SeqCst), 1);
3143 }
3144
3145 #[crate::test(self)]
3146 fn test_entity_release_hooks(cx: &mut MutableAppContext) {
3147 struct Model {
3148 released: Arc<Mutex<bool>>,
3149 }
3150
3151 struct View {
3152 released: Arc<Mutex<bool>>,
3153 }
3154
3155 impl Entity for Model {
3156 type Event = ();
3157
3158 fn release(&mut self, _: &mut MutableAppContext) {
3159 *self.released.lock() = true;
3160 }
3161 }
3162
3163 impl Entity for View {
3164 type Event = ();
3165
3166 fn release(&mut self, _: &mut MutableAppContext) {
3167 *self.released.lock() = true;
3168 }
3169 }
3170
3171 impl super::View for View {
3172 fn ui_name() -> &'static str {
3173 "View"
3174 }
3175
3176 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3177 Empty::new().boxed()
3178 }
3179 }
3180
3181 let model_released = Arc::new(Mutex::new(false));
3182 let view_released = Arc::new(Mutex::new(false));
3183
3184 let model = cx.add_model(|_| Model {
3185 released: model_released.clone(),
3186 });
3187
3188 let (window_id, _) = cx.add_window(Default::default(), |_| View {
3189 released: view_released.clone(),
3190 });
3191
3192 assert!(!*model_released.lock());
3193 assert!(!*view_released.lock());
3194
3195 cx.update(move || {
3196 drop(model);
3197 });
3198 assert!(*model_released.lock());
3199
3200 drop(cx.remove_window(window_id));
3201 assert!(*view_released.lock());
3202 }
3203
3204 #[crate::test(self)]
3205 fn test_subscribe_and_emit_from_view(cx: &mut MutableAppContext) {
3206 #[derive(Default)]
3207 struct View {
3208 events: Vec<usize>,
3209 }
3210
3211 impl Entity for View {
3212 type Event = usize;
3213 }
3214
3215 impl super::View for View {
3216 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3217 Empty::new().boxed()
3218 }
3219
3220 fn ui_name() -> &'static str {
3221 "View"
3222 }
3223 }
3224
3225 struct Model;
3226
3227 impl Entity for Model {
3228 type Event = usize;
3229 }
3230
3231 let (window_id, handle_1) = cx.add_window(Default::default(), |_| View::default());
3232 let handle_2 = cx.add_view(window_id, |_| View::default());
3233 let handle_2b = handle_2.clone();
3234 let handle_3 = cx.add_model(|_| Model);
3235
3236 handle_1.update(cx, |_, c| {
3237 c.subscribe_to_view(&handle_2, move |me, _, event, c| {
3238 me.events.push(*event);
3239
3240 c.subscribe_to_view(&handle_2b, |me, _, event, _| {
3241 me.events.push(*event * 2);
3242 });
3243 });
3244
3245 c.subscribe_to_model(&handle_3, |me, _, event, _| {
3246 me.events.push(*event);
3247 })
3248 });
3249
3250 handle_2.update(cx, |_, c| c.emit(7));
3251 assert_eq!(handle_1.read(cx).events, vec![7]);
3252
3253 handle_2.update(cx, |_, c| c.emit(5));
3254 assert_eq!(handle_1.read(cx).events, vec![7, 10, 5]);
3255
3256 handle_3.update(cx, |_, c| c.emit(9));
3257 assert_eq!(handle_1.read(cx).events, vec![7, 10, 5, 9]);
3258 }
3259
3260 #[crate::test(self)]
3261 fn test_dropping_subscribers(cx: &mut MutableAppContext) {
3262 struct View;
3263
3264 impl Entity for View {
3265 type Event = ();
3266 }
3267
3268 impl super::View for View {
3269 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3270 Empty::new().boxed()
3271 }
3272
3273 fn ui_name() -> &'static str {
3274 "View"
3275 }
3276 }
3277
3278 struct Model;
3279
3280 impl Entity for Model {
3281 type Event = ();
3282 }
3283
3284 let (window_id, _) = cx.add_window(Default::default(), |_| View);
3285 let observing_view = cx.add_view(window_id, |_| View);
3286 let emitting_view = cx.add_view(window_id, |_| View);
3287 let observing_model = cx.add_model(|_| Model);
3288 let observed_model = cx.add_model(|_| Model);
3289
3290 observing_view.update(cx, |_, cx| {
3291 cx.subscribe_to_view(&emitting_view, |_, _, _, _| {});
3292 cx.subscribe_to_model(&observed_model, |_, _, _, _| {});
3293 });
3294 observing_model.update(cx, |_, cx| {
3295 cx.subscribe(&observed_model, |_, _, _| {});
3296 });
3297
3298 cx.update(|| {
3299 drop(observing_view);
3300 drop(observing_model);
3301 });
3302
3303 emitting_view.update(cx, |_, cx| cx.emit(()));
3304 observed_model.update(cx, |_, cx| cx.emit(()));
3305 }
3306
3307 #[crate::test(self)]
3308 fn test_observe_and_notify_from_view(cx: &mut MutableAppContext) {
3309 #[derive(Default)]
3310 struct View {
3311 events: Vec<usize>,
3312 }
3313
3314 impl Entity for View {
3315 type Event = usize;
3316 }
3317
3318 impl super::View for View {
3319 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3320 Empty::new().boxed()
3321 }
3322
3323 fn ui_name() -> &'static str {
3324 "View"
3325 }
3326 }
3327
3328 #[derive(Default)]
3329 struct Model {
3330 count: usize,
3331 }
3332
3333 impl Entity for Model {
3334 type Event = ();
3335 }
3336
3337 let (_, view) = cx.add_window(Default::default(), |_| View::default());
3338 let model = cx.add_model(|_| Model::default());
3339
3340 view.update(cx, |_, c| {
3341 c.observe_model(&model, |me, observed, c| {
3342 me.events.push(observed.read(c).count)
3343 });
3344 });
3345
3346 model.update(cx, |model, c| {
3347 model.count = 11;
3348 c.notify();
3349 });
3350 assert_eq!(view.read(cx).events, vec![11]);
3351 }
3352
3353 #[crate::test(self)]
3354 fn test_dropping_observers(cx: &mut MutableAppContext) {
3355 struct View;
3356
3357 impl Entity for View {
3358 type Event = ();
3359 }
3360
3361 impl super::View for View {
3362 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3363 Empty::new().boxed()
3364 }
3365
3366 fn ui_name() -> &'static str {
3367 "View"
3368 }
3369 }
3370
3371 struct Model;
3372
3373 impl Entity for Model {
3374 type Event = ();
3375 }
3376
3377 let (window_id, _) = cx.add_window(Default::default(), |_| View);
3378 let observing_view = cx.add_view(window_id, |_| View);
3379 let observing_model = cx.add_model(|_| Model);
3380 let observed_model = cx.add_model(|_| Model);
3381
3382 observing_view.update(cx, |_, cx| {
3383 cx.observe_model(&observed_model, |_, _, _| {});
3384 });
3385 observing_model.update(cx, |_, cx| {
3386 cx.observe(&observed_model, |_, _, _| {});
3387 });
3388
3389 cx.update(|| {
3390 drop(observing_view);
3391 drop(observing_model);
3392 });
3393
3394 observed_model.update(cx, |_, cx| cx.notify());
3395 }
3396
3397 #[crate::test(self)]
3398 fn test_focus(cx: &mut MutableAppContext) {
3399 struct View {
3400 name: String,
3401 events: Arc<Mutex<Vec<String>>>,
3402 }
3403
3404 impl Entity for View {
3405 type Event = ();
3406 }
3407
3408 impl super::View for View {
3409 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3410 Empty::new().boxed()
3411 }
3412
3413 fn ui_name() -> &'static str {
3414 "View"
3415 }
3416
3417 fn on_focus(&mut self, _: &mut ViewContext<Self>) {
3418 self.events.lock().push(format!("{} focused", &self.name));
3419 }
3420
3421 fn on_blur(&mut self, _: &mut ViewContext<Self>) {
3422 self.events.lock().push(format!("{} blurred", &self.name));
3423 }
3424 }
3425
3426 let events: Arc<Mutex<Vec<String>>> = Default::default();
3427 let (window_id, view_1) = cx.add_window(Default::default(), |_| View {
3428 events: events.clone(),
3429 name: "view 1".to_string(),
3430 });
3431 let view_2 = cx.add_view(window_id, |_| View {
3432 events: events.clone(),
3433 name: "view 2".to_string(),
3434 });
3435
3436 view_1.update(cx, |_, cx| cx.focus(&view_2));
3437 view_1.update(cx, |_, cx| cx.focus(&view_1));
3438 view_1.update(cx, |_, cx| cx.focus(&view_2));
3439 view_1.update(cx, |_, _| drop(view_2));
3440
3441 assert_eq!(
3442 *events.lock(),
3443 [
3444 "view 1 focused".to_string(),
3445 "view 1 blurred".to_string(),
3446 "view 2 focused".to_string(),
3447 "view 2 blurred".to_string(),
3448 "view 1 focused".to_string(),
3449 "view 1 blurred".to_string(),
3450 "view 2 focused".to_string(),
3451 "view 1 focused".to_string(),
3452 ],
3453 );
3454 }
3455
3456 #[crate::test(self)]
3457 fn test_dispatch_action(cx: &mut MutableAppContext) {
3458 struct ViewA {
3459 id: usize,
3460 }
3461
3462 impl Entity for ViewA {
3463 type Event = ();
3464 }
3465
3466 impl View for ViewA {
3467 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3468 Empty::new().boxed()
3469 }
3470
3471 fn ui_name() -> &'static str {
3472 "View"
3473 }
3474 }
3475
3476 struct ViewB {
3477 id: usize,
3478 }
3479
3480 impl Entity for ViewB {
3481 type Event = ();
3482 }
3483
3484 impl View for ViewB {
3485 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3486 Empty::new().boxed()
3487 }
3488
3489 fn ui_name() -> &'static str {
3490 "View"
3491 }
3492 }
3493
3494 struct ActionArg {
3495 foo: String,
3496 }
3497
3498 let actions = Rc::new(RefCell::new(Vec::new()));
3499
3500 let actions_clone = actions.clone();
3501 cx.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
3502 actions_clone.borrow_mut().push("global a".to_string());
3503 });
3504
3505 let actions_clone = actions.clone();
3506 cx.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
3507 actions_clone.borrow_mut().push("global b".to_string());
3508 });
3509
3510 let actions_clone = actions.clone();
3511 cx.add_action("action", move |view: &mut ViewA, arg: &ActionArg, cx| {
3512 assert_eq!(arg.foo, "bar");
3513 cx.propagate_action();
3514 actions_clone.borrow_mut().push(format!("{} a", view.id));
3515 });
3516
3517 let actions_clone = actions.clone();
3518 cx.add_action("action", move |view: &mut ViewA, _: &ActionArg, cx| {
3519 if view.id != 1 {
3520 cx.propagate_action();
3521 }
3522 actions_clone.borrow_mut().push(format!("{} b", view.id));
3523 });
3524
3525 let actions_clone = actions.clone();
3526 cx.add_action("action", move |view: &mut ViewB, _: &ActionArg, cx| {
3527 cx.propagate_action();
3528 actions_clone.borrow_mut().push(format!("{} c", view.id));
3529 });
3530
3531 let actions_clone = actions.clone();
3532 cx.add_action("action", move |view: &mut ViewB, _: &ActionArg, cx| {
3533 cx.propagate_action();
3534 actions_clone.borrow_mut().push(format!("{} d", view.id));
3535 });
3536
3537 let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 });
3538 let view_2 = cx.add_view(window_id, |_| ViewB { id: 2 });
3539 let view_3 = cx.add_view(window_id, |_| ViewA { id: 3 });
3540 let view_4 = cx.add_view(window_id, |_| ViewB { id: 4 });
3541
3542 cx.dispatch_action(
3543 window_id,
3544 vec![view_1.id(), view_2.id(), view_3.id(), view_4.id()],
3545 "action",
3546 ActionArg { foo: "bar".into() },
3547 );
3548
3549 assert_eq!(
3550 *actions.borrow(),
3551 vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "1 b"]
3552 );
3553
3554 // Remove view_1, which doesn't propagate the action
3555 actions.borrow_mut().clear();
3556 cx.dispatch_action(
3557 window_id,
3558 vec![view_2.id(), view_3.id(), view_4.id()],
3559 "action",
3560 ActionArg { foo: "bar".into() },
3561 );
3562
3563 assert_eq!(
3564 *actions.borrow(),
3565 vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "global b", "global a"]
3566 );
3567 }
3568
3569 #[crate::test(self)]
3570 fn test_dispatch_keystroke(cx: &mut MutableAppContext) {
3571 use std::cell::Cell;
3572
3573 #[derive(Clone)]
3574 struct ActionArg {
3575 key: String,
3576 }
3577
3578 struct View {
3579 id: usize,
3580 keymap_context: keymap::Context,
3581 }
3582
3583 impl Entity for View {
3584 type Event = ();
3585 }
3586
3587 impl super::View for View {
3588 fn render<'a>(&self, _: &RenderContext<Self>) -> ElementBox {
3589 Empty::new().boxed()
3590 }
3591
3592 fn ui_name() -> &'static str {
3593 "View"
3594 }
3595
3596 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
3597 self.keymap_context.clone()
3598 }
3599 }
3600
3601 impl View {
3602 fn new(id: usize) -> Self {
3603 View {
3604 id,
3605 keymap_context: keymap::Context::default(),
3606 }
3607 }
3608 }
3609
3610 let mut view_1 = View::new(1);
3611 let mut view_2 = View::new(2);
3612 let mut view_3 = View::new(3);
3613 view_1.keymap_context.set.insert("a".into());
3614 view_2.keymap_context.set.insert("b".into());
3615 view_3.keymap_context.set.insert("c".into());
3616
3617 let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1);
3618 let view_2 = cx.add_view(window_id, |_| view_2);
3619 let view_3 = cx.add_view(window_id, |_| view_3);
3620
3621 // This keymap's only binding dispatches an action on view 2 because that view will have
3622 // "a" and "b" in its context, but not "c".
3623 let binding = keymap::Binding::new("a", "action", Some("a && b && !c"))
3624 .with_arg(ActionArg { key: "a".into() });
3625 cx.add_bindings(vec![binding]);
3626
3627 let handled_action = Rc::new(Cell::new(false));
3628 let handled_action_clone = handled_action.clone();
3629 cx.add_action("action", move |view: &mut View, arg: &ActionArg, _| {
3630 handled_action_clone.set(true);
3631 assert_eq!(view.id, 2);
3632 assert_eq!(arg.key, "a");
3633 });
3634
3635 cx.dispatch_keystroke(
3636 window_id,
3637 vec![view_1.id(), view_2.id(), view_3.id()],
3638 &Keystroke::parse("a").unwrap(),
3639 )
3640 .unwrap();
3641
3642 assert!(handled_action.get());
3643 }
3644
3645 #[crate::test(self)]
3646 async fn test_model_condition(mut cx: TestAppContext) {
3647 struct Counter(usize);
3648
3649 impl super::Entity for Counter {
3650 type Event = ();
3651 }
3652
3653 impl Counter {
3654 fn inc(&mut self, cx: &mut ModelContext<Self>) {
3655 self.0 += 1;
3656 cx.notify();
3657 }
3658 }
3659
3660 let model = cx.add_model(|_| Counter(0));
3661
3662 let condition1 = model.condition(&cx, |model, _| model.0 == 2);
3663 let condition2 = model.condition(&cx, |model, _| model.0 == 3);
3664 smol::pin!(condition1, condition2);
3665
3666 model.update(&mut cx, |model, cx| model.inc(cx));
3667 assert_eq!(poll_once(&mut condition1).await, None);
3668 assert_eq!(poll_once(&mut condition2).await, None);
3669
3670 model.update(&mut cx, |model, cx| model.inc(cx));
3671 assert_eq!(poll_once(&mut condition1).await, Some(()));
3672 assert_eq!(poll_once(&mut condition2).await, None);
3673
3674 model.update(&mut cx, |model, cx| model.inc(cx));
3675 assert_eq!(poll_once(&mut condition2).await, Some(()));
3676
3677 model.update(&mut cx, |_, cx| cx.notify());
3678 }
3679
3680 #[crate::test(self)]
3681 #[should_panic]
3682 async fn test_model_condition_timeout(mut cx: TestAppContext) {
3683 struct Model;
3684
3685 impl super::Entity for Model {
3686 type Event = ();
3687 }
3688
3689 let model = cx.add_model(|_| Model);
3690 model.condition(&cx, |_, _| false).await;
3691 }
3692
3693 #[crate::test(self)]
3694 #[should_panic(expected = "model dropped with pending condition")]
3695 async fn test_model_condition_panic_on_drop(mut cx: TestAppContext) {
3696 struct Model;
3697
3698 impl super::Entity for Model {
3699 type Event = ();
3700 }
3701
3702 let model = cx.add_model(|_| Model);
3703 let condition = model.condition(&cx, |_, _| false);
3704 cx.update(|_| drop(model));
3705 condition.await;
3706 }
3707
3708 #[crate::test(self)]
3709 async fn test_view_condition(mut cx: TestAppContext) {
3710 struct Counter(usize);
3711
3712 impl super::Entity for Counter {
3713 type Event = ();
3714 }
3715
3716 impl super::View for Counter {
3717 fn ui_name() -> &'static str {
3718 "test view"
3719 }
3720
3721 fn render(&self, _: &RenderContext<Self>) -> ElementBox {
3722 Empty::new().boxed()
3723 }
3724 }
3725
3726 impl Counter {
3727 fn inc(&mut self, cx: &mut ViewContext<Self>) {
3728 self.0 += 1;
3729 cx.notify();
3730 }
3731 }
3732
3733 let (_, view) = cx.add_window(|_| Counter(0));
3734
3735 let condition1 = view.condition(&cx, |view, _| view.0 == 2);
3736 let condition2 = view.condition(&cx, |view, _| view.0 == 3);
3737 smol::pin!(condition1, condition2);
3738
3739 view.update(&mut cx, |view, cx| view.inc(cx));
3740 assert_eq!(poll_once(&mut condition1).await, None);
3741 assert_eq!(poll_once(&mut condition2).await, None);
3742
3743 view.update(&mut cx, |view, cx| view.inc(cx));
3744 assert_eq!(poll_once(&mut condition1).await, Some(()));
3745 assert_eq!(poll_once(&mut condition2).await, None);
3746
3747 view.update(&mut cx, |view, cx| view.inc(cx));
3748 assert_eq!(poll_once(&mut condition2).await, Some(()));
3749 view.update(&mut cx, |_, cx| cx.notify());
3750 }
3751
3752 #[crate::test(self)]
3753 #[should_panic]
3754 async fn test_view_condition_timeout(mut cx: TestAppContext) {
3755 struct View;
3756
3757 impl super::Entity for View {
3758 type Event = ();
3759 }
3760
3761 impl super::View for View {
3762 fn ui_name() -> &'static str {
3763 "test view"
3764 }
3765
3766 fn render(&self, _: &RenderContext<Self>) -> ElementBox {
3767 Empty::new().boxed()
3768 }
3769 }
3770
3771 let (_, view) = cx.add_window(|_| View);
3772 view.condition(&cx, |_, _| false).await;
3773 }
3774
3775 #[crate::test(self)]
3776 #[should_panic(expected = "view dropped with pending condition")]
3777 async fn test_view_condition_panic_on_drop(mut cx: TestAppContext) {
3778 struct View;
3779
3780 impl super::Entity for View {
3781 type Event = ();
3782 }
3783
3784 impl super::View for View {
3785 fn ui_name() -> &'static str {
3786 "test view"
3787 }
3788
3789 fn render(&self, _: &RenderContext<Self>) -> ElementBox {
3790 Empty::new().boxed()
3791 }
3792 }
3793
3794 let window_id = cx.add_window(|_| View).0;
3795 let view = cx.add_view(window_id, |_| View);
3796
3797 let condition = view.condition(&cx, |_, _| false);
3798 cx.update(|_| drop(view));
3799 condition.await;
3800 }
3801}