app.rs

   1use crate::{
   2    elements::Element,
   3    executor::{self},
   4    keymap::{self, Keystroke},
   5    platform::{self, App as _},
   6    util::post_inc,
   7};
   8use anyhow::{anyhow, Result};
   9use keymap::MatchResult;
  10use parking_lot::Mutex;
  11use smol::{channel, prelude::*};
  12use std::{
  13    any::{type_name, Any, TypeId},
  14    borrow,
  15    cell::RefCell,
  16    collections::{HashMap, HashSet, VecDeque},
  17    fmt::{self, Debug},
  18    hash::{Hash, Hasher},
  19    marker::PhantomData,
  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    pub fn test<T, F: Future<Output = T>>(f: impl FnOnce(App) -> F) -> T {
  70        let platform = platform::current::app(); // TODO: Make a test platform app
  71        let foreground = Rc::new(executor::Foreground::test());
  72        let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
  73            foreground.clone(),
  74            Arc::new(platform),
  75        ))));
  76        app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
  77        smol::block_on(foreground.run(f(app)))
  78    }
  79
  80    pub fn new() -> Result<Self> {
  81        let platform = Arc::new(platform::current::app());
  82        let foreground = Rc::new(executor::Foreground::platform(platform.dispatcher())?);
  83        let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
  84            foreground, platform,
  85        ))));
  86        app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
  87        Ok(app)
  88    }
  89
  90    pub fn on_window_invalidated<F: 'static + FnMut(WindowInvalidation, &mut MutableAppContext)>(
  91        &self,
  92        window_id: usize,
  93        callback: F,
  94    ) {
  95        self.0
  96            .borrow_mut()
  97            .on_window_invalidated(window_id, callback);
  98    }
  99
 100    pub fn add_action<S, V, T, F>(&self, name: S, handler: F)
 101    where
 102        S: Into<String>,
 103        V: View,
 104        T: Any,
 105        F: 'static + FnMut(&mut V, &T, &mut ViewContext<V>),
 106    {
 107        self.0.borrow_mut().add_action(name, handler);
 108    }
 109
 110    pub fn add_global_action<S, T, F>(&self, name: S, handler: F)
 111    where
 112        S: Into<String>,
 113        T: 'static + Any,
 114        F: 'static + FnMut(&T, &mut MutableAppContext),
 115    {
 116        self.0.borrow_mut().add_global_action(name, handler);
 117    }
 118
 119    pub fn dispatch_action<T: 'static + Any>(
 120        &self,
 121        window_id: usize,
 122        responder_chain: Vec<usize>,
 123        name: &str,
 124        arg: T,
 125    ) {
 126        self.0.borrow_mut().dispatch_action(
 127            window_id,
 128            &responder_chain,
 129            name,
 130            Box::new(arg).as_ref(),
 131        );
 132    }
 133
 134    pub fn dispatch_global_action<T: 'static + Any>(&self, name: &str, arg: T) {
 135        self.0
 136            .borrow_mut()
 137            .dispatch_global_action(name, Box::new(arg).as_ref());
 138    }
 139
 140    pub fn add_bindings<T: IntoIterator<Item = keymap::Binding>>(&self, bindings: T) {
 141        self.0.borrow_mut().add_bindings(bindings);
 142    }
 143
 144    pub fn dispatch_keystroke(
 145        &self,
 146        window_id: usize,
 147        responder_chain: Vec<usize>,
 148        keystroke: &Keystroke,
 149    ) -> Result<bool> {
 150        let mut state = self.0.borrow_mut();
 151        state.dispatch_keystroke(window_id, responder_chain, keystroke)
 152    }
 153
 154    pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
 155    where
 156        T: Entity,
 157        F: FnOnce(&mut ModelContext<T>) -> T,
 158    {
 159        let mut state = self.0.borrow_mut();
 160        state.pending_flushes += 1;
 161        let handle = state.add_model(build_model);
 162        state.flush_effects();
 163        handle
 164    }
 165
 166    fn read_model<T, F, S>(&self, handle: &ModelHandle<T>, read: F) -> S
 167    where
 168        T: Entity,
 169        F: FnOnce(&T, &AppContext) -> S,
 170    {
 171        let state = self.0.borrow();
 172        read(state.model(handle), &state.ctx)
 173    }
 174
 175    pub fn add_window<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>)
 176    where
 177        T: View,
 178        F: FnOnce(&mut ViewContext<T>) -> T,
 179    {
 180        self.0.borrow_mut().add_window(build_root_view)
 181    }
 182
 183    pub fn window_ids(&self) -> Vec<usize> {
 184        self.0.borrow().window_ids().collect()
 185    }
 186
 187    pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
 188        self.0.borrow().root_view(window_id)
 189    }
 190
 191    pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
 192    where
 193        T: View,
 194        F: FnOnce(&mut ViewContext<T>) -> T,
 195    {
 196        let mut state = self.0.borrow_mut();
 197        state.pending_flushes += 1;
 198        let handle = state.add_view(window_id, build_view);
 199        state.flush_effects();
 200        handle
 201    }
 202
 203    pub fn add_option_view<T, F>(
 204        &mut self,
 205        window_id: usize,
 206        build_view: F,
 207    ) -> Option<ViewHandle<T>>
 208    where
 209        T: View,
 210        F: FnOnce(&mut ViewContext<T>) -> Option<T>,
 211    {
 212        let mut state = self.0.borrow_mut();
 213        state.pending_flushes += 1;
 214        let handle = state.add_option_view(window_id, build_view);
 215        state.flush_effects();
 216        handle
 217    }
 218
 219    pub fn read<T, F: FnOnce(&AppContext) -> T>(&mut self, callback: F) -> T {
 220        callback(self.0.borrow().ctx())
 221    }
 222
 223    pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
 224        let mut state = self.0.borrow_mut();
 225        state.pending_flushes += 1;
 226        let result = callback(&mut *state);
 227        state.flush_effects();
 228        result
 229    }
 230
 231    fn read_view<T, F, S>(&self, handle: &ViewHandle<T>, read: F) -> S
 232    where
 233        T: View,
 234        F: FnOnce(&T, &AppContext) -> S,
 235    {
 236        let state = self.0.borrow();
 237        read(state.view(handle), state.ctx())
 238    }
 239
 240    pub fn finish_pending_tasks(&self) -> impl Future<Output = ()> {
 241        self.0.borrow().finish_pending_tasks()
 242    }
 243}
 244
 245impl UpdateModel for App {
 246    fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
 247    where
 248        T: Entity,
 249        F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
 250    {
 251        let mut state = self.0.borrow_mut();
 252        state.pending_flushes += 1;
 253        let result = state.update_model(handle, update);
 254        state.flush_effects();
 255        result
 256    }
 257}
 258
 259impl UpdateView for App {
 260    fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
 261    where
 262        T: View,
 263        F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
 264    {
 265        let mut state = self.0.borrow_mut();
 266        state.pending_flushes += 1;
 267        let result = state.update_view(handle, update);
 268        state.flush_effects();
 269        result
 270    }
 271}
 272
 273type ActionCallback =
 274    dyn FnMut(&mut dyn AnyView, &dyn Any, &mut MutableAppContext, usize, usize) -> bool;
 275
 276type GlobalActionCallback = dyn FnMut(&dyn Any, &mut MutableAppContext);
 277
 278pub struct MutableAppContext {
 279    platform: Arc<dyn platform::App>,
 280    ctx: AppContext,
 281    actions: HashMap<TypeId, HashMap<String, Vec<Box<ActionCallback>>>>,
 282    global_actions: HashMap<String, Vec<Box<GlobalActionCallback>>>,
 283    keystroke_matcher: keymap::Matcher,
 284    next_entity_id: usize,
 285    next_window_id: usize,
 286    next_task_id: usize,
 287    weak_self: Option<rc::Weak<RefCell<Self>>>,
 288    subscriptions: HashMap<usize, Vec<Subscription>>,
 289    observations: HashMap<usize, Vec<Observation>>,
 290    window_invalidations: HashMap<usize, WindowInvalidation>,
 291    invalidation_callbacks:
 292        HashMap<usize, Box<dyn FnMut(WindowInvalidation, &mut MutableAppContext)>>,
 293    foreground: Rc<executor::Foreground>,
 294    background: Arc<executor::Background>,
 295    task_callbacks: HashMap<usize, TaskCallback>,
 296    task_done: (channel::Sender<usize>, channel::Receiver<usize>),
 297    pending_effects: VecDeque<Effect>,
 298    pending_flushes: usize,
 299    flushing_effects: bool,
 300}
 301
 302impl MutableAppContext {
 303    pub fn new(foreground: Rc<executor::Foreground>, platform: Arc<dyn platform::App>) -> Self {
 304        Self {
 305            platform,
 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    pub fn finish_pending_tasks(&self) -> impl Future<Output = ()> {
1042        let mut pending_tasks = self.task_callbacks.keys().cloned().collect::<HashSet<_>>();
1043        let task_done = self.task_done.1.clone();
1044
1045        async move {
1046            while !pending_tasks.is_empty() {
1047                if let Ok(task_id) = task_done.recv().await {
1048                    pending_tasks.remove(&task_id);
1049                } else {
1050                    break;
1051                }
1052            }
1053        }
1054    }
1055}
1056
1057impl ModelAsRef for MutableAppContext {
1058    fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1059        if let Some(model) = self.ctx.models.get(&handle.model_id) {
1060            model
1061                .as_any()
1062                .downcast_ref()
1063                .expect("Downcast is type safe")
1064        } else {
1065            panic!("Circular model reference");
1066        }
1067    }
1068}
1069
1070impl UpdateModel for MutableAppContext {
1071    fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1072    where
1073        T: Entity,
1074        F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1075    {
1076        if let Some(mut model) = self.ctx.models.remove(&handle.model_id) {
1077            self.pending_flushes += 1;
1078            let mut ctx = ModelContext::new(self, handle.model_id);
1079            let result = update(
1080                model
1081                    .as_any_mut()
1082                    .downcast_mut()
1083                    .expect("Downcast is type safe"),
1084                &mut ctx,
1085            );
1086            self.ctx.models.insert(handle.model_id, model);
1087            self.flush_effects();
1088            result
1089        } else {
1090            panic!("Circular model update");
1091        }
1092    }
1093}
1094
1095impl ViewAsRef for MutableAppContext {
1096    fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1097        if let Some(window) = self.ctx.windows.get(&handle.window_id) {
1098            if let Some(view) = window.views.get(&handle.view_id) {
1099                view.as_any().downcast_ref().expect("Downcast is type safe")
1100            } else {
1101                panic!("Circular view reference");
1102            }
1103        } else {
1104            panic!("Window does not exist");
1105        }
1106    }
1107}
1108
1109impl UpdateView for MutableAppContext {
1110    fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
1111    where
1112        T: View,
1113        F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
1114    {
1115        self.pending_flushes += 1;
1116        let mut view = if let Some(window) = self.ctx.windows.get_mut(&handle.window_id) {
1117            if let Some(view) = window.views.remove(&handle.view_id) {
1118                view
1119            } else {
1120                panic!("Circular view update");
1121            }
1122        } else {
1123            panic!("Window does not exist");
1124        };
1125
1126        let mut ctx = ViewContext::new(self, handle.window_id, handle.view_id);
1127        let result = update(
1128            view.as_any_mut()
1129                .downcast_mut()
1130                .expect("Downcast is type safe"),
1131            &mut ctx,
1132        );
1133        self.ctx
1134            .windows
1135            .get_mut(&handle.window_id)
1136            .unwrap()
1137            .views
1138            .insert(handle.view_id, view);
1139        self.flush_effects();
1140        result
1141    }
1142}
1143
1144pub struct AppContext {
1145    models: HashMap<usize, Box<dyn AnyModel>>,
1146    windows: HashMap<usize, Window>,
1147    ref_counts: Arc<Mutex<RefCounts>>,
1148}
1149
1150impl AppContext {
1151    pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
1152        self.windows
1153            .get(&window_id)
1154            .and_then(|window| window.root_view.as_ref().map(|v| v.id()))
1155    }
1156
1157    pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
1158        self.windows
1159            .get(&window_id)
1160            .and_then(|window| window.focused_view)
1161    }
1162
1163    pub fn render_view(&self, window_id: usize, view_id: usize) -> Result<Box<dyn Element>> {
1164        self.windows
1165            .get(&window_id)
1166            .and_then(|w| w.views.get(&view_id))
1167            .map(|v| v.render(self))
1168            .ok_or(anyhow!("view not found"))
1169    }
1170
1171    pub fn render_views(&self, window_id: usize) -> Result<HashMap<usize, Box<dyn Element>>> {
1172        self.windows
1173            .get(&window_id)
1174            .map(|w| {
1175                w.views
1176                    .iter()
1177                    .map(|(id, view)| (*id, view.render(self)))
1178                    .collect::<HashMap<_, Box<dyn Element>>>()
1179            })
1180            .ok_or(anyhow!("window not found"))
1181    }
1182}
1183
1184impl ModelAsRef for AppContext {
1185    fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1186        if let Some(model) = self.models.get(&handle.model_id) {
1187            model
1188                .as_any()
1189                .downcast_ref()
1190                .expect("downcast should be type safe")
1191        } else {
1192            panic!("circular model reference");
1193        }
1194    }
1195}
1196
1197impl ViewAsRef for AppContext {
1198    fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1199        if let Some(window) = self.windows.get(&handle.window_id) {
1200            if let Some(view) = window.views.get(&handle.view_id) {
1201                view.as_any()
1202                    .downcast_ref()
1203                    .expect("downcast should be type safe")
1204            } else {
1205                panic!("circular view reference");
1206            }
1207        } else {
1208            panic!("window does not exist");
1209        }
1210    }
1211}
1212
1213#[derive(Default)]
1214struct Window {
1215    views: HashMap<usize, Box<dyn AnyView>>,
1216    root_view: Option<AnyViewHandle>,
1217    focused_view: Option<usize>,
1218}
1219
1220#[derive(Default, Clone)]
1221pub struct WindowInvalidation {
1222    pub updated: HashSet<usize>,
1223    pub removed: Vec<usize>,
1224}
1225
1226pub enum Effect {
1227    Event {
1228        entity_id: usize,
1229        payload: Box<dyn Any>,
1230    },
1231    ModelNotification {
1232        model_id: usize,
1233    },
1234    ViewNotification {
1235        window_id: usize,
1236        view_id: usize,
1237    },
1238    Focus {
1239        window_id: usize,
1240        view_id: usize,
1241    },
1242}
1243
1244pub trait AnyModel: Send + Sync {
1245    fn as_any(&self) -> &dyn Any;
1246    fn as_any_mut(&mut self) -> &mut dyn Any;
1247}
1248
1249impl<T> AnyModel for T
1250where
1251    T: Entity,
1252{
1253    fn as_any(&self) -> &dyn Any {
1254        self
1255    }
1256
1257    fn as_any_mut(&mut self) -> &mut dyn Any {
1258        self
1259    }
1260}
1261
1262pub trait AnyView: Send + Sync {
1263    fn as_any(&self) -> &dyn Any;
1264    fn as_any_mut(&mut self) -> &mut dyn Any;
1265    fn ui_name(&self) -> &'static str;
1266    fn render<'a>(&self, app: &AppContext) -> Box<dyn Element>;
1267    fn on_focus(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize);
1268    fn on_blur(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize);
1269    fn keymap_context(&self, app: &AppContext) -> keymap::Context;
1270}
1271
1272impl<T> AnyView for T
1273where
1274    T: View,
1275{
1276    fn as_any(&self) -> &dyn Any {
1277        self
1278    }
1279
1280    fn as_any_mut(&mut self) -> &mut dyn Any {
1281        self
1282    }
1283
1284    fn ui_name(&self) -> &'static str {
1285        T::ui_name()
1286    }
1287
1288    fn render<'a>(&self, app: &AppContext) -> Box<dyn Element> {
1289        View::render(self, app)
1290    }
1291
1292    fn on_focus(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize) {
1293        let mut ctx = ViewContext::new(app, window_id, view_id);
1294        View::on_focus(self, &mut ctx);
1295    }
1296
1297    fn on_blur(&mut self, app: &mut MutableAppContext, window_id: usize, view_id: usize) {
1298        let mut ctx = ViewContext::new(app, window_id, view_id);
1299        View::on_blur(self, &mut ctx);
1300    }
1301
1302    fn keymap_context(&self, app: &AppContext) -> keymap::Context {
1303        View::keymap_context(self, app)
1304    }
1305}
1306
1307pub struct ModelContext<'a, T: ?Sized> {
1308    app: &'a mut MutableAppContext,
1309    model_id: usize,
1310    model_type: PhantomData<T>,
1311    halt_stream: bool,
1312}
1313
1314impl<'a, T: Entity> ModelContext<'a, T> {
1315    fn new(app: &'a mut MutableAppContext, model_id: usize) -> Self {
1316        Self {
1317            app,
1318            model_id,
1319            model_type: PhantomData,
1320            halt_stream: false,
1321        }
1322    }
1323
1324    pub fn app(&self) -> &AppContext {
1325        &self.app.ctx
1326    }
1327
1328    pub fn app_mut(&mut self) -> &mut MutableAppContext {
1329        self.app
1330    }
1331
1332    pub fn background_executor(&self) -> Arc<executor::Background> {
1333        self.app.background.clone()
1334    }
1335
1336    pub fn halt_stream(&mut self) {
1337        self.halt_stream = true;
1338    }
1339
1340    pub fn model_id(&self) -> usize {
1341        self.model_id
1342    }
1343
1344    pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
1345    where
1346        S: Entity,
1347        F: FnOnce(&mut ModelContext<S>) -> S,
1348    {
1349        self.app.add_model(build_model)
1350    }
1351
1352    pub fn subscribe<S: Entity, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1353    where
1354        S::Event: 'static,
1355        F: 'static + FnMut(&mut T, &S::Event, &mut ModelContext<T>),
1356    {
1357        self.app
1358            .subscriptions
1359            .entry(handle.model_id)
1360            .or_default()
1361            .push(Subscription::FromModel {
1362                model_id: self.model_id,
1363                callback: Box::new(move |model, payload, app, model_id| {
1364                    let model = model.downcast_mut().expect("downcast is type safe");
1365                    let payload = payload.downcast_ref().expect("downcast is type safe");
1366                    let mut ctx = ModelContext::new(app, model_id);
1367                    callback(model, payload, &mut ctx);
1368                }),
1369            });
1370    }
1371
1372    pub fn emit(&mut self, payload: T::Event) {
1373        self.app.pending_effects.push_back(Effect::Event {
1374            entity_id: self.model_id,
1375            payload: Box::new(payload),
1376        });
1377    }
1378
1379    pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1380    where
1381        S: Entity,
1382        F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ModelContext<T>),
1383    {
1384        self.app
1385            .observations
1386            .entry(handle.model_id)
1387            .or_default()
1388            .push(Observation::FromModel {
1389                model_id: self.model_id,
1390                callback: Box::new(move |model, observed_id, app, model_id| {
1391                    let model = model.downcast_mut().expect("downcast is type safe");
1392                    let observed = ModelHandle::new(observed_id, &app.ctx.ref_counts);
1393                    let mut ctx = ModelContext::new(app, model_id);
1394                    callback(model, observed, &mut ctx);
1395                }),
1396            });
1397    }
1398
1399    pub fn notify(&mut self) {
1400        self.app
1401            .pending_effects
1402            .push_back(Effect::ModelNotification {
1403                model_id: self.model_id,
1404            });
1405    }
1406
1407    pub fn spawn_local<S, F, U>(&mut self, future: S, callback: F) -> impl Future<Output = U>
1408    where
1409        S: 'static + Future,
1410        F: 'static + FnOnce(&mut T, S::Output, &mut ModelContext<T>) -> U,
1411        U: 'static,
1412    {
1413        let (tx, rx) = channel::bounded(1);
1414
1415        let task_id = self.app.spawn_local(future);
1416
1417        self.app.task_callbacks.insert(
1418            task_id,
1419            TaskCallback::OnModelFromFuture {
1420                model_id: self.model_id,
1421                callback: Box::new(move |model, output, app, model_id, executor| {
1422                    let model = model.downcast_mut().unwrap();
1423                    let output = *output.downcast().unwrap();
1424                    let result = callback(model, output, &mut ModelContext::new(app, model_id));
1425                    executor
1426                        .spawn(async move { tx.send(result).await })
1427                        .detach();
1428                }),
1429            },
1430        );
1431
1432        async move { rx.recv().await.unwrap() }
1433    }
1434
1435    pub fn spawn<S, F, U>(&mut self, future: S, callback: F) -> impl Future<Output = U>
1436    where
1437        S: 'static + Future + Send,
1438        S::Output: Send,
1439        F: 'static + FnOnce(&mut T, S::Output, &mut ModelContext<T>) -> U,
1440        U: 'static,
1441    {
1442        let (tx, rx) = channel::bounded(1);
1443
1444        self.app
1445            .background
1446            .spawn(async move {
1447                if let Err(e) = tx.send(future.await).await {
1448                    log::error!("error sending background task result to main thread: {}", e);
1449                }
1450            })
1451            .detach();
1452
1453        self.spawn_local(async move { rx.recv().await.unwrap() }, callback)
1454    }
1455
1456    pub fn spawn_stream_local<S, F>(
1457        &mut self,
1458        stream: S,
1459        mut callback: F,
1460    ) -> impl Future<Output = ()>
1461    where
1462        S: 'static + Stream + Unpin,
1463        F: 'static + FnMut(&mut T, Option<S::Item>, &mut ModelContext<T>),
1464    {
1465        let (tx, rx) = channel::bounded(1);
1466
1467        let task_id = self.app.spawn_stream_local(stream, tx);
1468        self.app.task_callbacks.insert(
1469            task_id,
1470            TaskCallback::OnModelFromStream {
1471                model_id: self.model_id,
1472                callback: Box::new(move |model, output, app, model_id| {
1473                    let model = model.downcast_mut().unwrap();
1474                    let output = *output.downcast().unwrap();
1475                    let mut ctx = ModelContext::new(app, model_id);
1476                    callback(model, output, &mut ctx);
1477                    ctx.halt_stream
1478                }),
1479            },
1480        );
1481
1482        async move { rx.recv().await.unwrap() }
1483    }
1484}
1485
1486impl<M> ModelAsRef for ModelContext<'_, M> {
1487    fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1488        self.app.model(handle)
1489    }
1490}
1491
1492impl<M> UpdateModel for ModelContext<'_, M> {
1493    fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1494    where
1495        T: Entity,
1496        F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1497    {
1498        self.app.update_model(handle, update)
1499    }
1500}
1501
1502pub struct ViewContext<'a, T: ?Sized> {
1503    app: &'a mut MutableAppContext,
1504    window_id: usize,
1505    view_id: usize,
1506    view_type: PhantomData<T>,
1507    halt_action_dispatch: bool,
1508    halt_stream: bool,
1509}
1510
1511impl<'a, T: View> ViewContext<'a, T> {
1512    fn new(app: &'a mut MutableAppContext, window_id: usize, view_id: usize) -> Self {
1513        Self {
1514            app,
1515            window_id,
1516            view_id,
1517            view_type: PhantomData,
1518            halt_action_dispatch: true,
1519            halt_stream: false,
1520        }
1521    }
1522
1523    pub fn handle(&self) -> WeakViewHandle<T> {
1524        WeakViewHandle::new(self.window_id, self.view_id)
1525    }
1526
1527    pub fn window_id(&self) -> usize {
1528        self.window_id
1529    }
1530
1531    pub fn app(&self) -> &AppContext {
1532        &self.app.ctx
1533    }
1534
1535    pub fn app_mut(&mut self) -> &mut MutableAppContext {
1536        self.app
1537    }
1538
1539    pub fn focus<S>(&mut self, handle: S)
1540    where
1541        S: Into<AnyViewHandle>,
1542    {
1543        let handle = handle.into();
1544        self.app.pending_effects.push_back(Effect::Focus {
1545            window_id: handle.window_id,
1546            view_id: handle.view_id,
1547        });
1548    }
1549
1550    pub fn focus_self(&mut self) {
1551        self.app.pending_effects.push_back(Effect::Focus {
1552            window_id: self.window_id,
1553            view_id: self.view_id,
1554        });
1555    }
1556
1557    pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
1558    where
1559        S: Entity,
1560        F: FnOnce(&mut ModelContext<S>) -> S,
1561    {
1562        self.app.add_model(build_model)
1563    }
1564
1565    pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
1566    where
1567        S: View,
1568        F: FnOnce(&mut ViewContext<S>) -> S,
1569    {
1570        self.app.add_view(self.window_id, build_view)
1571    }
1572
1573    pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
1574    where
1575        S: View,
1576        F: FnOnce(&mut ViewContext<S>) -> Option<S>,
1577    {
1578        self.app.add_option_view(self.window_id, build_view)
1579    }
1580
1581    pub fn subscribe_to_model<E, F>(&mut self, handle: &ModelHandle<E>, mut callback: F)
1582    where
1583        E: Entity,
1584        E::Event: 'static,
1585        F: 'static + FnMut(&mut T, ModelHandle<E>, &E::Event, &mut ViewContext<T>),
1586    {
1587        let emitter_handle = handle.downgrade();
1588        self.app
1589            .subscriptions
1590            .entry(handle.id())
1591            .or_default()
1592            .push(Subscription::FromView {
1593                window_id: self.window_id,
1594                view_id: self.view_id,
1595                callback: Box::new(move |view, payload, app, window_id, view_id| {
1596                    if let Some(emitter_handle) = emitter_handle.upgrade(app.ctx()) {
1597                        let model = view.downcast_mut().expect("downcast is type safe");
1598                        let payload = payload.downcast_ref().expect("downcast is type safe");
1599                        let mut ctx = ViewContext::new(app, window_id, view_id);
1600                        callback(model, emitter_handle, payload, &mut ctx);
1601                    }
1602                }),
1603            });
1604    }
1605
1606    pub fn subscribe_to_view<V, F>(&mut self, handle: &ViewHandle<V>, mut callback: F)
1607    where
1608        V: View,
1609        V::Event: 'static,
1610        F: 'static + FnMut(&mut T, ViewHandle<V>, &V::Event, &mut ViewContext<T>),
1611    {
1612        let emitter_handle = handle.downgrade();
1613
1614        self.app
1615            .subscriptions
1616            .entry(handle.id())
1617            .or_default()
1618            .push(Subscription::FromView {
1619                window_id: self.window_id,
1620                view_id: self.view_id,
1621                callback: Box::new(move |view, payload, app, window_id, view_id| {
1622                    if let Some(emitter_handle) = emitter_handle.upgrade(app.ctx()) {
1623                        let model = view.downcast_mut().expect("downcast is type safe");
1624                        let payload = payload.downcast_ref().expect("downcast is type safe");
1625                        let mut ctx = ViewContext::new(app, window_id, view_id);
1626                        callback(model, emitter_handle, payload, &mut ctx);
1627                    }
1628                }),
1629            });
1630    }
1631
1632    pub fn emit(&mut self, payload: T::Event) {
1633        self.app.pending_effects.push_back(Effect::Event {
1634            entity_id: self.view_id,
1635            payload: Box::new(payload),
1636        });
1637    }
1638
1639    pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F)
1640    where
1641        S: Entity,
1642        F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ViewContext<T>),
1643    {
1644        self.app
1645            .observations
1646            .entry(handle.id())
1647            .or_default()
1648            .push(Observation::FromView {
1649                window_id: self.window_id,
1650                view_id: self.view_id,
1651                callback: Box::new(move |view, observed_id, app, window_id, view_id| {
1652                    let view = view.downcast_mut().expect("downcast is type safe");
1653                    let observed = ModelHandle::new(observed_id, &app.ctx.ref_counts);
1654                    let mut ctx = ViewContext::new(app, window_id, view_id);
1655                    callback(view, observed, &mut ctx);
1656                }),
1657            });
1658    }
1659
1660    pub fn notify(&mut self) {
1661        self.app
1662            .pending_effects
1663            .push_back(Effect::ViewNotification {
1664                window_id: self.window_id,
1665                view_id: self.view_id,
1666            });
1667    }
1668
1669    pub fn propagate_action(&mut self) {
1670        self.halt_action_dispatch = false;
1671    }
1672
1673    pub fn halt_stream(&mut self) {
1674        self.halt_stream = true;
1675    }
1676
1677    pub fn spawn_local<S, F, U>(&mut self, future: S, callback: F) -> impl Future<Output = U>
1678    where
1679        S: 'static + Future,
1680        F: 'static + FnOnce(&mut T, S::Output, &mut ViewContext<T>) -> U,
1681        U: 'static,
1682    {
1683        let (tx, rx) = channel::bounded(1);
1684
1685        let task_id = self.app.spawn_local(future);
1686
1687        self.app.task_callbacks.insert(
1688            task_id,
1689            TaskCallback::OnViewFromFuture {
1690                window_id: self.window_id,
1691                view_id: self.view_id,
1692                callback: Box::new(move |view, output, app, window_id, view_id, executor| {
1693                    let view = view.as_any_mut().downcast_mut().unwrap();
1694                    let output = *output.downcast().unwrap();
1695                    let result =
1696                        callback(view, output, &mut ViewContext::new(app, window_id, view_id));
1697                    executor
1698                        .spawn(async move { tx.send(result).await })
1699                        .detach();
1700                }),
1701            },
1702        );
1703
1704        async move { rx.recv().await.unwrap() }
1705    }
1706
1707    pub fn spawn<S, F, U>(&mut self, future: S, callback: F) -> impl Future<Output = U>
1708    where
1709        S: 'static + Future + Send,
1710        S::Output: Send,
1711        F: 'static + FnOnce(&mut T, S::Output, &mut ViewContext<T>) -> U,
1712        U: 'static,
1713    {
1714        let (tx, rx) = channel::bounded(1);
1715
1716        self.app
1717            .background
1718            .spawn(async move {
1719                if let Err(_) = tx.send(future.await).await {
1720                    log::error!("Error sending background task result to main thread",);
1721                }
1722            })
1723            .detach();
1724
1725        self.spawn_local(async move { rx.recv().await.unwrap() }, callback)
1726    }
1727
1728    pub fn spawn_stream_local<S, F>(
1729        &mut self,
1730        stream: S,
1731        mut callback: F,
1732    ) -> impl Future<Output = ()>
1733    where
1734        S: 'static + Stream + Unpin,
1735        F: 'static + FnMut(&mut T, Option<S::Item>, &mut ViewContext<T>),
1736    {
1737        let (tx, rx) = channel::bounded(1);
1738
1739        let task_id = self.app.spawn_stream_local(stream, tx);
1740        self.app.task_callbacks.insert(
1741            task_id,
1742            TaskCallback::OnViewFromStream {
1743                window_id: self.window_id,
1744                view_id: self.view_id,
1745                callback: Box::new(move |view, output, app, window_id, view_id| {
1746                    let view = view.as_any_mut().downcast_mut().unwrap();
1747                    let output = *output.downcast().unwrap();
1748                    let mut ctx = ViewContext::new(app, window_id, view_id);
1749                    callback(view, output, &mut ctx);
1750                    ctx.halt_stream
1751                }),
1752            },
1753        );
1754
1755        async move { rx.recv().await.unwrap() }
1756    }
1757}
1758
1759impl<V> ModelAsRef for ViewContext<'_, V> {
1760    fn model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
1761        self.app.model(handle)
1762    }
1763}
1764
1765impl<V: View> UpdateModel for ViewContext<'_, V> {
1766    fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
1767    where
1768        T: Entity,
1769        F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1770    {
1771        self.app.update_model(handle, update)
1772    }
1773}
1774
1775impl<V: View> ViewAsRef for ViewContext<'_, V> {
1776    fn view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
1777        self.app.view(handle)
1778    }
1779}
1780
1781impl<V: View> UpdateView for ViewContext<'_, V> {
1782    fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
1783    where
1784        T: View,
1785        F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
1786    {
1787        self.app.update_view(handle, update)
1788    }
1789}
1790
1791pub trait Handle<T> {
1792    fn id(&self) -> usize;
1793    fn location(&self) -> EntityLocation;
1794}
1795
1796#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
1797pub enum EntityLocation {
1798    Model(usize),
1799    View(usize, usize),
1800}
1801
1802pub struct ModelHandle<T> {
1803    model_id: usize,
1804    model_type: PhantomData<T>,
1805    ref_counts: Weak<Mutex<RefCounts>>,
1806}
1807
1808impl<T: Entity> ModelHandle<T> {
1809    fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
1810        ref_counts.lock().inc(model_id);
1811        Self {
1812            model_id,
1813            model_type: PhantomData,
1814            ref_counts: Arc::downgrade(ref_counts),
1815        }
1816    }
1817
1818    fn downgrade(&self) -> WeakModelHandle<T> {
1819        WeakModelHandle::new(self.model_id)
1820    }
1821
1822    pub fn id(&self) -> usize {
1823        self.model_id
1824    }
1825
1826    pub fn as_ref<'a, A: ModelAsRef>(&self, app: &'a A) -> &'a T {
1827        app.model(self)
1828    }
1829
1830    pub fn read<'a, S, F>(&self, app: &'a App, read: F) -> S
1831    where
1832        F: FnOnce(&T, &AppContext) -> S,
1833    {
1834        app.read_model(self, read)
1835    }
1836
1837    pub fn update<A, F, S>(&self, app: &mut A, update: F) -> S
1838    where
1839        A: UpdateModel,
1840        F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
1841    {
1842        app.update_model(self, update)
1843    }
1844}
1845
1846impl<T> Clone for ModelHandle<T> {
1847    fn clone(&self) -> Self {
1848        if let Some(ref_counts) = self.ref_counts.upgrade() {
1849            ref_counts.lock().inc(self.model_id);
1850        }
1851
1852        Self {
1853            model_id: self.model_id,
1854            model_type: PhantomData,
1855            ref_counts: self.ref_counts.clone(),
1856        }
1857    }
1858}
1859
1860impl<T> PartialEq for ModelHandle<T> {
1861    fn eq(&self, other: &Self) -> bool {
1862        self.model_id == other.model_id
1863    }
1864}
1865
1866impl<T> Eq for ModelHandle<T> {}
1867
1868impl<T> Hash for ModelHandle<T> {
1869    fn hash<H: Hasher>(&self, state: &mut H) {
1870        self.model_id.hash(state);
1871    }
1872}
1873
1874impl<T> borrow::Borrow<usize> for ModelHandle<T> {
1875    fn borrow(&self) -> &usize {
1876        &self.model_id
1877    }
1878}
1879
1880impl<T> Debug for ModelHandle<T> {
1881    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1882        f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
1883            .field(&self.model_id)
1884            .finish()
1885    }
1886}
1887
1888unsafe impl<T> Send for ModelHandle<T> {}
1889unsafe impl<T> Sync for ModelHandle<T> {}
1890
1891impl<T> Drop for ModelHandle<T> {
1892    fn drop(&mut self) {
1893        if let Some(ref_counts) = self.ref_counts.upgrade() {
1894            ref_counts.lock().dec_model(self.model_id);
1895        }
1896    }
1897}
1898
1899impl<T> Handle<T> for ModelHandle<T> {
1900    fn id(&self) -> usize {
1901        self.model_id
1902    }
1903
1904    fn location(&self) -> EntityLocation {
1905        EntityLocation::Model(self.model_id)
1906    }
1907}
1908
1909pub struct WeakModelHandle<T> {
1910    model_id: usize,
1911    model_type: PhantomData<T>,
1912}
1913
1914impl<T: Entity> WeakModelHandle<T> {
1915    fn new(model_id: usize) -> Self {
1916        Self {
1917            model_id,
1918            model_type: PhantomData,
1919        }
1920    }
1921
1922    pub fn upgrade(&self, app: &AppContext) -> Option<ModelHandle<T>> {
1923        if app.models.contains_key(&self.model_id) {
1924            Some(ModelHandle::new(self.model_id, &app.ref_counts))
1925        } else {
1926            None
1927        }
1928    }
1929}
1930
1931pub struct ViewHandle<T> {
1932    window_id: usize,
1933    view_id: usize,
1934    view_type: PhantomData<T>,
1935    ref_counts: Weak<Mutex<RefCounts>>,
1936}
1937
1938impl<T: View> ViewHandle<T> {
1939    fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
1940        ref_counts.lock().inc(view_id);
1941        Self {
1942            window_id,
1943            view_id,
1944            view_type: PhantomData,
1945            ref_counts: Arc::downgrade(ref_counts),
1946        }
1947    }
1948
1949    fn downgrade(&self) -> WeakViewHandle<T> {
1950        WeakViewHandle::new(self.window_id, self.view_id)
1951    }
1952
1953    pub fn window_id(&self) -> usize {
1954        self.window_id
1955    }
1956
1957    pub fn id(&self) -> usize {
1958        self.view_id
1959    }
1960
1961    pub fn as_ref<'a, A: ViewAsRef>(&self, app: &'a A) -> &'a T {
1962        app.view(self)
1963    }
1964
1965    pub fn read<'a, F, S>(&self, app: &'a App, read: F) -> S
1966    where
1967        F: FnOnce(&T, &AppContext) -> S,
1968    {
1969        app.read_view(self, read)
1970    }
1971
1972    pub fn update<A, F, S>(&self, app: &mut A, update: F) -> S
1973    where
1974        A: UpdateView,
1975        F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
1976    {
1977        app.update_view(self, update)
1978    }
1979
1980    pub fn is_focused(&self, app: &AppContext) -> bool {
1981        app.focused_view_id(self.window_id)
1982            .map_or(false, |focused_id| focused_id == self.view_id)
1983    }
1984}
1985
1986impl<T> Clone for ViewHandle<T> {
1987    fn clone(&self) -> Self {
1988        if let Some(ref_counts) = self.ref_counts.upgrade() {
1989            ref_counts.lock().inc(self.view_id);
1990        }
1991
1992        Self {
1993            window_id: self.window_id,
1994            view_id: self.view_id,
1995            view_type: PhantomData,
1996            ref_counts: self.ref_counts.clone(),
1997        }
1998    }
1999}
2000
2001impl<T> PartialEq for ViewHandle<T> {
2002    fn eq(&self, other: &Self) -> bool {
2003        self.window_id == other.window_id && self.view_id == other.view_id
2004    }
2005}
2006
2007impl<T> Eq for ViewHandle<T> {}
2008
2009impl<T> Debug for ViewHandle<T> {
2010    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2011        f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
2012            .field("window_id", &self.window_id)
2013            .field("view_id", &self.view_id)
2014            .finish()
2015    }
2016}
2017
2018impl<T> Drop for ViewHandle<T> {
2019    fn drop(&mut self) {
2020        if let Some(ref_counts) = self.ref_counts.upgrade() {
2021            ref_counts.lock().dec_view(self.window_id, self.view_id);
2022        }
2023    }
2024}
2025
2026impl<T> Handle<T> for ViewHandle<T> {
2027    fn id(&self) -> usize {
2028        self.view_id
2029    }
2030
2031    fn location(&self) -> EntityLocation {
2032        EntityLocation::View(self.window_id, self.view_id)
2033    }
2034}
2035
2036#[derive(Clone)]
2037pub struct AnyViewHandle {
2038    window_id: usize,
2039    view_id: usize,
2040    view_type: TypeId,
2041    ref_counts: Weak<Mutex<RefCounts>>,
2042}
2043
2044impl AnyViewHandle {
2045    pub fn id(&self) -> usize {
2046        self.view_id
2047    }
2048
2049    pub fn is<T: 'static>(&self) -> bool {
2050        TypeId::of::<T>() == self.view_type
2051    }
2052
2053    pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
2054        if self.is::<T>() {
2055            if let Some(ref_counts) = self.ref_counts.upgrade() {
2056                return Some(ViewHandle::new(self.window_id, self.view_id, &ref_counts));
2057            }
2058        }
2059        None
2060    }
2061}
2062
2063impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
2064    fn from(handle: &ViewHandle<T>) -> Self {
2065        if let Some(ref_counts) = handle.ref_counts.upgrade() {
2066            ref_counts.lock().inc(handle.view_id);
2067        }
2068        AnyViewHandle {
2069            window_id: handle.window_id,
2070            view_id: handle.view_id,
2071            view_type: TypeId::of::<T>(),
2072            ref_counts: handle.ref_counts.clone(),
2073        }
2074    }
2075}
2076
2077impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
2078    fn from(handle: ViewHandle<T>) -> Self {
2079        (&handle).into()
2080    }
2081}
2082
2083pub struct WeakViewHandle<T> {
2084    window_id: usize,
2085    view_id: usize,
2086    view_type: PhantomData<T>,
2087}
2088
2089impl<T: View> WeakViewHandle<T> {
2090    fn new(window_id: usize, view_id: usize) -> Self {
2091        Self {
2092            window_id,
2093            view_id,
2094            view_type: PhantomData,
2095        }
2096    }
2097
2098    pub fn upgrade(&self, app: &AppContext) -> Option<ViewHandle<T>> {
2099        if app
2100            .windows
2101            .get(&self.window_id)
2102            .and_then(|w| w.views.get(&self.view_id))
2103            .is_some()
2104        {
2105            Some(ViewHandle::new(
2106                self.window_id,
2107                self.view_id,
2108                &app.ref_counts,
2109            ))
2110        } else {
2111            None
2112        }
2113    }
2114}
2115
2116impl<T> Clone for WeakViewHandle<T> {
2117    fn clone(&self) -> Self {
2118        Self {
2119            window_id: self.window_id,
2120            view_id: self.view_id,
2121            view_type: PhantomData,
2122        }
2123    }
2124}
2125
2126#[derive(Default)]
2127struct RefCounts {
2128    counts: HashMap<usize, usize>,
2129    dropped_models: HashSet<usize>,
2130    dropped_views: HashSet<(usize, usize)>,
2131}
2132
2133impl RefCounts {
2134    fn inc(&mut self, model_id: usize) {
2135        *self.counts.entry(model_id).or_insert(0) += 1;
2136    }
2137
2138    fn dec_model(&mut self, model_id: usize) {
2139        if let Some(count) = self.counts.get_mut(&model_id) {
2140            *count -= 1;
2141            if *count == 0 {
2142                self.counts.remove(&model_id);
2143                self.dropped_models.insert(model_id);
2144            }
2145        } else {
2146            panic!("Expected ref count to be positive")
2147        }
2148    }
2149
2150    fn dec_view(&mut self, window_id: usize, view_id: usize) {
2151        if let Some(count) = self.counts.get_mut(&view_id) {
2152            *count -= 1;
2153            if *count == 0 {
2154                self.counts.remove(&view_id);
2155                self.dropped_views.insert((window_id, view_id));
2156            }
2157        } else {
2158            panic!("Expected ref count to be positive")
2159        }
2160    }
2161
2162    fn take_dropped(&mut self) -> (HashSet<usize>, HashSet<(usize, usize)>) {
2163        let mut dropped_models = HashSet::new();
2164        let mut dropped_views = HashSet::new();
2165        std::mem::swap(&mut self.dropped_models, &mut dropped_models);
2166        std::mem::swap(&mut self.dropped_views, &mut dropped_views);
2167        (dropped_models, dropped_views)
2168    }
2169}
2170
2171enum Subscription {
2172    FromModel {
2173        model_id: usize,
2174        callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize)>,
2175    },
2176    FromView {
2177        window_id: usize,
2178        view_id: usize,
2179        callback: Box<dyn FnMut(&mut dyn Any, &dyn Any, &mut MutableAppContext, usize, usize)>,
2180    },
2181}
2182
2183enum Observation {
2184    FromModel {
2185        model_id: usize,
2186        callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize)>,
2187    },
2188    FromView {
2189        window_id: usize,
2190        view_id: usize,
2191        callback: Box<dyn FnMut(&mut dyn Any, usize, &mut MutableAppContext, usize, usize)>,
2192    },
2193}
2194
2195enum TaskCallback {
2196    OnModelFromFuture {
2197        model_id: usize,
2198        callback: Box<
2199            dyn FnOnce(
2200                &mut dyn Any,
2201                Box<dyn Any>,
2202                &mut MutableAppContext,
2203                usize,
2204                Rc<executor::Foreground>,
2205            ),
2206        >,
2207    },
2208    OnModelFromStream {
2209        model_id: usize,
2210        callback: Box<dyn FnMut(&mut dyn Any, Box<dyn Any>, &mut MutableAppContext, usize) -> bool>,
2211    },
2212    OnViewFromFuture {
2213        window_id: usize,
2214        view_id: usize,
2215        callback: Box<
2216            dyn FnOnce(
2217                &mut dyn AnyView,
2218                Box<dyn Any>,
2219                &mut MutableAppContext,
2220                usize,
2221                usize,
2222                Rc<executor::Foreground>,
2223            ),
2224        >,
2225    },
2226    OnViewFromStream {
2227        window_id: usize,
2228        view_id: usize,
2229        callback: Box<
2230            dyn FnMut(&mut dyn AnyView, Box<dyn Any>, &mut MutableAppContext, usize, usize) -> bool,
2231        >,
2232    },
2233}
2234
2235#[cfg(test)]
2236mod tests {
2237    use super::*;
2238    use crate::elements::*;
2239
2240    #[test]
2241    fn test_model_handles() {
2242        struct Model {
2243            other: Option<ModelHandle<Model>>,
2244            events: Vec<String>,
2245        }
2246
2247        impl Entity for Model {
2248            type Event = usize;
2249        }
2250
2251        impl Model {
2252            fn new(other: Option<ModelHandle<Self>>, ctx: &mut ModelContext<Self>) -> Self {
2253                if let Some(other) = other.as_ref() {
2254                    ctx.observe(other, |me, _, _| {
2255                        me.events.push("notified".into());
2256                    });
2257                    ctx.subscribe(other, |me, event, _| {
2258                        me.events.push(format!("observed event {}", event));
2259                    });
2260                }
2261
2262                Self {
2263                    other,
2264                    events: Vec::new(),
2265                }
2266            }
2267        }
2268
2269        let mut app = App::new().unwrap();
2270        let app = &mut app;
2271
2272        let handle_1 = app.add_model(|ctx| Model::new(None, ctx));
2273        let handle_2 = app.add_model(|ctx| Model::new(Some(handle_1.clone()), ctx));
2274        assert_eq!(app.0.borrow().ctx.models.len(), 2);
2275
2276        handle_1.update(app, |model, ctx| {
2277            model.events.push("updated".into());
2278            ctx.emit(1);
2279            ctx.notify();
2280            ctx.emit(2);
2281        });
2282        handle_1.read(app, |model, _| {
2283            assert_eq!(model.events, vec!["updated".to_string()]);
2284        });
2285        handle_2.read(app, |model, _| {
2286            assert_eq!(
2287                model.events,
2288                vec![
2289                    "observed event 1".to_string(),
2290                    "notified".to_string(),
2291                    "observed event 2".to_string(),
2292                ]
2293            );
2294        });
2295
2296        handle_2.update(app, |model, _| {
2297            drop(handle_1);
2298            model.other.take();
2299        });
2300
2301        let app_state = app.0.borrow();
2302        assert_eq!(app_state.ctx.models.len(), 1);
2303        assert!(app_state.subscriptions.is_empty());
2304        assert!(app_state.observations.is_empty());
2305    }
2306
2307    #[test]
2308    fn test_subscribe_and_emit_from_model() {
2309        #[derive(Default)]
2310        struct Model {
2311            events: Vec<usize>,
2312        }
2313
2314        impl Entity for Model {
2315            type Event = usize;
2316        }
2317
2318        let mut app = App::new().unwrap();
2319        let app = &mut app;
2320
2321        let handle_1 = app.add_model(|_| Model::default());
2322        let handle_2 = app.add_model(|_| Model::default());
2323        let handle_2b = handle_2.clone();
2324
2325        handle_1.update(app, |_, c| {
2326            c.subscribe(&handle_2, move |model: &mut Model, event, c| {
2327                model.events.push(*event);
2328
2329                c.subscribe(&handle_2b, |model, event, _| {
2330                    model.events.push(*event * 2);
2331                });
2332            });
2333        });
2334
2335        handle_2.update(app, |_, c| c.emit(7));
2336        handle_1.read(app, |model, _| assert_eq!(model.events, vec![7]));
2337
2338        handle_2.update(app, |_, c| c.emit(5));
2339        handle_1.read(app, |model, _| assert_eq!(model.events, vec![7, 10, 5]));
2340    }
2341
2342    #[test]
2343    fn test_observe_and_notify_from_model() {
2344        #[derive(Default)]
2345        struct Model {
2346            count: usize,
2347            events: Vec<usize>,
2348        }
2349
2350        impl Entity for Model {
2351            type Event = ();
2352        }
2353
2354        let mut app = App::new().unwrap();
2355
2356        let app = &mut app;
2357        let handle_1 = app.add_model(|_| Model::default());
2358        let handle_2 = app.add_model(|_| Model::default());
2359        let handle_2b = handle_2.clone();
2360
2361        handle_1.update(app, |_, c| {
2362            c.observe(&handle_2, move |model, observed, c| {
2363                model.events.push(observed.as_ref(c).count);
2364                c.observe(&handle_2b, |model, observed, c| {
2365                    model.events.push(observed.as_ref(c).count * 2);
2366                });
2367            });
2368        });
2369
2370        handle_2.update(app, |model, c| {
2371            model.count = 7;
2372            c.notify()
2373        });
2374        handle_1.read(app, |model, _| assert_eq!(model.events, vec![7]));
2375
2376        handle_2.update(app, |model, c| {
2377            model.count = 5;
2378            c.notify()
2379        });
2380        handle_1.read(app, |model, _| assert_eq!(model.events, vec![7, 10, 5]))
2381    }
2382
2383    #[test]
2384    fn test_spawn_from_model() {
2385        #[derive(Default)]
2386        struct Model {
2387            count: usize,
2388        }
2389
2390        impl Entity for Model {
2391            type Event = ();
2392        }
2393
2394        App::test(|mut app| async move {
2395            let handle = app.add_model(|_| Model::default());
2396            handle
2397                .update(&mut app, |_, c| {
2398                    c.spawn_local(async { 7 }, |model, output, _| {
2399                        model.count = output;
2400                    })
2401                })
2402                .await;
2403            handle.read(&app, |model, _| assert_eq!(model.count, 7));
2404
2405            handle
2406                .update(&mut app, |_, c| {
2407                    c.spawn(async { 14 }, |model, output, _| {
2408                        model.count = output;
2409                    })
2410                })
2411                .await;
2412            handle.read(&app, |model, _| assert_eq!(model.count, 14));
2413        });
2414    }
2415
2416    #[test]
2417    fn test_spawn_stream_local_from_model() {
2418        #[derive(Default)]
2419        struct Model {
2420            events: Vec<Option<usize>>,
2421        }
2422
2423        impl Entity for Model {
2424            type Event = ();
2425        }
2426
2427        App::test(|mut app| async move {
2428            let handle = app.add_model(|_| Model::default());
2429            handle
2430                .update(&mut app, |_, c| {
2431                    c.spawn_stream_local(smol::stream::iter(vec![1, 2, 3]), |model, output, _| {
2432                        model.events.push(output);
2433                    })
2434                })
2435                .await;
2436
2437            handle.read(&app, |model, _| {
2438                assert_eq!(model.events, [Some(1), Some(2), Some(3), None])
2439            });
2440        })
2441    }
2442
2443    #[test]
2444    fn test_view_handles() {
2445        struct View {
2446            other: Option<ViewHandle<View>>,
2447            events: Vec<String>,
2448        }
2449
2450        impl Entity for View {
2451            type Event = usize;
2452        }
2453
2454        impl super::View for View {
2455            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2456                Empty::new().boxed()
2457            }
2458
2459            fn ui_name() -> &'static str {
2460                "View"
2461            }
2462        }
2463
2464        impl View {
2465            fn new(other: Option<ViewHandle<View>>, ctx: &mut ViewContext<Self>) -> Self {
2466                if let Some(other) = other.as_ref() {
2467                    ctx.subscribe_to_view(other, |me, _, event, _| {
2468                        me.events.push(format!("observed event {}", event));
2469                    });
2470                }
2471                Self {
2472                    other,
2473                    events: Vec::new(),
2474                }
2475            }
2476        }
2477
2478        let mut app = App::new().unwrap();
2479        let app = &mut app;
2480
2481        let (window_id, _) = app.add_window(|ctx| View::new(None, ctx));
2482        let handle_1 = app.add_view(window_id, |ctx| View::new(None, ctx));
2483        let handle_2 = app.add_view(window_id, |ctx| View::new(Some(handle_1.clone()), ctx));
2484        assert_eq!(app.0.borrow().ctx.windows[&window_id].views.len(), 3);
2485
2486        handle_1.update(app, |view, ctx| {
2487            view.events.push("updated".into());
2488            ctx.emit(1);
2489            ctx.emit(2);
2490        });
2491        handle_1.read(app, |view, _| {
2492            assert_eq!(view.events, vec!["updated".to_string()]);
2493        });
2494        handle_2.read(app, |view, _| {
2495            assert_eq!(
2496                view.events,
2497                vec![
2498                    "observed event 1".to_string(),
2499                    "observed event 2".to_string(),
2500                ]
2501            );
2502        });
2503
2504        handle_2.update(app, |view, _| {
2505            drop(handle_1);
2506            view.other.take();
2507        });
2508
2509        let app_state = app.0.borrow();
2510        assert_eq!(app_state.ctx.windows[&window_id].views.len(), 2);
2511        assert!(app_state.subscriptions.is_empty());
2512        assert!(app_state.observations.is_empty());
2513    }
2514
2515    #[test]
2516    fn test_subscribe_and_emit_from_view() {
2517        #[derive(Default)]
2518        struct View {
2519            events: Vec<usize>,
2520        }
2521
2522        impl Entity for View {
2523            type Event = usize;
2524        }
2525
2526        impl super::View for View {
2527            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2528                Empty::new().boxed()
2529            }
2530
2531            fn ui_name() -> &'static str {
2532                "View"
2533            }
2534        }
2535
2536        struct Model;
2537
2538        impl Entity for Model {
2539            type Event = usize;
2540        }
2541
2542        let mut app = App::new().unwrap();
2543        let app = &mut app;
2544
2545        let (window_id, handle_1) = app.add_window(|_| View::default());
2546        let handle_2 = app.add_view(window_id, |_| View::default());
2547        let handle_2b = handle_2.clone();
2548        let handle_3 = app.add_model(|_| Model);
2549
2550        handle_1.update(app, |_, c| {
2551            c.subscribe_to_view(&handle_2, move |me, _, event, c| {
2552                me.events.push(*event);
2553
2554                c.subscribe_to_view(&handle_2b, |me, _, event, _| {
2555                    me.events.push(*event * 2);
2556                });
2557            });
2558
2559            c.subscribe_to_model(&handle_3, |me, _, event, _| {
2560                me.events.push(*event);
2561            })
2562        });
2563
2564        handle_2.update(app, |_, c| c.emit(7));
2565        handle_1.read(app, |view, _| assert_eq!(view.events, vec![7]));
2566
2567        handle_2.update(app, |_, c| c.emit(5));
2568        handle_1.read(app, |view, _| assert_eq!(view.events, vec![7, 10, 5]));
2569
2570        handle_3.update(app, |_, c| c.emit(9));
2571        handle_1.read(app, |view, _| assert_eq!(view.events, vec![7, 10, 5, 9]));
2572    }
2573
2574    #[test]
2575    fn test_dropping_subscribers() {
2576        struct View;
2577
2578        impl Entity for View {
2579            type Event = ();
2580        }
2581
2582        impl super::View for View {
2583            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2584                Empty::new().boxed()
2585            }
2586
2587            fn ui_name() -> &'static str {
2588                "View"
2589            }
2590        }
2591
2592        struct Model;
2593
2594        impl Entity for Model {
2595            type Event = ();
2596        }
2597
2598        let mut app = App::new().unwrap();
2599        let app = &mut app;
2600
2601        let (window_id, _) = app.add_window(|_| View);
2602        let observing_view = app.add_view(window_id, |_| View);
2603        let emitting_view = app.add_view(window_id, |_| View);
2604        let observing_model = app.add_model(|_| Model);
2605        let observed_model = app.add_model(|_| Model);
2606
2607        observing_view.update(app, |_, ctx| {
2608            ctx.subscribe_to_view(&emitting_view, |_, _, _, _| {});
2609            ctx.subscribe_to_model(&observed_model, |_, _, _, _| {});
2610        });
2611        observing_model.update(app, |_, ctx| {
2612            ctx.subscribe(&observed_model, |_, _, _| {});
2613        });
2614
2615        app.update(|_| {
2616            drop(observing_view);
2617            drop(observing_model);
2618        });
2619
2620        emitting_view.update(app, |_, ctx| ctx.emit(()));
2621        observed_model.update(app, |_, ctx| ctx.emit(()));
2622    }
2623
2624    #[test]
2625    fn test_observe_and_notify_from_view() {
2626        #[derive(Default)]
2627        struct View {
2628            events: Vec<usize>,
2629        }
2630
2631        impl Entity for View {
2632            type Event = usize;
2633        }
2634
2635        impl super::View for View {
2636            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2637                Empty::new().boxed()
2638            }
2639
2640            fn ui_name() -> &'static str {
2641                "View"
2642            }
2643        }
2644
2645        #[derive(Default)]
2646        struct Model {
2647            count: usize,
2648        }
2649
2650        impl Entity for Model {
2651            type Event = ();
2652        }
2653
2654        let mut app = App::new().unwrap();
2655        let app = &mut app;
2656        let (_, view) = app.add_window(|_| View::default());
2657        let model = app.add_model(|_| Model::default());
2658
2659        view.update(app, |_, c| {
2660            c.observe(&model, |me, observed, c| {
2661                me.events.push(observed.as_ref(c).count)
2662            });
2663        });
2664
2665        model.update(app, |model, c| {
2666            model.count = 11;
2667            c.notify();
2668        });
2669        view.read(app, |view, _| assert_eq!(view.events, vec![11]));
2670    }
2671
2672    #[test]
2673    fn test_dropping_observers() {
2674        struct View;
2675
2676        impl Entity for View {
2677            type Event = ();
2678        }
2679
2680        impl super::View for View {
2681            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2682                Empty::new().boxed()
2683            }
2684
2685            fn ui_name() -> &'static str {
2686                "View"
2687            }
2688        }
2689
2690        struct Model;
2691
2692        impl Entity for Model {
2693            type Event = ();
2694        }
2695
2696        let mut app = App::new().unwrap();
2697        let app = &mut app;
2698
2699        let (window_id, _) = app.add_window(|_| View);
2700        let observing_view = app.add_view(window_id, |_| View);
2701        let observing_model = app.add_model(|_| Model);
2702        let observed_model = app.add_model(|_| Model);
2703
2704        observing_view.update(app, |_, ctx| {
2705            ctx.observe(&observed_model, |_, _, _| {});
2706        });
2707        observing_model.update(app, |_, ctx| {
2708            ctx.observe(&observed_model, |_, _, _| {});
2709        });
2710
2711        app.update(|_| {
2712            drop(observing_view);
2713            drop(observing_model);
2714        });
2715
2716        observed_model.update(app, |_, ctx| ctx.notify());
2717    }
2718
2719    #[test]
2720    fn test_focus() {
2721        #[derive(Default)]
2722        struct View {
2723            events: Vec<String>,
2724        }
2725
2726        impl Entity for View {
2727            type Event = String;
2728        }
2729
2730        impl super::View for View {
2731            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2732                Empty::new().boxed()
2733            }
2734
2735            fn ui_name() -> &'static str {
2736                "View"
2737            }
2738
2739            fn on_focus(&mut self, ctx: &mut ViewContext<Self>) {
2740                self.events.push("self focused".into());
2741                ctx.emit("focused".into());
2742            }
2743
2744            fn on_blur(&mut self, ctx: &mut ViewContext<Self>) {
2745                self.events.push("self blurred".into());
2746                ctx.emit("blurred".into());
2747            }
2748        }
2749
2750        let mut app = App::new().unwrap();
2751        let app = &mut app;
2752        let (window_id, view_1) = app.add_window(|_| View::default());
2753        let view_2 = app.add_view(window_id, |_| View::default());
2754
2755        view_1.update(app, |_, ctx| {
2756            ctx.subscribe_to_view(&view_2, |view_1, _, event, _| {
2757                view_1.events.push(format!("view 2 {}", event));
2758            });
2759            ctx.focus(&view_2);
2760        });
2761
2762        view_1.update(app, |_, ctx| {
2763            ctx.focus(&view_1);
2764        });
2765
2766        view_1.read(app, |view_1, _| {
2767            assert_eq!(
2768                view_1.events,
2769                [
2770                    "self focused".to_string(),
2771                    "self blurred".to_string(),
2772                    "view 2 focused".to_string(),
2773                    "self focused".to_string(),
2774                    "view 2 blurred".to_string(),
2775                ],
2776            );
2777        });
2778    }
2779
2780    #[test]
2781    fn test_spawn_from_view() {
2782        #[derive(Default)]
2783        struct View {
2784            count: usize,
2785        }
2786
2787        impl Entity for View {
2788            type Event = ();
2789        }
2790
2791        impl super::View for View {
2792            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2793                Empty::new().boxed()
2794            }
2795
2796            fn ui_name() -> &'static str {
2797                "View"
2798            }
2799        }
2800
2801        App::test(|mut app| async move {
2802            let (_, handle) = app.add_window(|_| View::default());
2803            handle
2804                .update(&mut app, |_, c| {
2805                    c.spawn_local(async { 7 }, |me, output, _| {
2806                        me.count = output;
2807                    })
2808                })
2809                .await;
2810            handle.read(&app, |view, _| assert_eq!(view.count, 7));
2811            handle
2812                .update(&mut app, |_, c| {
2813                    c.spawn(async { 14 }, |me, output, _| {
2814                        me.count = output;
2815                    })
2816                })
2817                .await;
2818            handle.read(&app, |view, _| assert_eq!(view.count, 14));
2819        });
2820    }
2821
2822    #[test]
2823    fn test_spawn_stream_local_from_view() {
2824        #[derive(Default)]
2825        struct View {
2826            events: Vec<Option<usize>>,
2827        }
2828
2829        impl Entity for View {
2830            type Event = ();
2831        }
2832
2833        impl super::View for View {
2834            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2835                Empty::new().boxed()
2836            }
2837
2838            fn ui_name() -> &'static str {
2839                "View"
2840            }
2841        }
2842
2843        App::test(|mut app| async move {
2844            let (_, handle) = app.add_window(|_| View::default());
2845            handle
2846                .update(&mut app, |_, c| {
2847                    c.spawn_stream_local(smol::stream::iter(vec![1, 2, 3]), |me, output, _| {
2848                        me.events.push(output);
2849                    })
2850                })
2851                .await;
2852
2853            handle.read(&app, |view, _| {
2854                assert_eq!(view.events, [Some(1), Some(2), Some(3), None])
2855            });
2856        });
2857    }
2858
2859    #[test]
2860    fn test_dispatch_action() {
2861        struct ViewA {
2862            id: usize,
2863        }
2864
2865        impl Entity for ViewA {
2866            type Event = ();
2867        }
2868
2869        impl View for ViewA {
2870            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2871                Empty::new().boxed()
2872            }
2873
2874            fn ui_name() -> &'static str {
2875                "View"
2876            }
2877        }
2878
2879        struct ViewB {
2880            id: usize,
2881        }
2882
2883        impl Entity for ViewB {
2884            type Event = ();
2885        }
2886
2887        impl View for ViewB {
2888            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2889                Empty::new().boxed()
2890            }
2891
2892            fn ui_name() -> &'static str {
2893                "View"
2894            }
2895        }
2896
2897        struct ActionArg {
2898            foo: String,
2899        }
2900
2901        let mut app = App::new().unwrap();
2902        let actions = Rc::new(RefCell::new(Vec::new()));
2903
2904        let actions_clone = actions.clone();
2905        app.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
2906            actions_clone.borrow_mut().push("global a".to_string());
2907        });
2908
2909        let actions_clone = actions.clone();
2910        app.add_global_action("action", move |_: &ActionArg, _: &mut MutableAppContext| {
2911            actions_clone.borrow_mut().push("global b".to_string());
2912        });
2913
2914        let actions_clone = actions.clone();
2915        app.add_action("action", move |view: &mut ViewA, arg: &ActionArg, ctx| {
2916            assert_eq!(arg.foo, "bar");
2917            ctx.propagate_action();
2918            actions_clone.borrow_mut().push(format!("{} a", view.id));
2919        });
2920
2921        let actions_clone = actions.clone();
2922        app.add_action("action", move |view: &mut ViewA, _: &ActionArg, ctx| {
2923            if view.id != 1 {
2924                ctx.propagate_action();
2925            }
2926            actions_clone.borrow_mut().push(format!("{} b", view.id));
2927        });
2928
2929        let actions_clone = actions.clone();
2930        app.add_action("action", move |view: &mut ViewB, _: &ActionArg, ctx| {
2931            ctx.propagate_action();
2932            actions_clone.borrow_mut().push(format!("{} c", view.id));
2933        });
2934
2935        let actions_clone = actions.clone();
2936        app.add_action("action", move |view: &mut ViewB, _: &ActionArg, ctx| {
2937            ctx.propagate_action();
2938            actions_clone.borrow_mut().push(format!("{} d", view.id));
2939        });
2940
2941        let (window_id, view_1) = app.add_window(|_| ViewA { id: 1 });
2942        let view_2 = app.add_view(window_id, |_| ViewB { id: 2 });
2943        let view_3 = app.add_view(window_id, |_| ViewA { id: 3 });
2944        let view_4 = app.add_view(window_id, |_| ViewB { id: 4 });
2945
2946        app.dispatch_action(
2947            window_id,
2948            vec![view_1.id(), view_2.id(), view_3.id(), view_4.id()],
2949            "action",
2950            ActionArg { foo: "bar".into() },
2951        );
2952
2953        assert_eq!(
2954            *actions.borrow(),
2955            vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "1 b"]
2956        );
2957
2958        // Remove view_1, which doesn't propagate the action
2959        actions.borrow_mut().clear();
2960        app.dispatch_action(
2961            window_id,
2962            vec![view_2.id(), view_3.id(), view_4.id()],
2963            "action",
2964            ActionArg { foo: "bar".into() },
2965        );
2966
2967        assert_eq!(
2968            *actions.borrow(),
2969            vec!["4 d", "4 c", "3 b", "3 a", "2 d", "2 c", "global b", "global a"]
2970        );
2971    }
2972
2973    #[test]
2974    fn test_dispatch_keystroke() -> Result<()> {
2975        use std::cell::Cell;
2976
2977        #[derive(Clone)]
2978        struct ActionArg {
2979            key: String,
2980        }
2981
2982        struct View {
2983            id: usize,
2984            keymap_context: keymap::Context,
2985        }
2986
2987        impl Entity for View {
2988            type Event = ();
2989        }
2990
2991        impl super::View for View {
2992            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
2993                Empty::new().boxed()
2994            }
2995
2996            fn ui_name() -> &'static str {
2997                "View"
2998            }
2999
3000            fn keymap_context(&self, _: &AppContext) -> keymap::Context {
3001                self.keymap_context.clone()
3002            }
3003        }
3004
3005        impl View {
3006            fn new(id: usize) -> Self {
3007                View {
3008                    id,
3009                    keymap_context: keymap::Context::default(),
3010                }
3011            }
3012        }
3013
3014        let mut app = App::new().unwrap();
3015
3016        let mut view_1 = View::new(1);
3017        let mut view_2 = View::new(2);
3018        let mut view_3 = View::new(3);
3019        view_1.keymap_context.set.insert("a".into());
3020        view_2.keymap_context.set.insert("b".into());
3021        view_3.keymap_context.set.insert("c".into());
3022
3023        let (window_id, view_1) = app.add_window(|_| view_1);
3024        let view_2 = app.add_view(window_id, |_| view_2);
3025        let view_3 = app.add_view(window_id, |_| view_3);
3026
3027        // This keymap's only binding dispatches an action on view 2 because that view will have
3028        // "a" and "b" in its context, but not "c".
3029        let binding = keymap::Binding::new("a", "action", Some("a && b && !c"))
3030            .with_arg(ActionArg { key: "a".into() });
3031        app.add_bindings(vec![binding]);
3032
3033        let handled_action = Rc::new(Cell::new(false));
3034        let handled_action_clone = handled_action.clone();
3035        app.add_action("action", move |view: &mut View, arg: &ActionArg, _ctx| {
3036            handled_action_clone.set(true);
3037            assert_eq!(view.id, 2);
3038            assert_eq!(arg.key, "a");
3039        });
3040
3041        app.dispatch_keystroke(
3042            window_id,
3043            vec![view_1.id(), view_2.id(), view_3.id()],
3044            &Keystroke::parse("a")?,
3045        )?;
3046
3047        assert!(handled_action.get());
3048        Ok(())
3049    }
3050
3051    // #[test]
3052    // fn test_ui_and_window_updates() {
3053    //     struct View {
3054    //         count: usize,
3055    //     }
3056
3057    //     impl Entity for View {
3058    //         type Event = ();
3059    //     }
3060
3061    //     impl super::View for View {
3062    //         fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
3063    //             Empty::new().boxed()
3064    //         }
3065
3066    //         fn ui_name() -> &'static str {
3067    //             "View"
3068    //         }
3069    //     }
3070
3071    //     App::test(|mut app| async move {
3072    //         let (window_id, _) = app.add_window(|_| View { count: 3 });
3073    //         let view_1 = app.add_view(window_id, |_| View { count: 1 });
3074    //         let view_2 = app.add_view(window_id, |_| View { count: 2 });
3075
3076    //         // Ensure that registering for UI updates after mutating the app still gives us all the
3077    //         // updates.
3078    //         let ui_updates = Rc::new(RefCell::new(Vec::new()));
3079    //         let ui_updates_ = ui_updates.clone();
3080    //         app.on_ui_update(move |update, _| ui_updates_.borrow_mut().push(update));
3081
3082    //         assert_eq!(
3083    //             ui_updates.borrow_mut().drain(..).collect::<Vec<_>>(),
3084    //             vec![UiUpdate::OpenWindow {
3085    //                 window_id,
3086    //                 width: 1024.0,
3087    //                 height: 768.0,
3088    //             }]
3089    //         );
3090
3091    //         let window_invalidations = Rc::new(RefCell::new(Vec::new()));
3092    //         let window_invalidations_ = window_invalidations.clone();
3093    //         app.on_window_invalidated(window_id, move |update, _| {
3094    //             window_invalidations_.borrow_mut().push(update)
3095    //         });
3096
3097    //         let view_2_id = view_2.id();
3098    //         view_1.update(&mut app, |view, ctx| {
3099    //             view.count = 7;
3100    //             ctx.notify();
3101    //             drop(view_2);
3102    //         });
3103
3104    //         let invalidation = window_invalidations.borrow_mut().drain(..).next().unwrap();
3105    //         assert_eq!(invalidation.updated.len(), 1);
3106    //         assert!(invalidation.updated.contains(&view_1.id()));
3107    //         assert_eq!(invalidation.removed, vec![view_2_id]);
3108
3109    //         let view_3 = view_1.update(&mut app, |_, ctx| ctx.add_view(|_| View { count: 8 }));
3110
3111    //         let invalidation = window_invalidations.borrow_mut().drain(..).next().unwrap();
3112    //         assert_eq!(invalidation.updated.len(), 1);
3113    //         assert!(invalidation.updated.contains(&view_3.id()));
3114    //         assert!(invalidation.removed.is_empty());
3115
3116    //         view_3
3117    //             .update(&mut app, |_, ctx| {
3118    //                 ctx.spawn_local(async { 9 }, |me, output, ctx| {
3119    //                     me.count = output;
3120    //                     ctx.notify();
3121    //                 })
3122    //             })
3123    //             .await;
3124
3125    //         let invalidation = window_invalidations.borrow_mut().drain(..).next().unwrap();
3126    //         assert_eq!(invalidation.updated.len(), 1);
3127    //         assert!(invalidation.updated.contains(&view_3.id()));
3128    //         assert!(invalidation.removed.is_empty());
3129    //     });
3130    // }
3131
3132    #[test]
3133    fn test_finish_pending_tasks() {
3134        struct View;
3135
3136        impl Entity for View {
3137            type Event = ();
3138        }
3139
3140        impl super::View for View {
3141            fn render<'a>(&self, _: &AppContext) -> Box<dyn Element> {
3142                Empty::new().boxed()
3143            }
3144
3145            fn ui_name() -> &'static str {
3146                "View"
3147            }
3148        }
3149
3150        struct Model;
3151
3152        impl Entity for Model {
3153            type Event = ();
3154        }
3155
3156        App::test(|mut app| async move {
3157            let model = app.add_model(|_| Model);
3158            let (_, view) = app.add_window(|_| View);
3159
3160            model.update(&mut app, |_, ctx| {
3161                let _ = ctx.spawn(async {}, |_, _, _| {});
3162                let _ = ctx.spawn_local(async {}, |_, _, _| {});
3163                let _ = ctx.spawn_stream_local(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {});
3164            });
3165
3166            view.update(&mut app, |_, ctx| {
3167                let _ = ctx.spawn(async {}, |_, _, _| {});
3168                let _ = ctx.spawn_local(async {}, |_, _, _| {});
3169                let _ = ctx.spawn_stream_local(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {});
3170            });
3171
3172            assert!(!app.0.borrow().task_callbacks.is_empty());
3173            app.finish_pending_tasks().await;
3174            assert!(app.0.borrow().task_callbacks.is_empty());
3175            app.finish_pending_tasks().await; // Don't block if there are no tasks
3176        });
3177    }
3178}