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