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