app.rs

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