1pub mod action;
2mod callback_collection;
3#[cfg(any(test, feature = "test-support"))]
4pub mod test_app_context;
5
6use std::{
7 any::{type_name, Any, TypeId},
8 cell::RefCell,
9 fmt::{self, Debug},
10 hash::{Hash, Hasher},
11 marker::PhantomData,
12 mem,
13 ops::{Deref, DerefMut, Range},
14 path::{Path, PathBuf},
15 pin::Pin,
16 rc::{self, Rc},
17 sync::{Arc, Weak},
18 time::Duration,
19};
20
21use anyhow::{anyhow, Context, Result};
22use lazy_static::lazy_static;
23use parking_lot::Mutex;
24use postage::oneshot;
25use smallvec::SmallVec;
26use smol::prelude::*;
27
28pub use action::*;
29use callback_collection::{CallbackCollection, Mapping};
30use collections::{btree_map, hash_map::Entry, BTreeMap, HashMap, HashSet, VecDeque};
31use keymap::MatchResult;
32use platform::Event;
33#[cfg(any(test, feature = "test-support"))]
34pub use test_app_context::{ContextHandle, TestAppContext};
35
36use crate::{
37 elements::ElementBox,
38 executor::{self, Task},
39 geometry::rect::RectF,
40 keymap::{self, Binding, Keystroke},
41 platform::{self, KeyDownEvent, Platform, PromptLevel, WindowOptions},
42 presenter::Presenter,
43 util::post_inc,
44 Appearance, AssetCache, AssetSource, ClipboardItem, FontCache, InputHandler, KeyUpEvent,
45 ModifiersChangedEvent, MouseButton, MouseRegionId, PathPromptOptions, TextLayoutCache,
46};
47
48pub trait Entity: 'static {
49 type Event;
50
51 fn release(&mut self, _: &mut MutableAppContext) {}
52 fn app_will_quit(
53 &mut self,
54 _: &mut MutableAppContext,
55 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
56 None
57 }
58}
59
60pub trait View: Entity + Sized {
61 fn ui_name() -> &'static str;
62 fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox;
63 fn focus_in(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
64 fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
65 fn key_down(&mut self, _: &KeyDownEvent, _: &mut ViewContext<Self>) -> bool {
66 false
67 }
68 fn key_up(&mut self, _: &KeyUpEvent, _: &mut ViewContext<Self>) -> bool {
69 false
70 }
71 fn modifiers_changed(&mut self, _: &ModifiersChangedEvent, _: &mut ViewContext<Self>) -> bool {
72 false
73 }
74
75 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
76 Self::default_keymap_context()
77 }
78 fn default_keymap_context() -> keymap::Context {
79 let mut cx = keymap::Context::default();
80 cx.set.insert(Self::ui_name().into());
81 cx
82 }
83 fn debug_json(&self, _: &AppContext) -> serde_json::Value {
84 serde_json::Value::Null
85 }
86
87 fn text_for_range(&self, _: Range<usize>, _: &AppContext) -> Option<String> {
88 None
89 }
90 fn selected_text_range(&self, _: &AppContext) -> Option<Range<usize>> {
91 None
92 }
93 fn marked_text_range(&self, _: &AppContext) -> Option<Range<usize>> {
94 None
95 }
96 fn unmark_text(&mut self, _: &mut ViewContext<Self>) {}
97 fn replace_text_in_range(
98 &mut self,
99 _: Option<Range<usize>>,
100 _: &str,
101 _: &mut ViewContext<Self>,
102 ) {
103 }
104 fn replace_and_mark_text_in_range(
105 &mut self,
106 _: Option<Range<usize>>,
107 _: &str,
108 _: Option<Range<usize>>,
109 _: &mut ViewContext<Self>,
110 ) {
111 }
112}
113
114pub trait ReadModel {
115 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T;
116}
117
118pub trait ReadModelWith {
119 fn read_model_with<E: Entity, T>(
120 &self,
121 handle: &ModelHandle<E>,
122 read: &mut dyn FnMut(&E, &AppContext) -> T,
123 ) -> T;
124}
125
126pub trait UpdateModel {
127 fn update_model<T: Entity, O>(
128 &mut self,
129 handle: &ModelHandle<T>,
130 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
131 ) -> O;
132}
133
134pub trait UpgradeModelHandle {
135 fn upgrade_model_handle<T: Entity>(
136 &self,
137 handle: &WeakModelHandle<T>,
138 ) -> Option<ModelHandle<T>>;
139
140 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool;
141
142 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle>;
143}
144
145pub trait UpgradeViewHandle {
146 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>>;
147
148 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle>;
149}
150
151pub trait ReadView {
152 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T;
153}
154
155pub trait ReadViewWith {
156 fn read_view_with<V, T>(
157 &self,
158 handle: &ViewHandle<V>,
159 read: &mut dyn FnMut(&V, &AppContext) -> T,
160 ) -> T
161 where
162 V: View;
163}
164
165pub trait UpdateView {
166 fn update_view<T, S>(
167 &mut self,
168 handle: &ViewHandle<T>,
169 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
170 ) -> S
171 where
172 T: View;
173}
174
175pub struct Menu<'a> {
176 pub name: &'a str,
177 pub items: Vec<MenuItem<'a>>,
178}
179
180pub enum MenuItem<'a> {
181 Separator,
182 Submenu(Menu<'a>),
183 Action {
184 name: &'a str,
185 action: Box<dyn Action>,
186 },
187}
188
189#[derive(Clone)]
190pub struct App(Rc<RefCell<MutableAppContext>>);
191
192#[derive(Clone)]
193pub struct AsyncAppContext(Rc<RefCell<MutableAppContext>>);
194
195pub struct WindowInputHandler {
196 app: Rc<RefCell<MutableAppContext>>,
197 window_id: usize,
198}
199
200impl App {
201 pub fn new(asset_source: impl AssetSource) -> Result<Self> {
202 let platform = platform::current::platform();
203 let foreground_platform = platform::current::foreground_platform();
204 let foreground = Rc::new(executor::Foreground::platform(platform.dispatcher())?);
205 let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
206 foreground,
207 Arc::new(executor::Background::new()),
208 platform.clone(),
209 foreground_platform.clone(),
210 Arc::new(FontCache::new(platform.fonts())),
211 Default::default(),
212 asset_source,
213 ))));
214
215 foreground_platform.on_quit(Box::new({
216 let cx = app.0.clone();
217 move || {
218 cx.borrow_mut().quit();
219 }
220 }));
221 foreground_platform.on_will_open_menu(Box::new({
222 let cx = app.0.clone();
223 move || {
224 let mut cx = cx.borrow_mut();
225 cx.keystroke_matcher.clear_pending();
226 }
227 }));
228 foreground_platform.on_validate_menu_command(Box::new({
229 let cx = app.0.clone();
230 move |action| {
231 let cx = cx.borrow_mut();
232 !cx.keystroke_matcher.has_pending_keystrokes() && cx.is_action_available(action)
233 }
234 }));
235 foreground_platform.on_menu_command(Box::new({
236 let cx = app.0.clone();
237 move |action| {
238 let mut cx = cx.borrow_mut();
239 if let Some(key_window_id) = cx.cx.platform.key_window_id() {
240 if let Some(view_id) = cx.focused_view_id(key_window_id) {
241 cx.handle_dispatch_action_from_effect(key_window_id, Some(view_id), action);
242 return;
243 }
244 }
245 cx.dispatch_global_action_any(action);
246 }
247 }));
248
249 app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
250 Ok(app)
251 }
252
253 pub fn background(&self) -> Arc<executor::Background> {
254 self.0.borrow().background().clone()
255 }
256
257 pub fn on_become_active<F>(self, mut callback: F) -> Self
258 where
259 F: 'static + FnMut(&mut MutableAppContext),
260 {
261 let cx = self.0.clone();
262 self.0
263 .borrow_mut()
264 .foreground_platform
265 .on_become_active(Box::new(move || callback(&mut *cx.borrow_mut())));
266 self
267 }
268
269 pub fn on_resign_active<F>(self, mut callback: F) -> Self
270 where
271 F: 'static + FnMut(&mut MutableAppContext),
272 {
273 let cx = self.0.clone();
274 self.0
275 .borrow_mut()
276 .foreground_platform
277 .on_resign_active(Box::new(move || callback(&mut *cx.borrow_mut())));
278 self
279 }
280
281 pub fn on_quit<F>(&mut self, mut callback: F) -> &mut Self
282 where
283 F: 'static + FnMut(&mut MutableAppContext),
284 {
285 let cx = self.0.clone();
286 self.0
287 .borrow_mut()
288 .foreground_platform
289 .on_quit(Box::new(move || callback(&mut *cx.borrow_mut())));
290 self
291 }
292
293 pub fn on_event<F>(&mut self, mut callback: F) -> &mut Self
294 where
295 F: 'static + FnMut(Event, &mut MutableAppContext) -> bool,
296 {
297 let cx = self.0.clone();
298 self.0
299 .borrow_mut()
300 .foreground_platform
301 .on_event(Box::new(move |event| {
302 callback(event, &mut *cx.borrow_mut())
303 }));
304 self
305 }
306
307 pub fn on_open_urls<F>(&mut self, mut callback: F) -> &mut Self
308 where
309 F: 'static + FnMut(Vec<String>, &mut MutableAppContext),
310 {
311 let cx = self.0.clone();
312 self.0
313 .borrow_mut()
314 .foreground_platform
315 .on_open_urls(Box::new(move |paths| {
316 callback(paths, &mut *cx.borrow_mut())
317 }));
318 self
319 }
320
321 pub fn run<F>(self, on_finish_launching: F)
322 where
323 F: 'static + FnOnce(&mut MutableAppContext),
324 {
325 let platform = self.0.borrow().foreground_platform.clone();
326 platform.run(Box::new(move || {
327 let mut cx = self.0.borrow_mut();
328 let cx = &mut *cx;
329 crate::views::init(cx);
330 on_finish_launching(cx);
331 }))
332 }
333
334 pub fn platform(&self) -> Arc<dyn Platform> {
335 self.0.borrow().platform()
336 }
337
338 pub fn font_cache(&self) -> Arc<FontCache> {
339 self.0.borrow().cx.font_cache.clone()
340 }
341
342 fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
343 let mut state = self.0.borrow_mut();
344 let result = state.update(callback);
345 state.pending_notifications.clear();
346 result
347 }
348}
349
350impl WindowInputHandler {
351 fn read_focused_view<T, F>(&self, f: F) -> Option<T>
352 where
353 F: FnOnce(&dyn AnyView, &AppContext) -> T,
354 {
355 // Input-related application hooks are sometimes called by the OS during
356 // a call to a window-manipulation API, like prompting the user for file
357 // paths. In that case, the AppContext will already be borrowed, so any
358 // InputHandler methods need to fail gracefully.
359 //
360 // See https://github.com/zed-industries/feedback/issues/444
361 let app = self.app.try_borrow().ok()?;
362
363 let view_id = app.focused_view_id(self.window_id)?;
364 let view = app.cx.views.get(&(self.window_id, view_id))?;
365 let result = f(view.as_ref(), &app);
366 Some(result)
367 }
368
369 fn update_focused_view<T, F>(&mut self, f: F) -> Option<T>
370 where
371 F: FnOnce(usize, usize, &mut dyn AnyView, &mut MutableAppContext) -> T,
372 {
373 let mut app = self.app.try_borrow_mut().ok()?;
374 app.update(|app| {
375 let view_id = app.focused_view_id(self.window_id)?;
376 let mut view = app.cx.views.remove(&(self.window_id, view_id))?;
377 let result = f(self.window_id, view_id, view.as_mut(), &mut *app);
378 app.cx.views.insert((self.window_id, view_id), view);
379 Some(result)
380 })
381 }
382}
383
384impl InputHandler for WindowInputHandler {
385 fn text_for_range(&self, range: Range<usize>) -> Option<String> {
386 self.read_focused_view(|view, cx| view.text_for_range(range.clone(), cx))
387 .flatten()
388 }
389
390 fn selected_text_range(&self) -> Option<Range<usize>> {
391 self.read_focused_view(|view, cx| view.selected_text_range(cx))
392 .flatten()
393 }
394
395 fn replace_text_in_range(&mut self, range: Option<Range<usize>>, text: &str) {
396 self.update_focused_view(|window_id, view_id, view, cx| {
397 view.replace_text_in_range(range, text, cx, window_id, view_id);
398 });
399 }
400
401 fn marked_text_range(&self) -> Option<Range<usize>> {
402 self.read_focused_view(|view, cx| view.marked_text_range(cx))
403 .flatten()
404 }
405
406 fn unmark_text(&mut self) {
407 self.update_focused_view(|window_id, view_id, view, cx| {
408 view.unmark_text(cx, window_id, view_id);
409 });
410 }
411
412 fn replace_and_mark_text_in_range(
413 &mut self,
414 range: Option<Range<usize>>,
415 new_text: &str,
416 new_selected_range: Option<Range<usize>>,
417 ) {
418 self.update_focused_view(|window_id, view_id, view, cx| {
419 view.replace_and_mark_text_in_range(
420 range,
421 new_text,
422 new_selected_range,
423 cx,
424 window_id,
425 view_id,
426 );
427 });
428 }
429
430 fn rect_for_range(&self, range_utf16: Range<usize>) -> Option<RectF> {
431 let app = self.app.borrow();
432 let (presenter, _) = app.presenters_and_platform_windows.get(&self.window_id)?;
433 let presenter = presenter.borrow();
434 presenter.rect_for_text_range(range_utf16, &app)
435 }
436}
437
438impl AsyncAppContext {
439 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
440 where
441 F: FnOnce(AsyncAppContext) -> Fut,
442 Fut: 'static + Future<Output = T>,
443 T: 'static,
444 {
445 self.0.borrow().foreground.spawn(f(self.clone()))
446 }
447
448 pub fn read<T, F: FnOnce(&AppContext) -> T>(&self, callback: F) -> T {
449 callback(self.0.borrow().as_ref())
450 }
451
452 pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
453 self.0.borrow_mut().update(callback)
454 }
455
456 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
457 where
458 T: Entity,
459 F: FnOnce(&mut ModelContext<T>) -> T,
460 {
461 self.update(|cx| cx.add_model(build_model))
462 }
463
464 pub fn add_window<T, F>(
465 &mut self,
466 window_options: WindowOptions,
467 build_root_view: F,
468 ) -> (usize, ViewHandle<T>)
469 where
470 T: View,
471 F: FnOnce(&mut ViewContext<T>) -> T,
472 {
473 self.update(|cx| cx.add_window(window_options, build_root_view))
474 }
475
476 pub fn remove_window(&mut self, window_id: usize) {
477 self.update(|cx| cx.remove_window(window_id))
478 }
479
480 pub fn activate_window(&mut self, window_id: usize) {
481 self.update(|cx| cx.activate_window(window_id))
482 }
483
484 pub fn prompt(
485 &mut self,
486 window_id: usize,
487 level: PromptLevel,
488 msg: &str,
489 answers: &[&str],
490 ) -> oneshot::Receiver<usize> {
491 self.update(|cx| cx.prompt(window_id, level, msg, answers))
492 }
493
494 pub fn platform(&self) -> Arc<dyn Platform> {
495 self.0.borrow().platform()
496 }
497
498 pub fn foreground(&self) -> Rc<executor::Foreground> {
499 self.0.borrow().foreground.clone()
500 }
501
502 pub fn background(&self) -> Arc<executor::Background> {
503 self.0.borrow().cx.background.clone()
504 }
505}
506
507impl UpdateModel for AsyncAppContext {
508 fn update_model<E: Entity, O>(
509 &mut self,
510 handle: &ModelHandle<E>,
511 update: &mut dyn FnMut(&mut E, &mut ModelContext<E>) -> O,
512 ) -> O {
513 self.0.borrow_mut().update_model(handle, update)
514 }
515}
516
517impl UpgradeModelHandle for AsyncAppContext {
518 fn upgrade_model_handle<T: Entity>(
519 &self,
520 handle: &WeakModelHandle<T>,
521 ) -> Option<ModelHandle<T>> {
522 self.0.borrow().upgrade_model_handle(handle)
523 }
524
525 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
526 self.0.borrow().model_handle_is_upgradable(handle)
527 }
528
529 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
530 self.0.borrow().upgrade_any_model_handle(handle)
531 }
532}
533
534impl UpgradeViewHandle for AsyncAppContext {
535 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
536 self.0.borrow_mut().upgrade_view_handle(handle)
537 }
538
539 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
540 self.0.borrow_mut().upgrade_any_view_handle(handle)
541 }
542}
543
544impl ReadModelWith for AsyncAppContext {
545 fn read_model_with<E: Entity, T>(
546 &self,
547 handle: &ModelHandle<E>,
548 read: &mut dyn FnMut(&E, &AppContext) -> T,
549 ) -> T {
550 let cx = self.0.borrow();
551 let cx = cx.as_ref();
552 read(handle.read(cx), cx)
553 }
554}
555
556impl UpdateView for AsyncAppContext {
557 fn update_view<T, S>(
558 &mut self,
559 handle: &ViewHandle<T>,
560 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
561 ) -> S
562 where
563 T: View,
564 {
565 self.0.borrow_mut().update_view(handle, update)
566 }
567}
568
569impl ReadViewWith for AsyncAppContext {
570 fn read_view_with<V, T>(
571 &self,
572 handle: &ViewHandle<V>,
573 read: &mut dyn FnMut(&V, &AppContext) -> T,
574 ) -> T
575 where
576 V: View,
577 {
578 let cx = self.0.borrow();
579 let cx = cx.as_ref();
580 read(handle.read(cx), cx)
581 }
582}
583
584type ActionCallback =
585 dyn FnMut(&mut dyn AnyView, &dyn Action, &mut MutableAppContext, usize, usize);
586type GlobalActionCallback = dyn FnMut(&dyn Action, &mut MutableAppContext);
587
588type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext) -> bool>;
589type GlobalSubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
590type ObservationCallback = Box<dyn FnMut(&mut MutableAppContext) -> bool>;
591type FocusObservationCallback = Box<dyn FnMut(bool, &mut MutableAppContext) -> bool>;
592type GlobalObservationCallback = Box<dyn FnMut(&mut MutableAppContext)>;
593type ReleaseObservationCallback = Box<dyn FnOnce(&dyn Any, &mut MutableAppContext)>;
594type ActionObservationCallback = Box<dyn FnMut(TypeId, &mut MutableAppContext)>;
595type WindowActivationCallback = Box<dyn FnMut(bool, &mut MutableAppContext) -> bool>;
596type WindowFullscreenCallback = Box<dyn FnMut(bool, &mut MutableAppContext) -> bool>;
597type KeystrokeCallback = Box<
598 dyn FnMut(&Keystroke, &MatchResult, Option<&Box<dyn Action>>, &mut MutableAppContext) -> bool,
599>;
600type DeserializeActionCallback = fn(json: &str) -> anyhow::Result<Box<dyn Action>>;
601type WindowShouldCloseSubscriptionCallback = Box<dyn FnMut(&mut MutableAppContext) -> bool>;
602
603pub struct MutableAppContext {
604 weak_self: Option<rc::Weak<RefCell<Self>>>,
605 foreground_platform: Rc<dyn platform::ForegroundPlatform>,
606 assets: Arc<AssetCache>,
607 cx: AppContext,
608 action_deserializers: HashMap<&'static str, (TypeId, DeserializeActionCallback)>,
609 capture_actions: HashMap<TypeId, HashMap<TypeId, Vec<Box<ActionCallback>>>>,
610 actions: HashMap<TypeId, HashMap<TypeId, Vec<Box<ActionCallback>>>>,
611 global_actions: HashMap<TypeId, Box<GlobalActionCallback>>,
612 keystroke_matcher: keymap::Matcher,
613 next_entity_id: usize,
614 next_window_id: usize,
615 next_subscription_id: usize,
616 frame_count: usize,
617
618 focus_observations: CallbackCollection<usize, FocusObservationCallback>,
619 global_subscriptions: CallbackCollection<TypeId, GlobalSubscriptionCallback>,
620 global_observations: CallbackCollection<TypeId, GlobalObservationCallback>,
621 subscriptions: CallbackCollection<usize, SubscriptionCallback>,
622 observations: CallbackCollection<usize, ObservationCallback>,
623 window_activation_observations: CallbackCollection<usize, WindowActivationCallback>,
624 window_fullscreen_observations: CallbackCollection<usize, WindowFullscreenCallback>,
625 keystroke_observations: CallbackCollection<usize, KeystrokeCallback>,
626
627 release_observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>,
628 action_dispatch_observations: Arc<Mutex<BTreeMap<usize, ActionObservationCallback>>>,
629
630 #[allow(clippy::type_complexity)]
631 presenters_and_platform_windows:
632 HashMap<usize, (Rc<RefCell<Presenter>>, Box<dyn platform::Window>)>,
633 foreground: Rc<executor::Foreground>,
634 pending_effects: VecDeque<Effect>,
635 pending_notifications: HashSet<usize>,
636 pending_global_notifications: HashSet<TypeId>,
637 pending_flushes: usize,
638 flushing_effects: bool,
639 halt_action_dispatch: bool,
640}
641
642impl MutableAppContext {
643 fn new(
644 foreground: Rc<executor::Foreground>,
645 background: Arc<executor::Background>,
646 platform: Arc<dyn platform::Platform>,
647 foreground_platform: Rc<dyn platform::ForegroundPlatform>,
648 font_cache: Arc<FontCache>,
649 ref_counts: RefCounts,
650 asset_source: impl AssetSource,
651 ) -> Self {
652 Self {
653 weak_self: None,
654 foreground_platform,
655 assets: Arc::new(AssetCache::new(asset_source)),
656 cx: AppContext {
657 models: Default::default(),
658 views: Default::default(),
659 parents: Default::default(),
660 windows: Default::default(),
661 globals: Default::default(),
662 element_states: Default::default(),
663 ref_counts: Arc::new(Mutex::new(ref_counts)),
664 background,
665 font_cache,
666 platform,
667 },
668 action_deserializers: Default::default(),
669 capture_actions: Default::default(),
670 actions: Default::default(),
671 global_actions: Default::default(),
672 keystroke_matcher: keymap::Matcher::default(),
673 next_entity_id: 0,
674 next_window_id: 0,
675 next_subscription_id: 0,
676 frame_count: 0,
677 subscriptions: Default::default(),
678 global_subscriptions: Default::default(),
679 observations: Default::default(),
680 focus_observations: Default::default(),
681 release_observations: Default::default(),
682 global_observations: Default::default(),
683 window_activation_observations: Default::default(),
684 window_fullscreen_observations: Default::default(),
685 keystroke_observations: Default::default(),
686 action_dispatch_observations: Default::default(),
687 presenters_and_platform_windows: Default::default(),
688 foreground,
689 pending_effects: VecDeque::new(),
690 pending_notifications: Default::default(),
691 pending_global_notifications: Default::default(),
692 pending_flushes: 0,
693 flushing_effects: false,
694 halt_action_dispatch: false,
695 }
696 }
697
698 pub fn upgrade(&self) -> App {
699 App(self.weak_self.as_ref().unwrap().upgrade().unwrap())
700 }
701
702 pub fn quit(&mut self) {
703 let mut futures = Vec::new();
704 for model_id in self.cx.models.keys().copied().collect::<Vec<_>>() {
705 let mut model = self.cx.models.remove(&model_id).unwrap();
706 futures.extend(model.app_will_quit(self));
707 self.cx.models.insert(model_id, model);
708 }
709
710 for view_id in self.cx.views.keys().copied().collect::<Vec<_>>() {
711 let mut view = self.cx.views.remove(&view_id).unwrap();
712 futures.extend(view.app_will_quit(self));
713 self.cx.views.insert(view_id, view);
714 }
715
716 self.remove_all_windows();
717
718 let futures = futures::future::join_all(futures);
719 if self
720 .background
721 .block_with_timeout(Duration::from_millis(100), futures)
722 .is_err()
723 {
724 log::error!("timed out waiting on app_will_quit");
725 }
726 }
727
728 pub fn remove_all_windows(&mut self) {
729 for (window_id, _) in self.cx.windows.drain() {
730 self.presenters_and_platform_windows.remove(&window_id);
731 }
732 self.flush_effects();
733 }
734
735 pub fn platform(&self) -> Arc<dyn platform::Platform> {
736 self.cx.platform.clone()
737 }
738
739 pub fn font_cache(&self) -> &Arc<FontCache> {
740 &self.cx.font_cache
741 }
742
743 pub fn foreground(&self) -> &Rc<executor::Foreground> {
744 &self.foreground
745 }
746
747 pub fn background(&self) -> &Arc<executor::Background> {
748 &self.cx.background
749 }
750
751 pub fn debug_elements(&self, window_id: usize) -> Option<crate::json::Value> {
752 self.presenters_and_platform_windows
753 .get(&window_id)
754 .and_then(|(presenter, _)| presenter.borrow().debug_elements(self))
755 }
756
757 pub fn deserialize_action(
758 &self,
759 name: &str,
760 argument: Option<&str>,
761 ) -> Result<Box<dyn Action>> {
762 let callback = self
763 .action_deserializers
764 .get(name)
765 .ok_or_else(|| anyhow!("unknown action {}", name))?
766 .1;
767 callback(argument.unwrap_or("{}"))
768 .with_context(|| format!("invalid data for action {}", name))
769 }
770
771 pub fn add_action<A, V, F, R>(&mut self, handler: F)
772 where
773 A: Action,
774 V: View,
775 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>) -> R,
776 {
777 self.add_action_internal(handler, false)
778 }
779
780 pub fn capture_action<A, V, F>(&mut self, handler: F)
781 where
782 A: Action,
783 V: View,
784 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>),
785 {
786 self.add_action_internal(handler, true)
787 }
788
789 fn add_action_internal<A, V, F, R>(&mut self, mut handler: F, capture: bool)
790 where
791 A: Action,
792 V: View,
793 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>) -> R,
794 {
795 let handler = Box::new(
796 move |view: &mut dyn AnyView,
797 action: &dyn Action,
798 cx: &mut MutableAppContext,
799 window_id: usize,
800 view_id: usize| {
801 let action = action.as_any().downcast_ref().unwrap();
802 let mut cx = ViewContext::new(cx, window_id, view_id);
803 handler(
804 view.as_any_mut()
805 .downcast_mut()
806 .expect("downcast is type safe"),
807 action,
808 &mut cx,
809 );
810 },
811 );
812
813 self.action_deserializers
814 .entry(A::qualified_name())
815 .or_insert((TypeId::of::<A>(), A::from_json_str));
816
817 let actions = if capture {
818 &mut self.capture_actions
819 } else {
820 &mut self.actions
821 };
822
823 actions
824 .entry(TypeId::of::<V>())
825 .or_default()
826 .entry(TypeId::of::<A>())
827 .or_default()
828 .push(handler);
829 }
830
831 pub fn add_async_action<A, V, F>(&mut self, mut handler: F)
832 where
833 A: Action,
834 V: View,
835 F: 'static + FnMut(&mut V, &A, &mut ViewContext<V>) -> Option<Task<Result<()>>>,
836 {
837 self.add_action(move |view, action, cx| {
838 if let Some(task) = handler(view, action, cx) {
839 task.detach_and_log_err(cx);
840 }
841 })
842 }
843
844 pub fn add_global_action<A, F>(&mut self, mut handler: F)
845 where
846 A: Action,
847 F: 'static + FnMut(&A, &mut MutableAppContext),
848 {
849 let handler = Box::new(move |action: &dyn Action, cx: &mut MutableAppContext| {
850 let action = action.as_any().downcast_ref().unwrap();
851 handler(action, cx);
852 });
853
854 self.action_deserializers
855 .entry(A::qualified_name())
856 .or_insert((TypeId::of::<A>(), A::from_json_str));
857
858 if self
859 .global_actions
860 .insert(TypeId::of::<A>(), handler)
861 .is_some()
862 {
863 panic!(
864 "registered multiple global handlers for {}",
865 type_name::<A>()
866 );
867 }
868 }
869
870 pub fn window_ids(&self) -> impl Iterator<Item = usize> + '_ {
871 self.cx.windows.keys().cloned()
872 }
873
874 pub fn activate_window(&self, window_id: usize) {
875 if let Some((_, window)) = self.presenters_and_platform_windows.get(&window_id) {
876 window.activate()
877 }
878 }
879
880 pub fn root_view<T: View>(&self, window_id: usize) -> Option<ViewHandle<T>> {
881 self.cx
882 .windows
883 .get(&window_id)
884 .and_then(|window| window.root_view.clone().downcast::<T>())
885 }
886
887 pub fn window_is_active(&self, window_id: usize) -> bool {
888 self.cx
889 .windows
890 .get(&window_id)
891 .map_or(false, |window| window.is_active)
892 }
893
894 pub fn window_is_fullscreen(&self, window_id: usize) -> bool {
895 self.cx
896 .windows
897 .get(&window_id)
898 .map_or(false, |window| window.is_fullscreen)
899 }
900
901 pub fn window_bounds(&self, window_id: usize) -> RectF {
902 self.presenters_and_platform_windows[&window_id].1.bounds()
903 }
904
905 pub fn render_view(&mut self, params: RenderParams) -> Result<ElementBox> {
906 let window_id = params.window_id;
907 let view_id = params.view_id;
908 let mut view = self
909 .cx
910 .views
911 .remove(&(window_id, view_id))
912 .ok_or_else(|| anyhow!("view not found"))?;
913 let element = view.render(params, self);
914 self.cx.views.insert((window_id, view_id), view);
915 Ok(element)
916 }
917
918 pub fn render_views(
919 &mut self,
920 window_id: usize,
921 titlebar_height: f32,
922 appearance: Appearance,
923 ) -> HashMap<usize, ElementBox> {
924 self.start_frame();
925 #[allow(clippy::needless_collect)]
926 let view_ids = self
927 .views
928 .keys()
929 .filter_map(|(win_id, view_id)| {
930 if *win_id == window_id {
931 Some(*view_id)
932 } else {
933 None
934 }
935 })
936 .collect::<Vec<_>>();
937
938 view_ids
939 .into_iter()
940 .map(|view_id| {
941 (
942 view_id,
943 self.render_view(RenderParams {
944 window_id,
945 view_id,
946 titlebar_height,
947 hovered_region_ids: Default::default(),
948 clicked_region_ids: None,
949 refreshing: false,
950 appearance,
951 })
952 .unwrap(),
953 )
954 })
955 .collect()
956 }
957
958 pub(crate) fn start_frame(&mut self) {
959 self.frame_count += 1;
960 }
961
962 pub fn update<T, F: FnOnce(&mut Self) -> T>(&mut self, callback: F) -> T {
963 self.pending_flushes += 1;
964 let result = callback(self);
965 self.flush_effects();
966 result
967 }
968
969 pub fn set_menus(&mut self, menus: Vec<Menu>) {
970 self.foreground_platform
971 .set_menus(menus, &self.keystroke_matcher);
972 }
973
974 fn show_character_palette(&self, window_id: usize) {
975 let (_, window) = &self.presenters_and_platform_windows[&window_id];
976 window.show_character_palette();
977 }
978
979 pub fn minimize_window(&self, window_id: usize) {
980 let (_, window) = &self.presenters_and_platform_windows[&window_id];
981 window.minimize();
982 }
983
984 pub fn zoom_window(&self, window_id: usize) {
985 let (_, window) = &self.presenters_and_platform_windows[&window_id];
986 window.zoom();
987 }
988
989 pub fn toggle_window_full_screen(&self, window_id: usize) {
990 let (_, window) = &self.presenters_and_platform_windows[&window_id];
991 window.toggle_full_screen();
992 }
993
994 fn prompt(
995 &self,
996 window_id: usize,
997 level: PromptLevel,
998 msg: &str,
999 answers: &[&str],
1000 ) -> oneshot::Receiver<usize> {
1001 let (_, window) = &self.presenters_and_platform_windows[&window_id];
1002 window.prompt(level, msg, answers)
1003 }
1004
1005 pub fn prompt_for_paths(
1006 &self,
1007 options: PathPromptOptions,
1008 ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
1009 self.foreground_platform.prompt_for_paths(options)
1010 }
1011
1012 pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
1013 self.foreground_platform.prompt_for_new_path(directory)
1014 }
1015
1016 pub fn emit_global<E: Any>(&mut self, payload: E) {
1017 self.pending_effects.push_back(Effect::GlobalEvent {
1018 payload: Box::new(payload),
1019 });
1020 }
1021
1022 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1023 where
1024 E: Entity,
1025 E::Event: 'static,
1026 H: Handle<E>,
1027 F: 'static + FnMut(H, &E::Event, &mut Self),
1028 {
1029 self.subscribe_internal(handle, move |handle, event, cx| {
1030 callback(handle, event, cx);
1031 true
1032 })
1033 }
1034
1035 pub fn subscribe_global<E, F>(&mut self, mut callback: F) -> Subscription
1036 where
1037 E: Any,
1038 F: 'static + FnMut(&E, &mut Self),
1039 {
1040 let subscription_id = post_inc(&mut self.next_subscription_id);
1041 let type_id = TypeId::of::<E>();
1042 self.pending_effects.push_back(Effect::GlobalSubscription {
1043 type_id,
1044 subscription_id,
1045 callback: Box::new(move |payload, cx| {
1046 let payload = payload.downcast_ref().expect("downcast is type safe");
1047 callback(payload, cx)
1048 }),
1049 });
1050
1051 Subscription::GlobalSubscription {
1052 id: subscription_id,
1053 type_id,
1054 subscriptions: Some(self.global_subscriptions.downgrade()),
1055 }
1056 }
1057
1058 pub fn observe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1059 where
1060 E: Entity,
1061 E::Event: 'static,
1062 H: Handle<E>,
1063 F: 'static + FnMut(H, &mut Self),
1064 {
1065 self.observe_internal(handle, move |handle, cx| {
1066 callback(handle, cx);
1067 true
1068 })
1069 }
1070
1071 pub fn subscribe_internal<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1072 where
1073 E: Entity,
1074 E::Event: 'static,
1075 H: Handle<E>,
1076 F: 'static + FnMut(H, &E::Event, &mut Self) -> bool,
1077 {
1078 let subscription_id = post_inc(&mut self.next_subscription_id);
1079 let emitter = handle.downgrade();
1080 self.pending_effects.push_back(Effect::Subscription {
1081 entity_id: handle.id(),
1082 subscription_id,
1083 callback: Box::new(move |payload, cx| {
1084 if let Some(emitter) = H::upgrade_from(&emitter, cx.as_ref()) {
1085 let payload = payload.downcast_ref().expect("downcast is type safe");
1086 callback(emitter, payload, cx)
1087 } else {
1088 false
1089 }
1090 }),
1091 });
1092 Subscription::Subscription {
1093 id: subscription_id,
1094 entity_id: handle.id(),
1095 subscriptions: Some(self.subscriptions.downgrade()),
1096 }
1097 }
1098
1099 fn observe_internal<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
1100 where
1101 E: Entity,
1102 E::Event: 'static,
1103 H: Handle<E>,
1104 F: 'static + FnMut(H, &mut Self) -> bool,
1105 {
1106 let subscription_id = post_inc(&mut self.next_subscription_id);
1107 let observed = handle.downgrade();
1108 let entity_id = handle.id();
1109 self.pending_effects.push_back(Effect::Observation {
1110 entity_id,
1111 subscription_id,
1112 callback: Box::new(move |cx| {
1113 if let Some(observed) = H::upgrade_from(&observed, cx) {
1114 callback(observed, cx)
1115 } else {
1116 false
1117 }
1118 }),
1119 });
1120 Subscription::Observation {
1121 id: subscription_id,
1122 entity_id,
1123 observations: Some(self.observations.downgrade()),
1124 }
1125 }
1126
1127 fn observe_focus<F, V>(&mut self, handle: &ViewHandle<V>, mut callback: F) -> Subscription
1128 where
1129 F: 'static + FnMut(ViewHandle<V>, bool, &mut MutableAppContext) -> bool,
1130 V: View,
1131 {
1132 let subscription_id = post_inc(&mut self.next_subscription_id);
1133 let observed = handle.downgrade();
1134 let view_id = handle.id();
1135
1136 self.pending_effects.push_back(Effect::FocusObservation {
1137 view_id,
1138 subscription_id,
1139 callback: Box::new(move |focused, cx| {
1140 if let Some(observed) = observed.upgrade(cx) {
1141 callback(observed, focused, cx)
1142 } else {
1143 false
1144 }
1145 }),
1146 });
1147
1148 Subscription::FocusObservation {
1149 id: subscription_id,
1150 view_id,
1151 observations: Some(self.focus_observations.downgrade()),
1152 }
1153 }
1154
1155 pub fn observe_global<G, F>(&mut self, mut observe: F) -> Subscription
1156 where
1157 G: Any,
1158 F: 'static + FnMut(&mut MutableAppContext),
1159 {
1160 let type_id = TypeId::of::<G>();
1161 let id = post_inc(&mut self.next_subscription_id);
1162
1163 self.global_observations.add_callback(
1164 type_id,
1165 id,
1166 Box::new(move |cx: &mut MutableAppContext| observe(cx)),
1167 );
1168
1169 Subscription::GlobalObservation {
1170 id,
1171 type_id,
1172 observations: Some(self.global_observations.downgrade()),
1173 }
1174 }
1175
1176 pub fn observe_default_global<G, F>(&mut self, observe: F) -> Subscription
1177 where
1178 G: Any + Default,
1179 F: 'static + FnMut(&mut MutableAppContext),
1180 {
1181 if !self.has_global::<G>() {
1182 self.set_global(G::default());
1183 }
1184 self.observe_global::<G, F>(observe)
1185 }
1186
1187 pub fn observe_release<E, H, F>(&mut self, handle: &H, callback: F) -> Subscription
1188 where
1189 E: Entity,
1190 E::Event: 'static,
1191 H: Handle<E>,
1192 F: 'static + FnOnce(&E, &mut Self),
1193 {
1194 let id = post_inc(&mut self.next_subscription_id);
1195 self.release_observations
1196 .lock()
1197 .entry(handle.id())
1198 .or_default()
1199 .insert(
1200 id,
1201 Box::new(move |released, cx| {
1202 let released = released.downcast_ref().unwrap();
1203 callback(released, cx)
1204 }),
1205 );
1206 Subscription::ReleaseObservation {
1207 id,
1208 entity_id: handle.id(),
1209 observations: Some(Arc::downgrade(&self.release_observations)),
1210 }
1211 }
1212
1213 pub fn observe_actions<F>(&mut self, callback: F) -> Subscription
1214 where
1215 F: 'static + FnMut(TypeId, &mut MutableAppContext),
1216 {
1217 let id = post_inc(&mut self.next_subscription_id);
1218 self.action_dispatch_observations
1219 .lock()
1220 .insert(id, Box::new(callback));
1221 Subscription::ActionObservation {
1222 id,
1223 observations: Some(Arc::downgrade(&self.action_dispatch_observations)),
1224 }
1225 }
1226
1227 fn observe_window_activation<F>(&mut self, window_id: usize, callback: F) -> Subscription
1228 where
1229 F: 'static + FnMut(bool, &mut MutableAppContext) -> bool,
1230 {
1231 let subscription_id = post_inc(&mut self.next_subscription_id);
1232 self.pending_effects
1233 .push_back(Effect::WindowActivationObservation {
1234 window_id,
1235 subscription_id,
1236 callback: Box::new(callback),
1237 });
1238 Subscription::WindowActivationObservation {
1239 id: subscription_id,
1240 window_id,
1241 observations: Some(self.window_activation_observations.downgrade()),
1242 }
1243 }
1244
1245 fn observe_fullscreen<F>(&mut self, window_id: usize, callback: F) -> Subscription
1246 where
1247 F: 'static + FnMut(bool, &mut MutableAppContext) -> bool,
1248 {
1249 let subscription_id = post_inc(&mut self.next_subscription_id);
1250 self.pending_effects
1251 .push_back(Effect::WindowFullscreenObservation {
1252 window_id,
1253 subscription_id,
1254 callback: Box::new(callback),
1255 });
1256 Subscription::WindowFullscreenObservation {
1257 id: subscription_id,
1258 window_id,
1259 observations: Some(self.window_activation_observations.downgrade()),
1260 }
1261 }
1262
1263 pub fn observe_keystrokes<F>(&mut self, window_id: usize, callback: F) -> Subscription
1264 where
1265 F: 'static
1266 + FnMut(
1267 &Keystroke,
1268 &MatchResult,
1269 Option<&Box<dyn Action>>,
1270 &mut MutableAppContext,
1271 ) -> bool,
1272 {
1273 let subscription_id = post_inc(&mut self.next_subscription_id);
1274 self.keystroke_observations
1275 .add_callback(window_id, subscription_id, Box::new(callback));
1276
1277 Subscription::KeystrokeObservation {
1278 id: subscription_id,
1279 window_id,
1280 observations: Some(self.keystroke_observations.downgrade()),
1281 }
1282 }
1283
1284 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut MutableAppContext)) {
1285 self.pending_effects.push_back(Effect::Deferred {
1286 callback: Box::new(callback),
1287 after_window_update: false,
1288 })
1289 }
1290
1291 pub fn after_window_update(&mut self, callback: impl 'static + FnOnce(&mut MutableAppContext)) {
1292 self.pending_effects.push_back(Effect::Deferred {
1293 callback: Box::new(callback),
1294 after_window_update: true,
1295 })
1296 }
1297
1298 pub(crate) fn notify_model(&mut self, model_id: usize) {
1299 if self.pending_notifications.insert(model_id) {
1300 self.pending_effects
1301 .push_back(Effect::ModelNotification { model_id });
1302 }
1303 }
1304
1305 pub(crate) fn notify_view(&mut self, window_id: usize, view_id: usize) {
1306 if self.pending_notifications.insert(view_id) {
1307 self.pending_effects
1308 .push_back(Effect::ViewNotification { window_id, view_id });
1309 }
1310 }
1311
1312 pub(crate) fn notify_global(&mut self, type_id: TypeId) {
1313 if self.pending_global_notifications.insert(type_id) {
1314 self.pending_effects
1315 .push_back(Effect::GlobalNotification { type_id });
1316 }
1317 }
1318
1319 pub(crate) fn name_for_view(&self, window_id: usize, view_id: usize) -> Option<&str> {
1320 self.views
1321 .get(&(window_id, view_id))
1322 .map(|view| view.ui_name())
1323 }
1324
1325 pub fn all_action_names<'a>(&'a self) -> impl Iterator<Item = &'static str> + 'a {
1326 self.action_deserializers.keys().copied()
1327 }
1328
1329 pub fn available_actions(
1330 &self,
1331 window_id: usize,
1332 view_id: usize,
1333 ) -> impl Iterator<Item = (&'static str, Box<dyn Action>, SmallVec<[&Binding; 1]>)> {
1334 let mut action_types: HashSet<_> = self.global_actions.keys().copied().collect();
1335
1336 for view_id in self.ancestors(window_id, view_id) {
1337 if let Some(view) = self.views.get(&(window_id, view_id)) {
1338 let view_type = view.as_any().type_id();
1339 if let Some(actions) = self.actions.get(&view_type) {
1340 action_types.extend(actions.keys().copied());
1341 }
1342 }
1343 }
1344
1345 self.action_deserializers
1346 .iter()
1347 .filter_map(move |(name, (type_id, deserialize))| {
1348 if action_types.contains(type_id) {
1349 Some((
1350 *name,
1351 deserialize("{}").ok()?,
1352 self.keystroke_matcher
1353 .bindings_for_action_type(*type_id)
1354 .collect(),
1355 ))
1356 } else {
1357 None
1358 }
1359 })
1360 }
1361
1362 pub fn is_action_available(&self, action: &dyn Action) -> bool {
1363 let action_type = action.as_any().type_id();
1364 if let Some(window_id) = self.cx.platform.key_window_id() {
1365 if let Some(focused_view_id) = self.focused_view_id(window_id) {
1366 for view_id in self.ancestors(window_id, focused_view_id) {
1367 if let Some(view) = self.views.get(&(window_id, view_id)) {
1368 let view_type = view.as_any().type_id();
1369 if let Some(actions) = self.actions.get(&view_type) {
1370 if actions.contains_key(&action_type) {
1371 return true;
1372 }
1373 }
1374 }
1375 }
1376 }
1377 }
1378 self.global_actions.contains_key(&action_type)
1379 }
1380
1381 /// Return keystrokes that would dispatch the given action closest to the focused view, if there are any.
1382 pub(crate) fn keystrokes_for_action(
1383 &self,
1384 window_id: usize,
1385 dispatch_path: &[usize],
1386 action: &dyn Action,
1387 ) -> Option<SmallVec<[Keystroke; 2]>> {
1388 for view_id in dispatch_path.iter().rev() {
1389 let view = self
1390 .cx
1391 .views
1392 .get(&(window_id, *view_id))
1393 .expect("view in responder chain does not exist");
1394 let cx = view.keymap_context(self.as_ref());
1395 let keystrokes = self.keystroke_matcher.keystrokes_for_action(action, &cx);
1396 if keystrokes.is_some() {
1397 return keystrokes;
1398 }
1399 }
1400
1401 None
1402 }
1403
1404 // Traverses the parent tree. Walks down the tree toward the passed
1405 // view calling visit with true. Then walks back up the tree calling visit with false.
1406 // If `visit` returns false this function will immediately return.
1407 // Returns a bool indicating if the traversal was completed early.
1408 fn visit_dispatch_path(
1409 &mut self,
1410 window_id: usize,
1411 view_id: usize,
1412 mut visit: impl FnMut(usize, bool, &mut MutableAppContext) -> bool,
1413 ) -> bool {
1414 // List of view ids from the leaf to the root of the window
1415 let path = self.ancestors(window_id, view_id).collect::<Vec<_>>();
1416
1417 // Walk down from the root to the leaf calling visit with capture_phase = true
1418 for view_id in path.iter().rev() {
1419 if !visit(*view_id, true, self) {
1420 return false;
1421 }
1422 }
1423
1424 // Walk up from the leaf to the root calling visit with capture_phase = false
1425 for view_id in path.iter() {
1426 if !visit(*view_id, false, self) {
1427 return false;
1428 }
1429 }
1430
1431 true
1432 }
1433
1434 /// Returns an iterator over all of the view ids from the passed view up to the root of the window
1435 /// Includes the passed view itself
1436 fn ancestors(&self, window_id: usize, mut view_id: usize) -> impl Iterator<Item = usize> + '_ {
1437 std::iter::once(view_id)
1438 .into_iter()
1439 .chain(std::iter::from_fn(move || {
1440 if let Some(ParentId::View(parent_id)) = self.parents.get(&(window_id, view_id)) {
1441 view_id = *parent_id;
1442 Some(view_id)
1443 } else {
1444 None
1445 }
1446 }))
1447 }
1448
1449 fn actions_mut(
1450 &mut self,
1451 capture_phase: bool,
1452 ) -> &mut HashMap<TypeId, HashMap<TypeId, Vec<Box<ActionCallback>>>> {
1453 if capture_phase {
1454 &mut self.capture_actions
1455 } else {
1456 &mut self.actions
1457 }
1458 }
1459
1460 pub fn dispatch_global_action<A: Action>(&mut self, action: A) {
1461 self.dispatch_global_action_any(&action);
1462 }
1463
1464 fn dispatch_global_action_any(&mut self, action: &dyn Action) -> bool {
1465 self.update(|this| {
1466 if let Some((name, mut handler)) = this.global_actions.remove_entry(&action.id()) {
1467 handler(action, this);
1468 this.global_actions.insert(name, handler);
1469 true
1470 } else {
1471 false
1472 }
1473 })
1474 }
1475
1476 pub fn add_bindings<T: IntoIterator<Item = keymap::Binding>>(&mut self, bindings: T) {
1477 self.keystroke_matcher.add_bindings(bindings);
1478 }
1479
1480 pub fn clear_bindings(&mut self) {
1481 self.keystroke_matcher.clear_bindings();
1482 }
1483
1484 pub fn dispatch_key_down(&mut self, window_id: usize, event: &KeyDownEvent) -> bool {
1485 if let Some(focused_view_id) = self.focused_view_id(window_id) {
1486 for view_id in self
1487 .ancestors(window_id, focused_view_id)
1488 .collect::<Vec<_>>()
1489 {
1490 if let Some(mut view) = self.cx.views.remove(&(window_id, view_id)) {
1491 let handled = view.key_down(event, self, window_id, view_id);
1492 self.cx.views.insert((window_id, view_id), view);
1493 if handled {
1494 return true;
1495 }
1496 } else {
1497 log::error!("view {} does not exist", view_id)
1498 }
1499 }
1500 }
1501
1502 false
1503 }
1504
1505 pub fn dispatch_key_up(&mut self, window_id: usize, event: &KeyUpEvent) -> bool {
1506 if let Some(focused_view_id) = self.focused_view_id(window_id) {
1507 for view_id in self
1508 .ancestors(window_id, focused_view_id)
1509 .collect::<Vec<_>>()
1510 {
1511 if let Some(mut view) = self.cx.views.remove(&(window_id, view_id)) {
1512 let handled = view.key_up(event, self, window_id, view_id);
1513 self.cx.views.insert((window_id, view_id), view);
1514 if handled {
1515 return true;
1516 }
1517 } else {
1518 log::error!("view {} does not exist", view_id)
1519 }
1520 }
1521 }
1522
1523 false
1524 }
1525
1526 pub fn dispatch_modifiers_changed(
1527 &mut self,
1528 window_id: usize,
1529 event: &ModifiersChangedEvent,
1530 ) -> bool {
1531 if let Some(focused_view_id) = self.focused_view_id(window_id) {
1532 for view_id in self
1533 .ancestors(window_id, focused_view_id)
1534 .collect::<Vec<_>>()
1535 {
1536 if let Some(mut view) = self.cx.views.remove(&(window_id, view_id)) {
1537 let handled = view.modifiers_changed(event, self, window_id, view_id);
1538 self.cx.views.insert((window_id, view_id), view);
1539 if handled {
1540 return true;
1541 }
1542 } else {
1543 log::error!("view {} does not exist", view_id)
1544 }
1545 }
1546 }
1547
1548 false
1549 }
1550
1551 pub fn dispatch_keystroke(&mut self, window_id: usize, keystroke: &Keystroke) -> bool {
1552 if let Some(focused_view_id) = self.focused_view_id(window_id) {
1553 let dispatch_path = self
1554 .ancestors(window_id, focused_view_id)
1555 .map(|view_id| {
1556 (
1557 view_id,
1558 self.cx
1559 .views
1560 .get(&(window_id, view_id))
1561 .unwrap()
1562 .keymap_context(self.as_ref()),
1563 )
1564 })
1565 .collect();
1566
1567 let match_result = self
1568 .keystroke_matcher
1569 .push_keystroke(keystroke.clone(), dispatch_path);
1570 let mut handled_by = None;
1571
1572 let keystroke_handled = match &match_result {
1573 MatchResult::None => false,
1574 MatchResult::Pending => true,
1575 MatchResult::Matches(matches) => {
1576 for (view_id, action) in matches {
1577 if self.handle_dispatch_action_from_effect(
1578 window_id,
1579 Some(*view_id),
1580 action.as_ref(),
1581 ) {
1582 self.keystroke_matcher.clear_pending();
1583 handled_by = Some(action.boxed_clone());
1584 break;
1585 }
1586 }
1587 handled_by.is_some()
1588 }
1589 };
1590
1591 self.keystroke(
1592 window_id,
1593 keystroke.clone(),
1594 handled_by,
1595 match_result.clone(),
1596 );
1597 keystroke_handled
1598 } else {
1599 self.keystroke(window_id, keystroke.clone(), None, MatchResult::None);
1600 false
1601 }
1602 }
1603
1604 pub fn default_global<T: 'static + Default>(&mut self) -> &T {
1605 let type_id = TypeId::of::<T>();
1606 self.update(|this| {
1607 if let Entry::Vacant(entry) = this.cx.globals.entry(type_id) {
1608 entry.insert(Box::new(T::default()));
1609 this.notify_global(type_id);
1610 }
1611 });
1612 self.globals.get(&type_id).unwrap().downcast_ref().unwrap()
1613 }
1614
1615 pub fn set_global<T: 'static>(&mut self, state: T) {
1616 self.update(|this| {
1617 let type_id = TypeId::of::<T>();
1618 this.cx.globals.insert(type_id, Box::new(state));
1619 this.notify_global(type_id);
1620 });
1621 }
1622
1623 pub fn update_default_global<T, F, U>(&mut self, update: F) -> U
1624 where
1625 T: 'static + Default,
1626 F: FnOnce(&mut T, &mut MutableAppContext) -> U,
1627 {
1628 self.update(|this| {
1629 let type_id = TypeId::of::<T>();
1630 let mut state = this
1631 .cx
1632 .globals
1633 .remove(&type_id)
1634 .unwrap_or_else(|| Box::new(T::default()));
1635 let result = update(state.downcast_mut().unwrap(), this);
1636 this.cx.globals.insert(type_id, state);
1637 this.notify_global(type_id);
1638 result
1639 })
1640 }
1641
1642 pub fn update_global<T, F, U>(&mut self, update: F) -> U
1643 where
1644 T: 'static,
1645 F: FnOnce(&mut T, &mut MutableAppContext) -> U,
1646 {
1647 self.update(|this| {
1648 let type_id = TypeId::of::<T>();
1649 if let Some(mut state) = this.cx.globals.remove(&type_id) {
1650 let result = update(state.downcast_mut().unwrap(), this);
1651 this.cx.globals.insert(type_id, state);
1652 this.notify_global(type_id);
1653 result
1654 } else {
1655 panic!("No global added for {}", std::any::type_name::<T>());
1656 }
1657 })
1658 }
1659
1660 pub fn clear_globals(&mut self) {
1661 self.cx.globals.clear();
1662 }
1663
1664 pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
1665 where
1666 T: Entity,
1667 F: FnOnce(&mut ModelContext<T>) -> T,
1668 {
1669 self.update(|this| {
1670 let model_id = post_inc(&mut this.next_entity_id);
1671 let handle = ModelHandle::new(model_id, &this.cx.ref_counts);
1672 let mut cx = ModelContext::new(this, model_id);
1673 let model = build_model(&mut cx);
1674 this.cx.models.insert(model_id, Box::new(model));
1675 handle
1676 })
1677 }
1678
1679 pub fn add_window<T, F>(
1680 &mut self,
1681 window_options: WindowOptions,
1682 build_root_view: F,
1683 ) -> (usize, ViewHandle<T>)
1684 where
1685 T: View,
1686 F: FnOnce(&mut ViewContext<T>) -> T,
1687 {
1688 self.update(|this| {
1689 let window_id = post_inc(&mut this.next_window_id);
1690 let root_view = this
1691 .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
1692 .unwrap();
1693 this.cx.windows.insert(
1694 window_id,
1695 Window {
1696 root_view: root_view.clone().into(),
1697 focused_view_id: Some(root_view.id()),
1698 is_active: false,
1699 invalidation: None,
1700 is_fullscreen: false,
1701 },
1702 );
1703 root_view.update(this, |view, cx| view.focus_in(cx.handle().into(), cx));
1704
1705 let window =
1706 this.cx
1707 .platform
1708 .open_window(window_id, window_options, this.foreground.clone());
1709 this.register_platform_window(window_id, window);
1710
1711 (window_id, root_view)
1712 })
1713 }
1714
1715 pub fn add_status_bar_item<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>)
1716 where
1717 T: View,
1718 F: FnOnce(&mut ViewContext<T>) -> T,
1719 {
1720 self.update(|this| {
1721 let window_id = post_inc(&mut this.next_window_id);
1722 let root_view = this
1723 .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
1724 .unwrap();
1725 this.cx.windows.insert(
1726 window_id,
1727 Window {
1728 root_view: root_view.clone().into(),
1729 focused_view_id: Some(root_view.id()),
1730 is_active: false,
1731 invalidation: None,
1732 is_fullscreen: false,
1733 },
1734 );
1735 root_view.update(this, |view, cx| view.focus_in(cx.handle().into(), cx));
1736
1737 let status_item = this.cx.platform.add_status_item();
1738 this.register_platform_window(window_id, status_item);
1739
1740 (window_id, root_view)
1741 })
1742 }
1743
1744 pub fn remove_status_bar_item(&mut self, id: usize) {
1745 self.remove_window(id);
1746 }
1747
1748 fn register_platform_window(
1749 &mut self,
1750 window_id: usize,
1751 mut window: Box<dyn platform::Window>,
1752 ) {
1753 let presenter = Rc::new(RefCell::new(self.build_presenter(
1754 window_id,
1755 window.titlebar_height(),
1756 window.appearance(),
1757 )));
1758
1759 {
1760 let mut app = self.upgrade();
1761 let presenter = Rc::downgrade(&presenter);
1762
1763 window.on_event(Box::new(move |event| {
1764 app.update(|cx| {
1765 if let Some(presenter) = presenter.upgrade() {
1766 if let Event::KeyDown(KeyDownEvent { keystroke, .. }) = &event {
1767 if cx.dispatch_keystroke(window_id, keystroke) {
1768 return true;
1769 }
1770 }
1771
1772 presenter.borrow_mut().dispatch_event(event, false, cx)
1773 } else {
1774 false
1775 }
1776 })
1777 }));
1778 }
1779
1780 {
1781 let mut app = self.upgrade();
1782 window.on_active_status_change(Box::new(move |is_active| {
1783 app.update(|cx| cx.window_changed_active_status(window_id, is_active))
1784 }));
1785 }
1786
1787 {
1788 let mut app = self.upgrade();
1789 window.on_resize(Box::new(move || {
1790 app.update(|cx| cx.window_was_resized(window_id))
1791 }));
1792 }
1793
1794 {
1795 let mut app = self.upgrade();
1796 window.on_fullscreen(Box::new(move |is_fullscreen| {
1797 app.update(|cx| cx.window_was_fullscreen_changed(window_id, is_fullscreen))
1798 }));
1799 }
1800
1801 {
1802 let mut app = self.upgrade();
1803 window.on_close(Box::new(move || {
1804 app.update(|cx| cx.remove_window(window_id));
1805 }));
1806 }
1807
1808 {
1809 let mut app = self.upgrade();
1810 window.on_appearance_changed(Box::new(move || app.update(|cx| cx.refresh_windows())));
1811 }
1812
1813 window.set_input_handler(Box::new(WindowInputHandler {
1814 app: self.upgrade().0,
1815 window_id,
1816 }));
1817
1818 let scene = presenter.borrow_mut().build_scene(
1819 window.content_size(),
1820 window.scale_factor(),
1821 false,
1822 self,
1823 );
1824 window.present_scene(scene);
1825 self.presenters_and_platform_windows
1826 .insert(window_id, (presenter.clone(), window));
1827 }
1828
1829 pub fn replace_root_view<T, F>(&mut self, window_id: usize, build_root_view: F) -> ViewHandle<T>
1830 where
1831 T: View,
1832 F: FnOnce(&mut ViewContext<T>) -> T,
1833 {
1834 self.update(|this| {
1835 let root_view = this
1836 .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
1837 .unwrap();
1838 let window = this.cx.windows.get_mut(&window_id).unwrap();
1839 window.root_view = root_view.clone().into();
1840 window.focused_view_id = Some(root_view.id());
1841 root_view
1842 })
1843 }
1844
1845 pub fn remove_window(&mut self, window_id: usize) {
1846 self.cx.windows.remove(&window_id);
1847 self.presenters_and_platform_windows.remove(&window_id);
1848 self.flush_effects();
1849 }
1850
1851 pub fn build_presenter(
1852 &mut self,
1853 window_id: usize,
1854 titlebar_height: f32,
1855 appearance: Appearance,
1856 ) -> Presenter {
1857 Presenter::new(
1858 window_id,
1859 titlebar_height,
1860 appearance,
1861 self.cx.font_cache.clone(),
1862 TextLayoutCache::new(self.cx.platform.fonts()),
1863 self.assets.clone(),
1864 self,
1865 )
1866 }
1867
1868 pub fn add_view<T, F>(
1869 &mut self,
1870 parent_handle: impl Into<AnyViewHandle>,
1871 build_view: F,
1872 ) -> ViewHandle<T>
1873 where
1874 T: View,
1875 F: FnOnce(&mut ViewContext<T>) -> T,
1876 {
1877 let parent_handle = parent_handle.into();
1878 self.build_and_insert_view(
1879 parent_handle.window_id,
1880 ParentId::View(parent_handle.view_id),
1881 |cx| Some(build_view(cx)),
1882 )
1883 .unwrap()
1884 }
1885
1886 pub fn add_option_view<T, F>(
1887 &mut self,
1888 parent_handle: impl Into<AnyViewHandle>,
1889 build_view: F,
1890 ) -> Option<ViewHandle<T>>
1891 where
1892 T: View,
1893 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
1894 {
1895 let parent_handle = parent_handle.into();
1896 self.build_and_insert_view(
1897 parent_handle.window_id,
1898 ParentId::View(parent_handle.view_id),
1899 build_view,
1900 )
1901 }
1902
1903 pub(crate) fn build_and_insert_view<T, F>(
1904 &mut self,
1905 window_id: usize,
1906 parent_id: ParentId,
1907 build_view: F,
1908 ) -> Option<ViewHandle<T>>
1909 where
1910 T: View,
1911 F: FnOnce(&mut ViewContext<T>) -> Option<T>,
1912 {
1913 self.update(|this| {
1914 let view_id = post_inc(&mut this.next_entity_id);
1915 let mut cx = ViewContext::new(this, window_id, view_id);
1916 let handle = if let Some(view) = build_view(&mut cx) {
1917 this.cx.views.insert((window_id, view_id), Box::new(view));
1918 this.cx.parents.insert((window_id, view_id), parent_id);
1919 if let Some(window) = this.cx.windows.get_mut(&window_id) {
1920 window
1921 .invalidation
1922 .get_or_insert_with(Default::default)
1923 .updated
1924 .insert(view_id);
1925 }
1926 Some(ViewHandle::new(window_id, view_id, &this.cx.ref_counts))
1927 } else {
1928 None
1929 };
1930 handle
1931 })
1932 }
1933
1934 fn remove_dropped_entities(&mut self) {
1935 loop {
1936 let (dropped_models, dropped_views, dropped_element_states) =
1937 self.cx.ref_counts.lock().take_dropped();
1938 if dropped_models.is_empty()
1939 && dropped_views.is_empty()
1940 && dropped_element_states.is_empty()
1941 {
1942 break;
1943 }
1944
1945 for model_id in dropped_models {
1946 self.subscriptions.remove(model_id);
1947 self.observations.remove(model_id);
1948 let mut model = self.cx.models.remove(&model_id).unwrap();
1949 model.release(self);
1950 self.pending_effects
1951 .push_back(Effect::ModelRelease { model_id, model });
1952 }
1953
1954 for (window_id, view_id) in dropped_views {
1955 self.subscriptions.remove(view_id);
1956 self.observations.remove(view_id);
1957 let mut view = self.cx.views.remove(&(window_id, view_id)).unwrap();
1958 view.release(self);
1959 let change_focus_to = self.cx.windows.get_mut(&window_id).and_then(|window| {
1960 window
1961 .invalidation
1962 .get_or_insert_with(Default::default)
1963 .removed
1964 .push(view_id);
1965 if window.focused_view_id == Some(view_id) {
1966 Some(window.root_view.id())
1967 } else {
1968 None
1969 }
1970 });
1971 self.cx.parents.remove(&(window_id, view_id));
1972
1973 if let Some(view_id) = change_focus_to {
1974 self.handle_focus_effect(window_id, Some(view_id));
1975 }
1976
1977 self.pending_effects
1978 .push_back(Effect::ViewRelease { view_id, view });
1979 }
1980
1981 for key in dropped_element_states {
1982 self.cx.element_states.remove(&key);
1983 }
1984 }
1985 }
1986
1987 fn flush_effects(&mut self) {
1988 self.pending_flushes = self.pending_flushes.saturating_sub(1);
1989 let mut after_window_update_callbacks = Vec::new();
1990
1991 if !self.flushing_effects && self.pending_flushes == 0 {
1992 self.flushing_effects = true;
1993
1994 let mut refreshing = false;
1995 loop {
1996 if let Some(effect) = self.pending_effects.pop_front() {
1997 match effect {
1998 Effect::Subscription {
1999 entity_id,
2000 subscription_id,
2001 callback,
2002 } => self.subscriptions.add_or_remove_callback(
2003 entity_id,
2004 subscription_id,
2005 callback,
2006 ),
2007
2008 Effect::Event { entity_id, payload } => {
2009 let mut subscriptions = self.subscriptions.clone();
2010 subscriptions.emit_and_cleanup(entity_id, self, |callback, this| {
2011 callback(payload.as_ref(), this)
2012 })
2013 }
2014
2015 Effect::GlobalSubscription {
2016 type_id,
2017 subscription_id,
2018 callback,
2019 } => self.global_subscriptions.add_or_remove_callback(
2020 type_id,
2021 subscription_id,
2022 callback,
2023 ),
2024
2025 Effect::GlobalEvent { payload } => self.emit_global_event(payload),
2026
2027 Effect::Observation {
2028 entity_id,
2029 subscription_id,
2030 callback,
2031 } => self.observations.add_or_remove_callback(
2032 entity_id,
2033 subscription_id,
2034 callback,
2035 ),
2036
2037 Effect::ModelNotification { model_id } => {
2038 let mut observations = self.observations.clone();
2039 observations
2040 .emit_and_cleanup(model_id, self, |callback, this| callback(this));
2041 }
2042
2043 Effect::ViewNotification { window_id, view_id } => {
2044 self.handle_view_notification_effect(window_id, view_id)
2045 }
2046
2047 Effect::GlobalNotification { type_id } => {
2048 let mut subscriptions = self.global_observations.clone();
2049 subscriptions.emit_and_cleanup(type_id, self, |callback, this| {
2050 callback(this);
2051 true
2052 });
2053 }
2054
2055 Effect::Deferred {
2056 callback,
2057 after_window_update,
2058 } => {
2059 if after_window_update {
2060 after_window_update_callbacks.push(callback);
2061 } else {
2062 callback(self)
2063 }
2064 }
2065
2066 Effect::ModelRelease { model_id, model } => {
2067 self.handle_entity_release_effect(model_id, model.as_any())
2068 }
2069
2070 Effect::ViewRelease { view_id, view } => {
2071 self.handle_entity_release_effect(view_id, view.as_any())
2072 }
2073
2074 Effect::Focus { window_id, view_id } => {
2075 self.handle_focus_effect(window_id, view_id);
2076 }
2077
2078 Effect::FocusObservation {
2079 view_id,
2080 subscription_id,
2081 callback,
2082 } => {
2083 self.focus_observations.add_or_remove_callback(
2084 view_id,
2085 subscription_id,
2086 callback,
2087 );
2088 }
2089
2090 Effect::ResizeWindow { window_id } => {
2091 if let Some(window) = self.cx.windows.get_mut(&window_id) {
2092 window
2093 .invalidation
2094 .get_or_insert(WindowInvalidation::default());
2095 }
2096 }
2097
2098 Effect::WindowActivationObservation {
2099 window_id,
2100 subscription_id,
2101 callback,
2102 } => self.window_activation_observations.add_or_remove_callback(
2103 window_id,
2104 subscription_id,
2105 callback,
2106 ),
2107
2108 Effect::ActivateWindow {
2109 window_id,
2110 is_active,
2111 } => self.handle_window_activation_effect(window_id, is_active),
2112
2113 Effect::WindowFullscreenObservation {
2114 window_id,
2115 subscription_id,
2116 callback,
2117 } => self.window_fullscreen_observations.add_or_remove_callback(
2118 window_id,
2119 subscription_id,
2120 callback,
2121 ),
2122
2123 Effect::FullscreenWindow {
2124 window_id,
2125 is_fullscreen,
2126 } => self.handle_fullscreen_effect(window_id, is_fullscreen),
2127
2128 Effect::RefreshWindows => {
2129 refreshing = true;
2130 }
2131 Effect::DispatchActionFrom {
2132 window_id,
2133 view_id,
2134 action,
2135 } => {
2136 self.handle_dispatch_action_from_effect(
2137 window_id,
2138 Some(view_id),
2139 action.as_ref(),
2140 );
2141 }
2142 Effect::ActionDispatchNotification { action_id } => {
2143 self.handle_action_dispatch_notification_effect(action_id)
2144 }
2145 Effect::WindowShouldCloseSubscription {
2146 window_id,
2147 callback,
2148 } => {
2149 self.handle_window_should_close_subscription_effect(window_id, callback)
2150 }
2151 Effect::Keystroke {
2152 window_id,
2153 keystroke,
2154 handled_by,
2155 result,
2156 } => self.handle_keystroke_effect(window_id, keystroke, handled_by, result),
2157 }
2158 self.pending_notifications.clear();
2159 self.remove_dropped_entities();
2160 } else {
2161 self.remove_dropped_entities();
2162 if refreshing {
2163 self.perform_window_refresh();
2164 } else {
2165 self.update_windows();
2166 }
2167
2168 if self.pending_effects.is_empty() {
2169 for callback in after_window_update_callbacks.drain(..) {
2170 callback(self);
2171 }
2172
2173 if self.pending_effects.is_empty() {
2174 self.flushing_effects = false;
2175 self.pending_notifications.clear();
2176 self.pending_global_notifications.clear();
2177 break;
2178 }
2179 }
2180
2181 refreshing = false;
2182 }
2183 }
2184 }
2185 }
2186
2187 fn update_windows(&mut self) {
2188 let mut invalidations: HashMap<_, _> = Default::default();
2189 for (window_id, window) in &mut self.cx.windows {
2190 if let Some(invalidation) = window.invalidation.take() {
2191 invalidations.insert(*window_id, invalidation);
2192 }
2193 }
2194
2195 for (window_id, mut invalidation) in invalidations {
2196 if let Some((presenter, mut window)) =
2197 self.presenters_and_platform_windows.remove(&window_id)
2198 {
2199 {
2200 let mut presenter = presenter.borrow_mut();
2201 presenter.invalidate(&mut invalidation, window.appearance(), self);
2202 let scene = presenter.build_scene(
2203 window.content_size(),
2204 window.scale_factor(),
2205 false,
2206 self,
2207 );
2208 window.present_scene(scene);
2209 }
2210 self.presenters_and_platform_windows
2211 .insert(window_id, (presenter, window));
2212 }
2213 }
2214 }
2215
2216 fn window_was_resized(&mut self, window_id: usize) {
2217 self.pending_effects
2218 .push_back(Effect::ResizeWindow { window_id });
2219 }
2220
2221 fn window_was_fullscreen_changed(&mut self, window_id: usize, is_fullscreen: bool) {
2222 self.pending_effects.push_back(Effect::FullscreenWindow {
2223 window_id,
2224 is_fullscreen,
2225 });
2226 }
2227
2228 fn window_changed_active_status(&mut self, window_id: usize, is_active: bool) {
2229 self.pending_effects.push_back(Effect::ActivateWindow {
2230 window_id,
2231 is_active,
2232 });
2233 }
2234
2235 fn keystroke(
2236 &mut self,
2237 window_id: usize,
2238 keystroke: Keystroke,
2239 handled_by: Option<Box<dyn Action>>,
2240 result: MatchResult,
2241 ) {
2242 self.pending_effects.push_back(Effect::Keystroke {
2243 window_id,
2244 keystroke,
2245 handled_by,
2246 result,
2247 });
2248 }
2249
2250 pub fn refresh_windows(&mut self) {
2251 self.pending_effects.push_back(Effect::RefreshWindows);
2252 }
2253
2254 pub fn dispatch_action_at(&mut self, window_id: usize, view_id: usize, action: impl Action) {
2255 self.dispatch_any_action_at(window_id, view_id, Box::new(action));
2256 }
2257
2258 pub fn dispatch_any_action_at(
2259 &mut self,
2260 window_id: usize,
2261 view_id: usize,
2262 action: Box<dyn Action>,
2263 ) {
2264 self.pending_effects.push_back(Effect::DispatchActionFrom {
2265 window_id,
2266 view_id,
2267 action,
2268 });
2269 }
2270
2271 fn perform_window_refresh(&mut self) {
2272 let mut presenters = mem::take(&mut self.presenters_and_platform_windows);
2273 for (window_id, (presenter, window)) in &mut presenters {
2274 let mut invalidation = self
2275 .cx
2276 .windows
2277 .get_mut(window_id)
2278 .unwrap()
2279 .invalidation
2280 .take();
2281 let mut presenter = presenter.borrow_mut();
2282 presenter.refresh(
2283 invalidation.as_mut().unwrap_or(&mut Default::default()),
2284 window.appearance(),
2285 self,
2286 );
2287 let scene =
2288 presenter.build_scene(window.content_size(), window.scale_factor(), true, self);
2289 window.present_scene(scene);
2290 }
2291 self.presenters_and_platform_windows = presenters;
2292 }
2293
2294 fn emit_global_event(&mut self, payload: Box<dyn Any>) {
2295 let type_id = (&*payload).type_id();
2296
2297 let mut subscriptions = self.global_subscriptions.clone();
2298 subscriptions.emit_and_cleanup(type_id, self, |callback, this| {
2299 callback(payload.as_ref(), this);
2300 true //Always alive
2301 });
2302 }
2303
2304 fn handle_view_notification_effect(
2305 &mut self,
2306 observed_window_id: usize,
2307 observed_view_id: usize,
2308 ) {
2309 if self
2310 .cx
2311 .views
2312 .contains_key(&(observed_window_id, observed_view_id))
2313 {
2314 if let Some(window) = self.cx.windows.get_mut(&observed_window_id) {
2315 window
2316 .invalidation
2317 .get_or_insert_with(Default::default)
2318 .updated
2319 .insert(observed_view_id);
2320 }
2321
2322 let mut observations = self.observations.clone();
2323 observations.emit_and_cleanup(observed_view_id, self, |callback, this| callback(this));
2324 }
2325 }
2326
2327 fn handle_entity_release_effect(&mut self, entity_id: usize, entity: &dyn Any) {
2328 let callbacks = self.release_observations.lock().remove(&entity_id);
2329 if let Some(callbacks) = callbacks {
2330 for (_, callback) in callbacks {
2331 callback(entity, self);
2332 }
2333 }
2334 }
2335
2336 fn handle_fullscreen_effect(&mut self, window_id: usize, is_fullscreen: bool) {
2337 //Short circuit evaluation if we're already g2g
2338 if self
2339 .cx
2340 .windows
2341 .get(&window_id)
2342 .map(|w| w.is_fullscreen == is_fullscreen)
2343 .unwrap_or(false)
2344 {
2345 return;
2346 }
2347
2348 self.update(|this| {
2349 let window = this.cx.windows.get_mut(&window_id)?;
2350 window.is_fullscreen = is_fullscreen;
2351
2352 let mut observations = this.window_fullscreen_observations.clone();
2353 observations.emit_and_cleanup(window_id, this, |callback, this| {
2354 callback(is_fullscreen, this)
2355 });
2356
2357 Some(())
2358 });
2359 }
2360
2361 fn handle_keystroke_effect(
2362 &mut self,
2363 window_id: usize,
2364 keystroke: Keystroke,
2365 handled_by: Option<Box<dyn Action>>,
2366 result: MatchResult,
2367 ) {
2368 self.update(|this| {
2369 let mut observations = this.keystroke_observations.clone();
2370 observations.emit_and_cleanup(window_id, this, {
2371 move |callback, this| callback(&keystroke, &result, handled_by.as_ref(), this)
2372 });
2373 });
2374 }
2375
2376 fn handle_window_activation_effect(&mut self, window_id: usize, active: bool) {
2377 //Short circuit evaluation if we're already g2g
2378 if self
2379 .cx
2380 .windows
2381 .get(&window_id)
2382 .map(|w| w.is_active == active)
2383 .unwrap_or(false)
2384 {
2385 return;
2386 }
2387
2388 self.update(|this| {
2389 let window = this.cx.windows.get_mut(&window_id)?;
2390 window.is_active = active;
2391
2392 //Handle focus
2393 let focused_id = window.focused_view_id?;
2394 for view_id in this.ancestors(window_id, focused_id).collect::<Vec<_>>() {
2395 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
2396 if active {
2397 view.focus_in(this, window_id, view_id, focused_id);
2398 } else {
2399 view.focus_out(this, window_id, view_id, focused_id);
2400 }
2401 this.cx.views.insert((window_id, view_id), view);
2402 }
2403 }
2404
2405 let mut observations = this.window_activation_observations.clone();
2406 observations.emit_and_cleanup(window_id, this, |callback, this| callback(active, this));
2407
2408 Some(())
2409 });
2410 }
2411
2412 fn handle_focus_effect(&mut self, window_id: usize, focused_id: Option<usize>) {
2413 if self
2414 .cx
2415 .windows
2416 .get(&window_id)
2417 .map(|w| w.focused_view_id)
2418 .map_or(false, |cur_focused| cur_focused == focused_id)
2419 {
2420 return;
2421 }
2422
2423 self.update(|this| {
2424 let blurred_id = this.cx.windows.get_mut(&window_id).and_then(|window| {
2425 let blurred_id = window.focused_view_id;
2426 window.focused_view_id = focused_id;
2427 blurred_id
2428 });
2429
2430 let blurred_parents = blurred_id
2431 .map(|blurred_id| this.ancestors(window_id, blurred_id).collect::<Vec<_>>())
2432 .unwrap_or_default();
2433 let focused_parents = focused_id
2434 .map(|focused_id| this.ancestors(window_id, focused_id).collect::<Vec<_>>())
2435 .unwrap_or_default();
2436
2437 if let Some(blurred_id) = blurred_id {
2438 for view_id in blurred_parents.iter().copied() {
2439 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
2440 view.focus_out(this, window_id, view_id, blurred_id);
2441 this.cx.views.insert((window_id, view_id), view);
2442 }
2443 }
2444
2445 let mut subscriptions = this.focus_observations.clone();
2446 subscriptions
2447 .emit_and_cleanup(blurred_id, this, |callback, this| callback(false, this));
2448 }
2449
2450 if let Some(focused_id) = focused_id {
2451 for view_id in focused_parents {
2452 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
2453 view.focus_in(this, window_id, view_id, focused_id);
2454 this.cx.views.insert((window_id, view_id), view);
2455 }
2456 }
2457
2458 let mut subscriptions = this.focus_observations.clone();
2459 subscriptions
2460 .emit_and_cleanup(focused_id, this, |callback, this| callback(true, this));
2461 }
2462 })
2463 }
2464
2465 fn handle_dispatch_action_from_effect(
2466 &mut self,
2467 window_id: usize,
2468 view_id: Option<usize>,
2469 action: &dyn Action,
2470 ) -> bool {
2471 self.update(|this| {
2472 if let Some(view_id) = view_id {
2473 this.halt_action_dispatch = false;
2474 this.visit_dispatch_path(window_id, view_id, |view_id, capture_phase, this| {
2475 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
2476 let type_id = view.as_any().type_id();
2477
2478 if let Some((name, mut handlers)) = this
2479 .actions_mut(capture_phase)
2480 .get_mut(&type_id)
2481 .and_then(|h| h.remove_entry(&action.id()))
2482 {
2483 for handler in handlers.iter_mut().rev() {
2484 this.halt_action_dispatch = true;
2485 handler(view.as_mut(), action, this, window_id, view_id);
2486 if this.halt_action_dispatch {
2487 break;
2488 }
2489 }
2490 this.actions_mut(capture_phase)
2491 .get_mut(&type_id)
2492 .unwrap()
2493 .insert(name, handlers);
2494 }
2495
2496 this.cx.views.insert((window_id, view_id), view);
2497 }
2498
2499 !this.halt_action_dispatch
2500 });
2501 }
2502
2503 if !this.halt_action_dispatch {
2504 this.halt_action_dispatch = this.dispatch_global_action_any(action);
2505 }
2506
2507 this.pending_effects
2508 .push_back(Effect::ActionDispatchNotification {
2509 action_id: action.id(),
2510 });
2511 this.halt_action_dispatch
2512 })
2513 }
2514
2515 fn handle_action_dispatch_notification_effect(&mut self, action_id: TypeId) {
2516 let mut callbacks = mem::take(&mut *self.action_dispatch_observations.lock());
2517 for callback in callbacks.values_mut() {
2518 callback(action_id, self);
2519 }
2520 self.action_dispatch_observations.lock().extend(callbacks);
2521 }
2522
2523 fn handle_window_should_close_subscription_effect(
2524 &mut self,
2525 window_id: usize,
2526 mut callback: WindowShouldCloseSubscriptionCallback,
2527 ) {
2528 let mut app = self.upgrade();
2529 if let Some((_, window)) = self.presenters_and_platform_windows.get_mut(&window_id) {
2530 window.on_should_close(Box::new(move || app.update(|cx| callback(cx))))
2531 }
2532 }
2533
2534 pub fn focus(&mut self, window_id: usize, view_id: Option<usize>) {
2535 self.pending_effects
2536 .push_back(Effect::Focus { window_id, view_id });
2537 }
2538
2539 pub fn spawn<F, Fut, T>(&self, f: F) -> Task<T>
2540 where
2541 F: FnOnce(AsyncAppContext) -> Fut,
2542 Fut: 'static + Future<Output = T>,
2543 T: 'static,
2544 {
2545 let future = f(self.to_async());
2546 let cx = self.to_async();
2547 self.foreground.spawn(async move {
2548 let result = future.await;
2549 cx.0.borrow_mut().flush_effects();
2550 result
2551 })
2552 }
2553
2554 pub fn to_async(&self) -> AsyncAppContext {
2555 AsyncAppContext(self.weak_self.as_ref().unwrap().upgrade().unwrap())
2556 }
2557
2558 pub fn write_to_clipboard(&self, item: ClipboardItem) {
2559 self.cx.platform.write_to_clipboard(item);
2560 }
2561
2562 pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {
2563 self.cx.platform.read_from_clipboard()
2564 }
2565
2566 #[cfg(any(test, feature = "test-support"))]
2567 pub fn leak_detector(&self) -> Arc<Mutex<LeakDetector>> {
2568 self.cx.ref_counts.lock().leak_detector.clone()
2569 }
2570}
2571
2572impl ReadModel for MutableAppContext {
2573 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2574 if let Some(model) = self.cx.models.get(&handle.model_id) {
2575 model
2576 .as_any()
2577 .downcast_ref()
2578 .expect("downcast is type safe")
2579 } else {
2580 panic!("circular model reference");
2581 }
2582 }
2583}
2584
2585impl UpdateModel for MutableAppContext {
2586 fn update_model<T: Entity, V>(
2587 &mut self,
2588 handle: &ModelHandle<T>,
2589 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
2590 ) -> V {
2591 if let Some(mut model) = self.cx.models.remove(&handle.model_id) {
2592 self.update(|this| {
2593 let mut cx = ModelContext::new(this, handle.model_id);
2594 let result = update(
2595 model
2596 .as_any_mut()
2597 .downcast_mut()
2598 .expect("downcast is type safe"),
2599 &mut cx,
2600 );
2601 this.cx.models.insert(handle.model_id, model);
2602 result
2603 })
2604 } else {
2605 panic!("circular model update");
2606 }
2607 }
2608}
2609
2610impl UpgradeModelHandle for MutableAppContext {
2611 fn upgrade_model_handle<T: Entity>(
2612 &self,
2613 handle: &WeakModelHandle<T>,
2614 ) -> Option<ModelHandle<T>> {
2615 self.cx.upgrade_model_handle(handle)
2616 }
2617
2618 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
2619 self.cx.model_handle_is_upgradable(handle)
2620 }
2621
2622 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
2623 self.cx.upgrade_any_model_handle(handle)
2624 }
2625}
2626
2627impl UpgradeViewHandle for MutableAppContext {
2628 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
2629 self.cx.upgrade_view_handle(handle)
2630 }
2631
2632 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
2633 self.cx.upgrade_any_view_handle(handle)
2634 }
2635}
2636
2637impl ReadView for MutableAppContext {
2638 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2639 if let Some(view) = self.cx.views.get(&(handle.window_id, handle.view_id)) {
2640 view.as_any().downcast_ref().expect("downcast is type safe")
2641 } else {
2642 panic!("circular view reference for type {}", type_name::<T>());
2643 }
2644 }
2645}
2646
2647impl UpdateView for MutableAppContext {
2648 fn update_view<T, S>(
2649 &mut self,
2650 handle: &ViewHandle<T>,
2651 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
2652 ) -> S
2653 where
2654 T: View,
2655 {
2656 self.update(|this| {
2657 let mut view = this
2658 .cx
2659 .views
2660 .remove(&(handle.window_id, handle.view_id))
2661 .expect("circular view update");
2662
2663 let mut cx = ViewContext::new(this, handle.window_id, handle.view_id);
2664 let result = update(
2665 view.as_any_mut()
2666 .downcast_mut()
2667 .expect("downcast is type safe"),
2668 &mut cx,
2669 );
2670 this.cx
2671 .views
2672 .insert((handle.window_id, handle.view_id), view);
2673 result
2674 })
2675 }
2676}
2677
2678impl AsRef<AppContext> for MutableAppContext {
2679 fn as_ref(&self) -> &AppContext {
2680 &self.cx
2681 }
2682}
2683
2684impl Deref for MutableAppContext {
2685 type Target = AppContext;
2686
2687 fn deref(&self) -> &Self::Target {
2688 &self.cx
2689 }
2690}
2691
2692#[derive(Debug)]
2693pub enum ParentId {
2694 View(usize),
2695 Root,
2696}
2697
2698pub struct AppContext {
2699 models: HashMap<usize, Box<dyn AnyModel>>,
2700 views: HashMap<(usize, usize), Box<dyn AnyView>>,
2701 pub(crate) parents: HashMap<(usize, usize), ParentId>,
2702 windows: HashMap<usize, Window>,
2703 globals: HashMap<TypeId, Box<dyn Any>>,
2704 element_states: HashMap<ElementStateId, Box<dyn Any>>,
2705 background: Arc<executor::Background>,
2706 ref_counts: Arc<Mutex<RefCounts>>,
2707 font_cache: Arc<FontCache>,
2708 platform: Arc<dyn Platform>,
2709}
2710
2711impl AppContext {
2712 pub(crate) fn root_view(&self, window_id: usize) -> Option<AnyViewHandle> {
2713 self.windows
2714 .get(&window_id)
2715 .map(|window| window.root_view.clone())
2716 }
2717
2718 pub fn root_view_id(&self, window_id: usize) -> Option<usize> {
2719 self.windows
2720 .get(&window_id)
2721 .map(|window| window.root_view.id())
2722 }
2723
2724 pub fn focused_view_id(&self, window_id: usize) -> Option<usize> {
2725 self.windows
2726 .get(&window_id)
2727 .and_then(|window| window.focused_view_id)
2728 }
2729
2730 pub fn view_ui_name(&self, window_id: usize, view_id: usize) -> Option<&'static str> {
2731 Some(self.views.get(&(window_id, view_id))?.ui_name())
2732 }
2733
2734 pub fn background(&self) -> &Arc<executor::Background> {
2735 &self.background
2736 }
2737
2738 pub fn font_cache(&self) -> &Arc<FontCache> {
2739 &self.font_cache
2740 }
2741
2742 pub fn platform(&self) -> &Arc<dyn Platform> {
2743 &self.platform
2744 }
2745
2746 pub fn has_global<T: 'static>(&self) -> bool {
2747 self.globals.contains_key(&TypeId::of::<T>())
2748 }
2749
2750 pub fn global<T: 'static>(&self) -> &T {
2751 if let Some(global) = self.globals.get(&TypeId::of::<T>()) {
2752 global.downcast_ref().unwrap()
2753 } else {
2754 panic!("no global has been added for {}", type_name::<T>());
2755 }
2756 }
2757}
2758
2759impl ReadModel for AppContext {
2760 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
2761 if let Some(model) = self.models.get(&handle.model_id) {
2762 model
2763 .as_any()
2764 .downcast_ref()
2765 .expect("downcast should be type safe")
2766 } else {
2767 panic!("circular model reference");
2768 }
2769 }
2770}
2771
2772impl UpgradeModelHandle for AppContext {
2773 fn upgrade_model_handle<T: Entity>(
2774 &self,
2775 handle: &WeakModelHandle<T>,
2776 ) -> Option<ModelHandle<T>> {
2777 if self.models.contains_key(&handle.model_id) {
2778 Some(ModelHandle::new(handle.model_id, &self.ref_counts))
2779 } else {
2780 None
2781 }
2782 }
2783
2784 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
2785 self.models.contains_key(&handle.model_id)
2786 }
2787
2788 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
2789 if self.models.contains_key(&handle.model_id) {
2790 Some(AnyModelHandle::new(
2791 handle.model_id,
2792 handle.model_type,
2793 self.ref_counts.clone(),
2794 ))
2795 } else {
2796 None
2797 }
2798 }
2799}
2800
2801impl UpgradeViewHandle for AppContext {
2802 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
2803 if self.ref_counts.lock().is_entity_alive(handle.view_id) {
2804 Some(ViewHandle::new(
2805 handle.window_id,
2806 handle.view_id,
2807 &self.ref_counts,
2808 ))
2809 } else {
2810 None
2811 }
2812 }
2813
2814 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
2815 if self.ref_counts.lock().is_entity_alive(handle.view_id) {
2816 Some(AnyViewHandle::new(
2817 handle.window_id,
2818 handle.view_id,
2819 handle.view_type,
2820 self.ref_counts.clone(),
2821 ))
2822 } else {
2823 None
2824 }
2825 }
2826}
2827
2828impl ReadView for AppContext {
2829 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
2830 if let Some(view) = self.views.get(&(handle.window_id, handle.view_id)) {
2831 view.as_any()
2832 .downcast_ref()
2833 .expect("downcast should be type safe")
2834 } else {
2835 panic!("circular view reference");
2836 }
2837 }
2838}
2839
2840struct Window {
2841 root_view: AnyViewHandle,
2842 focused_view_id: Option<usize>,
2843 is_active: bool,
2844 is_fullscreen: bool,
2845 invalidation: Option<WindowInvalidation>,
2846}
2847
2848#[derive(Default, Clone)]
2849pub struct WindowInvalidation {
2850 pub updated: HashSet<usize>,
2851 pub removed: Vec<usize>,
2852}
2853
2854pub enum Effect {
2855 Subscription {
2856 entity_id: usize,
2857 subscription_id: usize,
2858 callback: SubscriptionCallback,
2859 },
2860 Event {
2861 entity_id: usize,
2862 payload: Box<dyn Any>,
2863 },
2864 GlobalSubscription {
2865 type_id: TypeId,
2866 subscription_id: usize,
2867 callback: GlobalSubscriptionCallback,
2868 },
2869 GlobalEvent {
2870 payload: Box<dyn Any>,
2871 },
2872 Observation {
2873 entity_id: usize,
2874 subscription_id: usize,
2875 callback: ObservationCallback,
2876 },
2877 ModelNotification {
2878 model_id: usize,
2879 },
2880 ViewNotification {
2881 window_id: usize,
2882 view_id: usize,
2883 },
2884 Deferred {
2885 callback: Box<dyn FnOnce(&mut MutableAppContext)>,
2886 after_window_update: bool,
2887 },
2888 GlobalNotification {
2889 type_id: TypeId,
2890 },
2891 ModelRelease {
2892 model_id: usize,
2893 model: Box<dyn AnyModel>,
2894 },
2895 ViewRelease {
2896 view_id: usize,
2897 view: Box<dyn AnyView>,
2898 },
2899 Focus {
2900 window_id: usize,
2901 view_id: Option<usize>,
2902 },
2903 FocusObservation {
2904 view_id: usize,
2905 subscription_id: usize,
2906 callback: FocusObservationCallback,
2907 },
2908 ResizeWindow {
2909 window_id: usize,
2910 },
2911 FullscreenWindow {
2912 window_id: usize,
2913 is_fullscreen: bool,
2914 },
2915 ActivateWindow {
2916 window_id: usize,
2917 is_active: bool,
2918 },
2919 WindowActivationObservation {
2920 window_id: usize,
2921 subscription_id: usize,
2922 callback: WindowActivationCallback,
2923 },
2924 WindowFullscreenObservation {
2925 window_id: usize,
2926 subscription_id: usize,
2927 callback: WindowFullscreenCallback,
2928 },
2929 Keystroke {
2930 window_id: usize,
2931 keystroke: Keystroke,
2932 handled_by: Option<Box<dyn Action>>,
2933 result: MatchResult,
2934 },
2935 RefreshWindows,
2936 DispatchActionFrom {
2937 window_id: usize,
2938 view_id: usize,
2939 action: Box<dyn Action>,
2940 },
2941 ActionDispatchNotification {
2942 action_id: TypeId,
2943 },
2944 WindowShouldCloseSubscription {
2945 window_id: usize,
2946 callback: WindowShouldCloseSubscriptionCallback,
2947 },
2948}
2949
2950impl Debug for Effect {
2951 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2952 match self {
2953 Effect::Subscription {
2954 entity_id,
2955 subscription_id,
2956 ..
2957 } => f
2958 .debug_struct("Effect::Subscribe")
2959 .field("entity_id", entity_id)
2960 .field("subscription_id", subscription_id)
2961 .finish(),
2962 Effect::Event { entity_id, .. } => f
2963 .debug_struct("Effect::Event")
2964 .field("entity_id", entity_id)
2965 .finish(),
2966 Effect::GlobalSubscription {
2967 type_id,
2968 subscription_id,
2969 ..
2970 } => f
2971 .debug_struct("Effect::Subscribe")
2972 .field("type_id", type_id)
2973 .field("subscription_id", subscription_id)
2974 .finish(),
2975 Effect::GlobalEvent { payload, .. } => f
2976 .debug_struct("Effect::GlobalEvent")
2977 .field("type_id", &(&*payload).type_id())
2978 .finish(),
2979 Effect::Observation {
2980 entity_id,
2981 subscription_id,
2982 ..
2983 } => f
2984 .debug_struct("Effect::Observation")
2985 .field("entity_id", entity_id)
2986 .field("subscription_id", subscription_id)
2987 .finish(),
2988 Effect::ModelNotification { model_id } => f
2989 .debug_struct("Effect::ModelNotification")
2990 .field("model_id", model_id)
2991 .finish(),
2992 Effect::ViewNotification { window_id, view_id } => f
2993 .debug_struct("Effect::ViewNotification")
2994 .field("window_id", window_id)
2995 .field("view_id", view_id)
2996 .finish(),
2997 Effect::GlobalNotification { type_id } => f
2998 .debug_struct("Effect::GlobalNotification")
2999 .field("type_id", type_id)
3000 .finish(),
3001 Effect::Deferred { .. } => f.debug_struct("Effect::Deferred").finish(),
3002 Effect::ModelRelease { model_id, .. } => f
3003 .debug_struct("Effect::ModelRelease")
3004 .field("model_id", model_id)
3005 .finish(),
3006 Effect::ViewRelease { view_id, .. } => f
3007 .debug_struct("Effect::ViewRelease")
3008 .field("view_id", view_id)
3009 .finish(),
3010 Effect::Focus { window_id, view_id } => f
3011 .debug_struct("Effect::Focus")
3012 .field("window_id", window_id)
3013 .field("view_id", view_id)
3014 .finish(),
3015 Effect::FocusObservation {
3016 view_id,
3017 subscription_id,
3018 ..
3019 } => f
3020 .debug_struct("Effect::FocusObservation")
3021 .field("view_id", view_id)
3022 .field("subscription_id", subscription_id)
3023 .finish(),
3024 Effect::DispatchActionFrom {
3025 window_id, view_id, ..
3026 } => f
3027 .debug_struct("Effect::DispatchActionFrom")
3028 .field("window_id", window_id)
3029 .field("view_id", view_id)
3030 .finish(),
3031 Effect::ActionDispatchNotification { action_id, .. } => f
3032 .debug_struct("Effect::ActionDispatchNotification")
3033 .field("action_id", action_id)
3034 .finish(),
3035 Effect::ResizeWindow { window_id } => f
3036 .debug_struct("Effect::RefreshWindow")
3037 .field("window_id", window_id)
3038 .finish(),
3039 Effect::WindowActivationObservation {
3040 window_id,
3041 subscription_id,
3042 ..
3043 } => f
3044 .debug_struct("Effect::WindowActivationObservation")
3045 .field("window_id", window_id)
3046 .field("subscription_id", subscription_id)
3047 .finish(),
3048 Effect::ActivateWindow {
3049 window_id,
3050 is_active,
3051 } => f
3052 .debug_struct("Effect::ActivateWindow")
3053 .field("window_id", window_id)
3054 .field("is_active", is_active)
3055 .finish(),
3056 Effect::FullscreenWindow {
3057 window_id,
3058 is_fullscreen,
3059 } => f
3060 .debug_struct("Effect::FullscreenWindow")
3061 .field("window_id", window_id)
3062 .field("is_fullscreen", is_fullscreen)
3063 .finish(),
3064 Effect::WindowFullscreenObservation {
3065 window_id,
3066 subscription_id,
3067 callback: _,
3068 } => f
3069 .debug_struct("Effect::WindowFullscreenObservation")
3070 .field("window_id", window_id)
3071 .field("subscription_id", subscription_id)
3072 .finish(),
3073 Effect::RefreshWindows => f.debug_struct("Effect::FullViewRefresh").finish(),
3074 Effect::WindowShouldCloseSubscription { window_id, .. } => f
3075 .debug_struct("Effect::WindowShouldCloseSubscription")
3076 .field("window_id", window_id)
3077 .finish(),
3078 Effect::Keystroke {
3079 window_id,
3080 keystroke,
3081 handled_by,
3082 result,
3083 } => f
3084 .debug_struct("Effect::Keystroke")
3085 .field("window_id", window_id)
3086 .field("keystroke", keystroke)
3087 .field(
3088 "keystroke",
3089 &handled_by.as_ref().map(|handled_by| handled_by.name()),
3090 )
3091 .field("result", result)
3092 .finish(),
3093 }
3094 }
3095}
3096
3097pub trait AnyModel {
3098 fn as_any(&self) -> &dyn Any;
3099 fn as_any_mut(&mut self) -> &mut dyn Any;
3100 fn release(&mut self, cx: &mut MutableAppContext);
3101 fn app_will_quit(
3102 &mut self,
3103 cx: &mut MutableAppContext,
3104 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
3105}
3106
3107impl<T> AnyModel for T
3108where
3109 T: Entity,
3110{
3111 fn as_any(&self) -> &dyn Any {
3112 self
3113 }
3114
3115 fn as_any_mut(&mut self) -> &mut dyn Any {
3116 self
3117 }
3118
3119 fn release(&mut self, cx: &mut MutableAppContext) {
3120 self.release(cx);
3121 }
3122
3123 fn app_will_quit(
3124 &mut self,
3125 cx: &mut MutableAppContext,
3126 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
3127 self.app_will_quit(cx)
3128 }
3129}
3130
3131pub trait AnyView {
3132 fn as_any(&self) -> &dyn Any;
3133 fn as_any_mut(&mut self) -> &mut dyn Any;
3134 fn release(&mut self, cx: &mut MutableAppContext);
3135 fn app_will_quit(
3136 &mut self,
3137 cx: &mut MutableAppContext,
3138 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
3139 fn ui_name(&self) -> &'static str;
3140 fn render(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox;
3141 fn focus_in(
3142 &mut self,
3143 cx: &mut MutableAppContext,
3144 window_id: usize,
3145 view_id: usize,
3146 focused_id: usize,
3147 );
3148 fn focus_out(
3149 &mut self,
3150 cx: &mut MutableAppContext,
3151 window_id: usize,
3152 view_id: usize,
3153 focused_id: usize,
3154 );
3155 fn key_down(
3156 &mut self,
3157 event: &KeyDownEvent,
3158 cx: &mut MutableAppContext,
3159 window_id: usize,
3160 view_id: usize,
3161 ) -> bool;
3162 fn key_up(
3163 &mut self,
3164 event: &KeyUpEvent,
3165 cx: &mut MutableAppContext,
3166 window_id: usize,
3167 view_id: usize,
3168 ) -> bool;
3169 fn modifiers_changed(
3170 &mut self,
3171 event: &ModifiersChangedEvent,
3172 cx: &mut MutableAppContext,
3173 window_id: usize,
3174 view_id: usize,
3175 ) -> bool;
3176 fn keymap_context(&self, cx: &AppContext) -> keymap::Context;
3177 fn debug_json(&self, cx: &AppContext) -> serde_json::Value;
3178
3179 fn text_for_range(&self, range: Range<usize>, cx: &AppContext) -> Option<String>;
3180 fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>>;
3181 fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>>;
3182 fn unmark_text(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize);
3183 fn replace_text_in_range(
3184 &mut self,
3185 range: Option<Range<usize>>,
3186 text: &str,
3187 cx: &mut MutableAppContext,
3188 window_id: usize,
3189 view_id: usize,
3190 );
3191 fn replace_and_mark_text_in_range(
3192 &mut self,
3193 range: Option<Range<usize>>,
3194 new_text: &str,
3195 new_selected_range: Option<Range<usize>>,
3196 cx: &mut MutableAppContext,
3197 window_id: usize,
3198 view_id: usize,
3199 );
3200 fn any_handle(&self, window_id: usize, view_id: usize, cx: &AppContext) -> AnyViewHandle {
3201 AnyViewHandle::new(
3202 window_id,
3203 view_id,
3204 self.as_any().type_id(),
3205 cx.ref_counts.clone(),
3206 )
3207 }
3208}
3209
3210impl<T> AnyView for T
3211where
3212 T: View,
3213{
3214 fn as_any(&self) -> &dyn Any {
3215 self
3216 }
3217
3218 fn as_any_mut(&mut self) -> &mut dyn Any {
3219 self
3220 }
3221
3222 fn release(&mut self, cx: &mut MutableAppContext) {
3223 self.release(cx);
3224 }
3225
3226 fn app_will_quit(
3227 &mut self,
3228 cx: &mut MutableAppContext,
3229 ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>> {
3230 self.app_will_quit(cx)
3231 }
3232
3233 fn ui_name(&self) -> &'static str {
3234 T::ui_name()
3235 }
3236
3237 fn render(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox {
3238 View::render(self, &mut RenderContext::new(params, cx))
3239 }
3240
3241 fn focus_in(
3242 &mut self,
3243 cx: &mut MutableAppContext,
3244 window_id: usize,
3245 view_id: usize,
3246 focused_id: usize,
3247 ) {
3248 let mut cx = ViewContext::new(cx, window_id, view_id);
3249 let focused_view_handle: AnyViewHandle = if view_id == focused_id {
3250 cx.handle().into()
3251 } else {
3252 let focused_type = cx
3253 .views
3254 .get(&(window_id, focused_id))
3255 .unwrap()
3256 .as_any()
3257 .type_id();
3258 AnyViewHandle::new(window_id, focused_id, focused_type, cx.ref_counts.clone())
3259 };
3260 View::focus_in(self, focused_view_handle, &mut cx);
3261 }
3262
3263 fn focus_out(
3264 &mut self,
3265 cx: &mut MutableAppContext,
3266 window_id: usize,
3267 view_id: usize,
3268 blurred_id: usize,
3269 ) {
3270 let mut cx = ViewContext::new(cx, window_id, view_id);
3271 let blurred_view_handle: AnyViewHandle = if view_id == blurred_id {
3272 cx.handle().into()
3273 } else {
3274 let blurred_type = cx
3275 .views
3276 .get(&(window_id, blurred_id))
3277 .unwrap()
3278 .as_any()
3279 .type_id();
3280 AnyViewHandle::new(window_id, blurred_id, blurred_type, cx.ref_counts.clone())
3281 };
3282 View::focus_out(self, blurred_view_handle, &mut cx);
3283 }
3284
3285 fn key_down(
3286 &mut self,
3287 event: &KeyDownEvent,
3288 cx: &mut MutableAppContext,
3289 window_id: usize,
3290 view_id: usize,
3291 ) -> bool {
3292 let mut cx = ViewContext::new(cx, window_id, view_id);
3293 View::key_down(self, event, &mut cx)
3294 }
3295
3296 fn key_up(
3297 &mut self,
3298 event: &KeyUpEvent,
3299 cx: &mut MutableAppContext,
3300 window_id: usize,
3301 view_id: usize,
3302 ) -> bool {
3303 let mut cx = ViewContext::new(cx, window_id, view_id);
3304 View::key_up(self, event, &mut cx)
3305 }
3306
3307 fn modifiers_changed(
3308 &mut self,
3309 event: &ModifiersChangedEvent,
3310 cx: &mut MutableAppContext,
3311 window_id: usize,
3312 view_id: usize,
3313 ) -> bool {
3314 let mut cx = ViewContext::new(cx, window_id, view_id);
3315 View::modifiers_changed(self, event, &mut cx)
3316 }
3317
3318 fn keymap_context(&self, cx: &AppContext) -> keymap::Context {
3319 View::keymap_context(self, cx)
3320 }
3321
3322 fn debug_json(&self, cx: &AppContext) -> serde_json::Value {
3323 View::debug_json(self, cx)
3324 }
3325
3326 fn text_for_range(&self, range: Range<usize>, cx: &AppContext) -> Option<String> {
3327 View::text_for_range(self, range, cx)
3328 }
3329
3330 fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
3331 View::selected_text_range(self, cx)
3332 }
3333
3334 fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
3335 View::marked_text_range(self, cx)
3336 }
3337
3338 fn unmark_text(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) {
3339 let mut cx = ViewContext::new(cx, window_id, view_id);
3340 View::unmark_text(self, &mut cx)
3341 }
3342
3343 fn replace_text_in_range(
3344 &mut self,
3345 range: Option<Range<usize>>,
3346 text: &str,
3347 cx: &mut MutableAppContext,
3348 window_id: usize,
3349 view_id: usize,
3350 ) {
3351 let mut cx = ViewContext::new(cx, window_id, view_id);
3352 View::replace_text_in_range(self, range, text, &mut cx)
3353 }
3354
3355 fn replace_and_mark_text_in_range(
3356 &mut self,
3357 range: Option<Range<usize>>,
3358 new_text: &str,
3359 new_selected_range: Option<Range<usize>>,
3360 cx: &mut MutableAppContext,
3361 window_id: usize,
3362 view_id: usize,
3363 ) {
3364 let mut cx = ViewContext::new(cx, window_id, view_id);
3365 View::replace_and_mark_text_in_range(self, range, new_text, new_selected_range, &mut cx)
3366 }
3367}
3368
3369pub struct ModelContext<'a, T: ?Sized> {
3370 app: &'a mut MutableAppContext,
3371 model_id: usize,
3372 model_type: PhantomData<T>,
3373 halt_stream: bool,
3374}
3375
3376impl<'a, T: Entity> ModelContext<'a, T> {
3377 fn new(app: &'a mut MutableAppContext, model_id: usize) -> Self {
3378 Self {
3379 app,
3380 model_id,
3381 model_type: PhantomData,
3382 halt_stream: false,
3383 }
3384 }
3385
3386 pub fn background(&self) -> &Arc<executor::Background> {
3387 &self.app.cx.background
3388 }
3389
3390 pub fn halt_stream(&mut self) {
3391 self.halt_stream = true;
3392 }
3393
3394 pub fn model_id(&self) -> usize {
3395 self.model_id
3396 }
3397
3398 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
3399 where
3400 S: Entity,
3401 F: FnOnce(&mut ModelContext<S>) -> S,
3402 {
3403 self.app.add_model(build_model)
3404 }
3405
3406 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ModelContext<T>)) {
3407 let handle = self.handle();
3408 self.app.defer(move |cx| {
3409 handle.update(cx, |model, cx| {
3410 callback(model, cx);
3411 })
3412 })
3413 }
3414
3415 pub fn emit(&mut self, payload: T::Event) {
3416 self.app.pending_effects.push_back(Effect::Event {
3417 entity_id: self.model_id,
3418 payload: Box::new(payload),
3419 });
3420 }
3421
3422 pub fn notify(&mut self) {
3423 self.app.notify_model(self.model_id);
3424 }
3425
3426 pub fn subscribe<S: Entity, F>(
3427 &mut self,
3428 handle: &ModelHandle<S>,
3429 mut callback: F,
3430 ) -> Subscription
3431 where
3432 S::Event: 'static,
3433 F: 'static + FnMut(&mut T, ModelHandle<S>, &S::Event, &mut ModelContext<T>),
3434 {
3435 let subscriber = self.weak_handle();
3436 self.app
3437 .subscribe_internal(handle, move |emitter, event, cx| {
3438 if let Some(subscriber) = subscriber.upgrade(cx) {
3439 subscriber.update(cx, |subscriber, cx| {
3440 callback(subscriber, emitter, event, cx);
3441 });
3442 true
3443 } else {
3444 false
3445 }
3446 })
3447 }
3448
3449 pub fn observe<S, F>(&mut self, handle: &ModelHandle<S>, mut callback: F) -> Subscription
3450 where
3451 S: Entity,
3452 F: 'static + FnMut(&mut T, ModelHandle<S>, &mut ModelContext<T>),
3453 {
3454 let observer = self.weak_handle();
3455 self.app.observe_internal(handle, move |observed, cx| {
3456 if let Some(observer) = observer.upgrade(cx) {
3457 observer.update(cx, |observer, cx| {
3458 callback(observer, observed, cx);
3459 });
3460 true
3461 } else {
3462 false
3463 }
3464 })
3465 }
3466
3467 pub fn observe_global<G, F>(&mut self, mut callback: F) -> Subscription
3468 where
3469 G: Any,
3470 F: 'static + FnMut(&mut T, &mut ModelContext<T>),
3471 {
3472 let observer = self.weak_handle();
3473 self.app.observe_global::<G, _>(move |cx| {
3474 if let Some(observer) = observer.upgrade(cx) {
3475 observer.update(cx, |observer, cx| callback(observer, cx));
3476 }
3477 })
3478 }
3479
3480 pub fn observe_release<S, F>(
3481 &mut self,
3482 handle: &ModelHandle<S>,
3483 mut callback: F,
3484 ) -> Subscription
3485 where
3486 S: Entity,
3487 F: 'static + FnMut(&mut T, &S, &mut ModelContext<T>),
3488 {
3489 let observer = self.weak_handle();
3490 self.app.observe_release(handle, move |released, cx| {
3491 if let Some(observer) = observer.upgrade(cx) {
3492 observer.update(cx, |observer, cx| {
3493 callback(observer, released, cx);
3494 });
3495 }
3496 })
3497 }
3498
3499 pub fn handle(&self) -> ModelHandle<T> {
3500 ModelHandle::new(self.model_id, &self.app.cx.ref_counts)
3501 }
3502
3503 pub fn weak_handle(&self) -> WeakModelHandle<T> {
3504 WeakModelHandle::new(self.model_id)
3505 }
3506
3507 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
3508 where
3509 F: FnOnce(ModelHandle<T>, AsyncAppContext) -> Fut,
3510 Fut: 'static + Future<Output = S>,
3511 S: 'static,
3512 {
3513 let handle = self.handle();
3514 self.app.spawn(|cx| f(handle, cx))
3515 }
3516
3517 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
3518 where
3519 F: FnOnce(WeakModelHandle<T>, AsyncAppContext) -> Fut,
3520 Fut: 'static + Future<Output = S>,
3521 S: 'static,
3522 {
3523 let handle = self.weak_handle();
3524 self.app.spawn(|cx| f(handle, cx))
3525 }
3526}
3527
3528impl<M> AsRef<AppContext> for ModelContext<'_, M> {
3529 fn as_ref(&self) -> &AppContext {
3530 &self.app.cx
3531 }
3532}
3533
3534impl<M> AsMut<MutableAppContext> for ModelContext<'_, M> {
3535 fn as_mut(&mut self) -> &mut MutableAppContext {
3536 self.app
3537 }
3538}
3539
3540impl<M> ReadModel for ModelContext<'_, M> {
3541 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
3542 self.app.read_model(handle)
3543 }
3544}
3545
3546impl<M> UpdateModel for ModelContext<'_, M> {
3547 fn update_model<T: Entity, V>(
3548 &mut self,
3549 handle: &ModelHandle<T>,
3550 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
3551 ) -> V {
3552 self.app.update_model(handle, update)
3553 }
3554}
3555
3556impl<M> UpgradeModelHandle for ModelContext<'_, M> {
3557 fn upgrade_model_handle<T: Entity>(
3558 &self,
3559 handle: &WeakModelHandle<T>,
3560 ) -> Option<ModelHandle<T>> {
3561 self.cx.upgrade_model_handle(handle)
3562 }
3563
3564 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
3565 self.cx.model_handle_is_upgradable(handle)
3566 }
3567
3568 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
3569 self.cx.upgrade_any_model_handle(handle)
3570 }
3571}
3572
3573impl<M> Deref for ModelContext<'_, M> {
3574 type Target = MutableAppContext;
3575
3576 fn deref(&self) -> &Self::Target {
3577 self.app
3578 }
3579}
3580
3581impl<M> DerefMut for ModelContext<'_, M> {
3582 fn deref_mut(&mut self) -> &mut Self::Target {
3583 &mut self.app
3584 }
3585}
3586
3587pub struct ViewContext<'a, T: ?Sized> {
3588 app: &'a mut MutableAppContext,
3589 window_id: usize,
3590 view_id: usize,
3591 view_type: PhantomData<T>,
3592}
3593
3594impl<'a, T: View> ViewContext<'a, T> {
3595 fn new(app: &'a mut MutableAppContext, window_id: usize, view_id: usize) -> Self {
3596 Self {
3597 app,
3598 window_id,
3599 view_id,
3600 view_type: PhantomData,
3601 }
3602 }
3603
3604 pub fn handle(&self) -> ViewHandle<T> {
3605 ViewHandle::new(self.window_id, self.view_id, &self.app.cx.ref_counts)
3606 }
3607
3608 pub fn weak_handle(&self) -> WeakViewHandle<T> {
3609 WeakViewHandle::new(self.window_id, self.view_id)
3610 }
3611
3612 pub fn window_id(&self) -> usize {
3613 self.window_id
3614 }
3615
3616 pub fn view_id(&self) -> usize {
3617 self.view_id
3618 }
3619
3620 pub fn foreground(&self) -> &Rc<executor::Foreground> {
3621 self.app.foreground()
3622 }
3623
3624 pub fn background_executor(&self) -> &Arc<executor::Background> {
3625 &self.app.cx.background
3626 }
3627
3628 pub fn platform(&self) -> Arc<dyn Platform> {
3629 self.app.platform()
3630 }
3631
3632 pub fn show_character_palette(&self) {
3633 self.app.show_character_palette(self.window_id);
3634 }
3635
3636 pub fn minimize_window(&self) {
3637 self.app.minimize_window(self.window_id)
3638 }
3639
3640 pub fn zoom_window(&self) {
3641 self.app.zoom_window(self.window_id)
3642 }
3643
3644 pub fn toggle_full_screen(&self) {
3645 self.app.toggle_window_full_screen(self.window_id)
3646 }
3647
3648 pub fn window_bounds(&self) -> RectF {
3649 self.app.window_bounds(self.window_id)
3650 }
3651
3652 pub fn prompt(
3653 &self,
3654 level: PromptLevel,
3655 msg: &str,
3656 answers: &[&str],
3657 ) -> oneshot::Receiver<usize> {
3658 self.app.prompt(self.window_id, level, msg, answers)
3659 }
3660
3661 pub fn prompt_for_paths(
3662 &self,
3663 options: PathPromptOptions,
3664 ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
3665 self.app.prompt_for_paths(options)
3666 }
3667
3668 pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
3669 self.app.prompt_for_new_path(directory)
3670 }
3671
3672 pub fn debug_elements(&self) -> crate::json::Value {
3673 self.app.debug_elements(self.window_id).unwrap()
3674 }
3675
3676 pub fn focus<S>(&mut self, handle: S)
3677 where
3678 S: Into<AnyViewHandle>,
3679 {
3680 let handle = handle.into();
3681 self.app.focus(handle.window_id, Some(handle.view_id));
3682 }
3683
3684 pub fn focus_self(&mut self) {
3685 self.app.focus(self.window_id, Some(self.view_id));
3686 }
3687
3688 pub fn is_self_focused(&self) -> bool {
3689 self.app.focused_view_id(self.window_id) == Some(self.view_id)
3690 }
3691
3692 pub fn is_child(&self, view: impl Into<AnyViewHandle>) -> bool {
3693 let view = view.into();
3694 if self.window_id != view.window_id {
3695 return false;
3696 }
3697 self.ancestors(view.window_id, view.view_id)
3698 .skip(1) // Skip self id
3699 .any(|parent| parent == self.view_id)
3700 }
3701
3702 pub fn blur(&mut self) {
3703 self.app.focus(self.window_id, None);
3704 }
3705
3706 pub fn set_window_title(&mut self, title: &str) {
3707 let window_id = self.window_id();
3708 if let Some((_, window)) = self.presenters_and_platform_windows.get_mut(&window_id) {
3709 window.set_title(title);
3710 }
3711 }
3712
3713 pub fn set_window_edited(&mut self, edited: bool) {
3714 let window_id = self.window_id();
3715 if let Some((_, window)) = self.presenters_and_platform_windows.get_mut(&window_id) {
3716 window.set_edited(edited);
3717 }
3718 }
3719
3720 pub fn on_window_should_close<F>(&mut self, mut callback: F)
3721 where
3722 F: 'static + FnMut(&mut T, &mut ViewContext<T>) -> bool,
3723 {
3724 let window_id = self.window_id();
3725 let view = self.weak_handle();
3726 self.pending_effects
3727 .push_back(Effect::WindowShouldCloseSubscription {
3728 window_id,
3729 callback: Box::new(move |cx| {
3730 if let Some(view) = view.upgrade(cx) {
3731 view.update(cx, |view, cx| callback(view, cx))
3732 } else {
3733 true
3734 }
3735 }),
3736 });
3737 }
3738
3739 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
3740 where
3741 S: Entity,
3742 F: FnOnce(&mut ModelContext<S>) -> S,
3743 {
3744 self.app.add_model(build_model)
3745 }
3746
3747 pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
3748 where
3749 S: View,
3750 F: FnOnce(&mut ViewContext<S>) -> S,
3751 {
3752 self.app
3753 .build_and_insert_view(self.window_id, ParentId::View(self.view_id), |cx| {
3754 Some(build_view(cx))
3755 })
3756 .unwrap()
3757 }
3758
3759 pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
3760 where
3761 S: View,
3762 F: FnOnce(&mut ViewContext<S>) -> Option<S>,
3763 {
3764 self.app
3765 .build_and_insert_view(self.window_id, ParentId::View(self.view_id), build_view)
3766 }
3767
3768 pub fn reparent(&mut self, view_handle: impl Into<AnyViewHandle>) {
3769 let view_handle = view_handle.into();
3770 if self.window_id != view_handle.window_id {
3771 panic!("Can't reparent view to a view from a different window");
3772 }
3773 self.cx
3774 .parents
3775 .remove(&(view_handle.window_id, view_handle.view_id));
3776 let new_parent_id = self.view_id;
3777 self.cx.parents.insert(
3778 (view_handle.window_id, view_handle.view_id),
3779 ParentId::View(new_parent_id),
3780 );
3781 }
3782
3783 pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
3784 where
3785 V: View,
3786 F: FnOnce(&mut ViewContext<V>) -> V,
3787 {
3788 let window_id = self.window_id;
3789 self.update(|this| {
3790 let root_view = this
3791 .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
3792 .unwrap();
3793 let window = this.cx.windows.get_mut(&window_id).unwrap();
3794 window.root_view = root_view.clone().into();
3795 window.focused_view_id = Some(root_view.id());
3796 root_view
3797 })
3798 }
3799
3800 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
3801 where
3802 E: Entity,
3803 E::Event: 'static,
3804 H: Handle<E>,
3805 F: 'static + FnMut(&mut T, H, &E::Event, &mut ViewContext<T>),
3806 {
3807 let subscriber = self.weak_handle();
3808 self.app
3809 .subscribe_internal(handle, move |emitter, event, cx| {
3810 if let Some(subscriber) = subscriber.upgrade(cx) {
3811 subscriber.update(cx, |subscriber, cx| {
3812 callback(subscriber, emitter, event, cx);
3813 });
3814 true
3815 } else {
3816 false
3817 }
3818 })
3819 }
3820
3821 pub fn observe<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
3822 where
3823 E: Entity,
3824 H: Handle<E>,
3825 F: 'static + FnMut(&mut T, H, &mut ViewContext<T>),
3826 {
3827 let observer = self.weak_handle();
3828 self.app.observe_internal(handle, move |observed, cx| {
3829 if let Some(observer) = observer.upgrade(cx) {
3830 observer.update(cx, |observer, cx| {
3831 callback(observer, observed, cx);
3832 });
3833 true
3834 } else {
3835 false
3836 }
3837 })
3838 }
3839
3840 pub fn observe_focus<F, V>(&mut self, handle: &ViewHandle<V>, mut callback: F) -> Subscription
3841 where
3842 F: 'static + FnMut(&mut T, ViewHandle<V>, bool, &mut ViewContext<T>),
3843 V: View,
3844 {
3845 let observer = self.weak_handle();
3846 self.app
3847 .observe_focus(handle, move |observed, focused, cx| {
3848 if let Some(observer) = observer.upgrade(cx) {
3849 observer.update(cx, |observer, cx| {
3850 callback(observer, observed, focused, cx);
3851 });
3852 true
3853 } else {
3854 false
3855 }
3856 })
3857 }
3858
3859 pub fn observe_release<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
3860 where
3861 E: Entity,
3862 H: Handle<E>,
3863 F: 'static + FnMut(&mut T, &E, &mut ViewContext<T>),
3864 {
3865 let observer = self.weak_handle();
3866 self.app.observe_release(handle, move |released, cx| {
3867 if let Some(observer) = observer.upgrade(cx) {
3868 observer.update(cx, |observer, cx| {
3869 callback(observer, released, cx);
3870 });
3871 }
3872 })
3873 }
3874
3875 pub fn observe_actions<F>(&mut self, mut callback: F) -> Subscription
3876 where
3877 F: 'static + FnMut(&mut T, TypeId, &mut ViewContext<T>),
3878 {
3879 let observer = self.weak_handle();
3880 self.app.observe_actions(move |action_id, cx| {
3881 if let Some(observer) = observer.upgrade(cx) {
3882 observer.update(cx, |observer, cx| {
3883 callback(observer, action_id, cx);
3884 });
3885 }
3886 })
3887 }
3888
3889 pub fn observe_window_activation<F>(&mut self, mut callback: F) -> Subscription
3890 where
3891 F: 'static + FnMut(&mut T, bool, &mut ViewContext<T>),
3892 {
3893 let observer = self.weak_handle();
3894 self.app
3895 .observe_window_activation(self.window_id(), move |active, cx| {
3896 if let Some(observer) = observer.upgrade(cx) {
3897 observer.update(cx, |observer, cx| {
3898 callback(observer, active, cx);
3899 });
3900 true
3901 } else {
3902 false
3903 }
3904 })
3905 }
3906
3907 pub fn observe_fullscreen<F>(&mut self, mut callback: F) -> Subscription
3908 where
3909 F: 'static + FnMut(&mut T, bool, &mut ViewContext<T>),
3910 {
3911 let observer = self.weak_handle();
3912 self.app
3913 .observe_fullscreen(self.window_id(), move |active, cx| {
3914 if let Some(observer) = observer.upgrade(cx) {
3915 observer.update(cx, |observer, cx| {
3916 callback(observer, active, cx);
3917 });
3918 true
3919 } else {
3920 false
3921 }
3922 })
3923 }
3924
3925 pub fn observe_keystroke<F>(&mut self, mut callback: F) -> Subscription
3926 where
3927 F: 'static
3928 + FnMut(
3929 &mut T,
3930 &Keystroke,
3931 Option<&Box<dyn Action>>,
3932 &MatchResult,
3933 &mut ViewContext<T>,
3934 ) -> bool,
3935 {
3936 let observer = self.weak_handle();
3937 self.app.observe_keystrokes(
3938 self.window_id(),
3939 move |keystroke, result, handled_by, cx| {
3940 if let Some(observer) = observer.upgrade(cx) {
3941 observer.update(cx, |observer, cx| {
3942 callback(observer, keystroke, handled_by, result, cx);
3943 });
3944 true
3945 } else {
3946 false
3947 }
3948 },
3949 )
3950 }
3951
3952 pub fn emit(&mut self, payload: T::Event) {
3953 self.app.pending_effects.push_back(Effect::Event {
3954 entity_id: self.view_id,
3955 payload: Box::new(payload),
3956 });
3957 }
3958
3959 pub fn notify(&mut self) {
3960 self.app.notify_view(self.window_id, self.view_id);
3961 }
3962
3963 pub fn dispatch_action(&mut self, action: impl Action) {
3964 self.app
3965 .dispatch_action_at(self.window_id, self.view_id, action)
3966 }
3967
3968 pub fn dispatch_any_action(&mut self, action: Box<dyn Action>) {
3969 self.app
3970 .dispatch_any_action_at(self.window_id, self.view_id, action)
3971 }
3972
3973 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>)) {
3974 let handle = self.handle();
3975 self.app.defer(move |cx| {
3976 handle.update(cx, |view, cx| {
3977 callback(view, cx);
3978 })
3979 })
3980 }
3981
3982 pub fn after_window_update(
3983 &mut self,
3984 callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>),
3985 ) {
3986 let handle = self.handle();
3987 self.app.after_window_update(move |cx| {
3988 handle.update(cx, |view, cx| {
3989 callback(view, cx);
3990 })
3991 })
3992 }
3993
3994 pub fn propagate_action(&mut self) {
3995 self.app.halt_action_dispatch = false;
3996 }
3997
3998 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
3999 where
4000 F: FnOnce(ViewHandle<T>, AsyncAppContext) -> Fut,
4001 Fut: 'static + Future<Output = S>,
4002 S: 'static,
4003 {
4004 let handle = self.handle();
4005 self.app.spawn(|cx| f(handle, cx))
4006 }
4007
4008 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
4009 where
4010 F: FnOnce(WeakViewHandle<T>, AsyncAppContext) -> Fut,
4011 Fut: 'static + Future<Output = S>,
4012 S: 'static,
4013 {
4014 let handle = self.weak_handle();
4015 self.app.spawn(|cx| f(handle, cx))
4016 }
4017}
4018
4019pub struct RenderParams {
4020 pub window_id: usize,
4021 pub view_id: usize,
4022 pub titlebar_height: f32,
4023 pub hovered_region_ids: HashSet<MouseRegionId>,
4024 pub clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
4025 pub refreshing: bool,
4026 pub appearance: Appearance,
4027}
4028
4029pub struct RenderContext<'a, T: View> {
4030 pub(crate) window_id: usize,
4031 pub(crate) view_id: usize,
4032 pub(crate) view_type: PhantomData<T>,
4033 pub(crate) hovered_region_ids: HashSet<MouseRegionId>,
4034 pub(crate) clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
4035 pub app: &'a mut MutableAppContext,
4036 pub titlebar_height: f32,
4037 pub appearance: Appearance,
4038 pub refreshing: bool,
4039}
4040
4041#[derive(Clone, Default)]
4042pub struct MouseState {
4043 hovered: bool,
4044 clicked: Option<MouseButton>,
4045 accessed_hovered: bool,
4046 accessed_clicked: bool,
4047}
4048
4049impl MouseState {
4050 pub fn hovered(&mut self) -> bool {
4051 self.accessed_hovered = true;
4052 self.hovered
4053 }
4054
4055 pub fn clicked(&mut self) -> Option<MouseButton> {
4056 self.accessed_clicked = true;
4057 self.clicked
4058 }
4059
4060 pub fn accessed_hovered(&self) -> bool {
4061 self.accessed_hovered
4062 }
4063
4064 pub fn accessed_clicked(&self) -> bool {
4065 self.accessed_clicked
4066 }
4067}
4068
4069impl<'a, V: View> RenderContext<'a, V> {
4070 fn new(params: RenderParams, app: &'a mut MutableAppContext) -> Self {
4071 Self {
4072 app,
4073 window_id: params.window_id,
4074 view_id: params.view_id,
4075 view_type: PhantomData,
4076 titlebar_height: params.titlebar_height,
4077 hovered_region_ids: params.hovered_region_ids.clone(),
4078 clicked_region_ids: params.clicked_region_ids.clone(),
4079 refreshing: params.refreshing,
4080 appearance: params.appearance,
4081 }
4082 }
4083
4084 pub fn handle(&self) -> WeakViewHandle<V> {
4085 WeakViewHandle::new(self.window_id, self.view_id)
4086 }
4087
4088 pub fn window_id(&self) -> usize {
4089 self.window_id
4090 }
4091
4092 pub fn view_id(&self) -> usize {
4093 self.view_id
4094 }
4095
4096 pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
4097 let region_id = MouseRegionId::new::<Tag>(self.view_id, region_id);
4098 MouseState {
4099 hovered: self.hovered_region_ids.contains(®ion_id),
4100 clicked: self.clicked_region_ids.as_ref().and_then(|(ids, button)| {
4101 if ids.contains(®ion_id) {
4102 Some(*button)
4103 } else {
4104 None
4105 }
4106 }),
4107 accessed_hovered: false,
4108 accessed_clicked: false,
4109 }
4110 }
4111
4112 pub fn element_state<Tag: 'static, T: 'static>(
4113 &mut self,
4114 element_id: usize,
4115 initial: T,
4116 ) -> ElementStateHandle<T> {
4117 let id = ElementStateId {
4118 view_id: self.view_id(),
4119 element_id,
4120 tag: TypeId::of::<Tag>(),
4121 };
4122 self.cx
4123 .element_states
4124 .entry(id)
4125 .or_insert_with(|| Box::new(initial));
4126 ElementStateHandle::new(id, self.frame_count, &self.cx.ref_counts)
4127 }
4128
4129 pub fn default_element_state<Tag: 'static, T: 'static + Default>(
4130 &mut self,
4131 element_id: usize,
4132 ) -> ElementStateHandle<T> {
4133 self.element_state::<Tag, T>(element_id, T::default())
4134 }
4135}
4136
4137impl AsRef<AppContext> for &AppContext {
4138 fn as_ref(&self) -> &AppContext {
4139 self
4140 }
4141}
4142
4143impl<V: View> Deref for RenderContext<'_, V> {
4144 type Target = MutableAppContext;
4145
4146 fn deref(&self) -> &Self::Target {
4147 self.app
4148 }
4149}
4150
4151impl<V: View> DerefMut for RenderContext<'_, V> {
4152 fn deref_mut(&mut self) -> &mut Self::Target {
4153 self.app
4154 }
4155}
4156
4157impl<V: View> ReadModel for RenderContext<'_, V> {
4158 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
4159 self.app.read_model(handle)
4160 }
4161}
4162
4163impl<V: View> UpdateModel for RenderContext<'_, V> {
4164 fn update_model<T: Entity, O>(
4165 &mut self,
4166 handle: &ModelHandle<T>,
4167 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
4168 ) -> O {
4169 self.app.update_model(handle, update)
4170 }
4171}
4172
4173impl<V: View> ReadView for RenderContext<'_, V> {
4174 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
4175 self.app.read_view(handle)
4176 }
4177}
4178
4179impl<M> AsRef<AppContext> for ViewContext<'_, M> {
4180 fn as_ref(&self) -> &AppContext {
4181 &self.app.cx
4182 }
4183}
4184
4185impl<M> Deref for ViewContext<'_, M> {
4186 type Target = MutableAppContext;
4187
4188 fn deref(&self) -> &Self::Target {
4189 self.app
4190 }
4191}
4192
4193impl<M> DerefMut for ViewContext<'_, M> {
4194 fn deref_mut(&mut self) -> &mut Self::Target {
4195 &mut self.app
4196 }
4197}
4198
4199impl<M> AsMut<MutableAppContext> for ViewContext<'_, M> {
4200 fn as_mut(&mut self) -> &mut MutableAppContext {
4201 self.app
4202 }
4203}
4204
4205impl<V> ReadModel for ViewContext<'_, V> {
4206 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
4207 self.app.read_model(handle)
4208 }
4209}
4210
4211impl<V> UpgradeModelHandle for ViewContext<'_, V> {
4212 fn upgrade_model_handle<T: Entity>(
4213 &self,
4214 handle: &WeakModelHandle<T>,
4215 ) -> Option<ModelHandle<T>> {
4216 self.cx.upgrade_model_handle(handle)
4217 }
4218
4219 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
4220 self.cx.model_handle_is_upgradable(handle)
4221 }
4222
4223 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
4224 self.cx.upgrade_any_model_handle(handle)
4225 }
4226}
4227
4228impl<V> UpgradeViewHandle for ViewContext<'_, V> {
4229 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
4230 self.cx.upgrade_view_handle(handle)
4231 }
4232
4233 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
4234 self.cx.upgrade_any_view_handle(handle)
4235 }
4236}
4237
4238impl<V: View> UpgradeViewHandle for RenderContext<'_, V> {
4239 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
4240 self.cx.upgrade_view_handle(handle)
4241 }
4242
4243 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
4244 self.cx.upgrade_any_view_handle(handle)
4245 }
4246}
4247
4248impl<V: View> UpdateModel for ViewContext<'_, V> {
4249 fn update_model<T: Entity, O>(
4250 &mut self,
4251 handle: &ModelHandle<T>,
4252 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
4253 ) -> O {
4254 self.app.update_model(handle, update)
4255 }
4256}
4257
4258impl<V: View> ReadView for ViewContext<'_, V> {
4259 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
4260 self.app.read_view(handle)
4261 }
4262}
4263
4264impl<V: View> UpdateView for ViewContext<'_, V> {
4265 fn update_view<T, S>(
4266 &mut self,
4267 handle: &ViewHandle<T>,
4268 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
4269 ) -> S
4270 where
4271 T: View,
4272 {
4273 self.app.update_view(handle, update)
4274 }
4275}
4276
4277pub trait Handle<T> {
4278 type Weak: 'static;
4279 fn id(&self) -> usize;
4280 fn location(&self) -> EntityLocation;
4281 fn downgrade(&self) -> Self::Weak;
4282 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4283 where
4284 Self: Sized;
4285}
4286
4287pub trait WeakHandle {
4288 fn id(&self) -> usize;
4289}
4290
4291#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
4292pub enum EntityLocation {
4293 Model(usize),
4294 View(usize, usize),
4295}
4296
4297pub struct ModelHandle<T: Entity> {
4298 model_id: usize,
4299 model_type: PhantomData<T>,
4300 ref_counts: Arc<Mutex<RefCounts>>,
4301
4302 #[cfg(any(test, feature = "test-support"))]
4303 handle_id: usize,
4304}
4305
4306impl<T: Entity> ModelHandle<T> {
4307 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4308 ref_counts.lock().inc_model(model_id);
4309
4310 #[cfg(any(test, feature = "test-support"))]
4311 let handle_id = ref_counts
4312 .lock()
4313 .leak_detector
4314 .lock()
4315 .handle_created(Some(type_name::<T>()), model_id);
4316
4317 Self {
4318 model_id,
4319 model_type: PhantomData,
4320 ref_counts: ref_counts.clone(),
4321
4322 #[cfg(any(test, feature = "test-support"))]
4323 handle_id,
4324 }
4325 }
4326
4327 pub fn downgrade(&self) -> WeakModelHandle<T> {
4328 WeakModelHandle::new(self.model_id)
4329 }
4330
4331 pub fn id(&self) -> usize {
4332 self.model_id
4333 }
4334
4335 pub fn read<'a, C: ReadModel>(&self, cx: &'a C) -> &'a T {
4336 cx.read_model(self)
4337 }
4338
4339 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
4340 where
4341 C: ReadModelWith,
4342 F: FnOnce(&T, &AppContext) -> S,
4343 {
4344 let mut read = Some(read);
4345 cx.read_model_with(self, &mut |model, cx| {
4346 let read = read.take().unwrap();
4347 read(model, cx)
4348 })
4349 }
4350
4351 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
4352 where
4353 C: UpdateModel,
4354 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
4355 {
4356 let mut update = Some(update);
4357 cx.update_model(self, &mut |model, cx| {
4358 let update = update.take().unwrap();
4359 update(model, cx)
4360 })
4361 }
4362}
4363
4364impl<T: Entity> Clone for ModelHandle<T> {
4365 fn clone(&self) -> Self {
4366 Self::new(self.model_id, &self.ref_counts)
4367 }
4368}
4369
4370impl<T: Entity> PartialEq for ModelHandle<T> {
4371 fn eq(&self, other: &Self) -> bool {
4372 self.model_id == other.model_id
4373 }
4374}
4375
4376impl<T: Entity> Eq for ModelHandle<T> {}
4377
4378impl<T: Entity> PartialEq<WeakModelHandle<T>> for ModelHandle<T> {
4379 fn eq(&self, other: &WeakModelHandle<T>) -> bool {
4380 self.model_id == other.model_id
4381 }
4382}
4383
4384impl<T: Entity> Hash for ModelHandle<T> {
4385 fn hash<H: Hasher>(&self, state: &mut H) {
4386 self.model_id.hash(state);
4387 }
4388}
4389
4390impl<T: Entity> std::borrow::Borrow<usize> for ModelHandle<T> {
4391 fn borrow(&self) -> &usize {
4392 &self.model_id
4393 }
4394}
4395
4396impl<T: Entity> Debug for ModelHandle<T> {
4397 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4398 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
4399 .field(&self.model_id)
4400 .finish()
4401 }
4402}
4403
4404unsafe impl<T: Entity> Send for ModelHandle<T> {}
4405unsafe impl<T: Entity> Sync for ModelHandle<T> {}
4406
4407impl<T: Entity> Drop for ModelHandle<T> {
4408 fn drop(&mut self) {
4409 let mut ref_counts = self.ref_counts.lock();
4410 ref_counts.dec_model(self.model_id);
4411
4412 #[cfg(any(test, feature = "test-support"))]
4413 ref_counts
4414 .leak_detector
4415 .lock()
4416 .handle_dropped(self.model_id, self.handle_id);
4417 }
4418}
4419
4420impl<T: Entity> Handle<T> for ModelHandle<T> {
4421 type Weak = WeakModelHandle<T>;
4422
4423 fn id(&self) -> usize {
4424 self.model_id
4425 }
4426
4427 fn location(&self) -> EntityLocation {
4428 EntityLocation::Model(self.model_id)
4429 }
4430
4431 fn downgrade(&self) -> Self::Weak {
4432 self.downgrade()
4433 }
4434
4435 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4436 where
4437 Self: Sized,
4438 {
4439 weak.upgrade(cx)
4440 }
4441}
4442
4443pub struct WeakModelHandle<T> {
4444 model_id: usize,
4445 model_type: PhantomData<T>,
4446}
4447
4448impl<T> WeakHandle for WeakModelHandle<T> {
4449 fn id(&self) -> usize {
4450 self.model_id
4451 }
4452}
4453
4454unsafe impl<T> Send for WeakModelHandle<T> {}
4455unsafe impl<T> Sync for WeakModelHandle<T> {}
4456
4457impl<T: Entity> WeakModelHandle<T> {
4458 fn new(model_id: usize) -> Self {
4459 Self {
4460 model_id,
4461 model_type: PhantomData,
4462 }
4463 }
4464
4465 pub fn id(&self) -> usize {
4466 self.model_id
4467 }
4468
4469 pub fn is_upgradable(&self, cx: &impl UpgradeModelHandle) -> bool {
4470 cx.model_handle_is_upgradable(self)
4471 }
4472
4473 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<ModelHandle<T>> {
4474 cx.upgrade_model_handle(self)
4475 }
4476}
4477
4478impl<T> Hash for WeakModelHandle<T> {
4479 fn hash<H: Hasher>(&self, state: &mut H) {
4480 self.model_id.hash(state)
4481 }
4482}
4483
4484impl<T> PartialEq for WeakModelHandle<T> {
4485 fn eq(&self, other: &Self) -> bool {
4486 self.model_id == other.model_id
4487 }
4488}
4489
4490impl<T> Eq for WeakModelHandle<T> {}
4491
4492impl<T: Entity> PartialEq<ModelHandle<T>> for WeakModelHandle<T> {
4493 fn eq(&self, other: &ModelHandle<T>) -> bool {
4494 self.model_id == other.model_id
4495 }
4496}
4497
4498impl<T> Clone for WeakModelHandle<T> {
4499 fn clone(&self) -> Self {
4500 Self {
4501 model_id: self.model_id,
4502 model_type: PhantomData,
4503 }
4504 }
4505}
4506
4507impl<T> Copy for WeakModelHandle<T> {}
4508
4509pub struct ViewHandle<T> {
4510 window_id: usize,
4511 view_id: usize,
4512 view_type: PhantomData<T>,
4513 ref_counts: Arc<Mutex<RefCounts>>,
4514 #[cfg(any(test, feature = "test-support"))]
4515 handle_id: usize,
4516}
4517
4518impl<T: View> ViewHandle<T> {
4519 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4520 ref_counts.lock().inc_view(window_id, view_id);
4521 #[cfg(any(test, feature = "test-support"))]
4522 let handle_id = ref_counts
4523 .lock()
4524 .leak_detector
4525 .lock()
4526 .handle_created(Some(type_name::<T>()), view_id);
4527
4528 Self {
4529 window_id,
4530 view_id,
4531 view_type: PhantomData,
4532 ref_counts: ref_counts.clone(),
4533
4534 #[cfg(any(test, feature = "test-support"))]
4535 handle_id,
4536 }
4537 }
4538
4539 pub fn downgrade(&self) -> WeakViewHandle<T> {
4540 WeakViewHandle::new(self.window_id, self.view_id)
4541 }
4542
4543 pub fn window_id(&self) -> usize {
4544 self.window_id
4545 }
4546
4547 pub fn id(&self) -> usize {
4548 self.view_id
4549 }
4550
4551 pub fn read<'a, C: ReadView>(&self, cx: &'a C) -> &'a T {
4552 cx.read_view(self)
4553 }
4554
4555 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
4556 where
4557 C: ReadViewWith,
4558 F: FnOnce(&T, &AppContext) -> S,
4559 {
4560 let mut read = Some(read);
4561 cx.read_view_with(self, &mut |view, cx| {
4562 let read = read.take().unwrap();
4563 read(view, cx)
4564 })
4565 }
4566
4567 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
4568 where
4569 C: UpdateView,
4570 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
4571 {
4572 let mut update = Some(update);
4573 cx.update_view(self, &mut |view, cx| {
4574 let update = update.take().unwrap();
4575 update(view, cx)
4576 })
4577 }
4578
4579 pub fn defer<C, F>(&self, cx: &mut C, update: F)
4580 where
4581 C: AsMut<MutableAppContext>,
4582 F: 'static + FnOnce(&mut T, &mut ViewContext<T>),
4583 {
4584 let this = self.clone();
4585 cx.as_mut().defer(move |cx| {
4586 this.update(cx, |view, cx| update(view, cx));
4587 });
4588 }
4589
4590 pub fn is_focused(&self, cx: &AppContext) -> bool {
4591 cx.focused_view_id(self.window_id)
4592 .map_or(false, |focused_id| focused_id == self.view_id)
4593 }
4594}
4595
4596impl<T: View> Clone for ViewHandle<T> {
4597 fn clone(&self) -> Self {
4598 ViewHandle::new(self.window_id, self.view_id, &self.ref_counts)
4599 }
4600}
4601
4602impl<T> PartialEq for ViewHandle<T> {
4603 fn eq(&self, other: &Self) -> bool {
4604 self.window_id == other.window_id && self.view_id == other.view_id
4605 }
4606}
4607
4608impl<T> PartialEq<WeakViewHandle<T>> for ViewHandle<T> {
4609 fn eq(&self, other: &WeakViewHandle<T>) -> bool {
4610 self.window_id == other.window_id && self.view_id == other.view_id
4611 }
4612}
4613
4614impl<T> PartialEq<ViewHandle<T>> for WeakViewHandle<T> {
4615 fn eq(&self, other: &ViewHandle<T>) -> bool {
4616 self.window_id == other.window_id && self.view_id == other.view_id
4617 }
4618}
4619
4620impl<T> Eq for ViewHandle<T> {}
4621
4622impl<T> Hash for ViewHandle<T> {
4623 fn hash<H: Hasher>(&self, state: &mut H) {
4624 self.window_id.hash(state);
4625 self.view_id.hash(state);
4626 }
4627}
4628
4629impl<T> Debug for ViewHandle<T> {
4630 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4631 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
4632 .field("window_id", &self.window_id)
4633 .field("view_id", &self.view_id)
4634 .finish()
4635 }
4636}
4637
4638impl<T> Drop for ViewHandle<T> {
4639 fn drop(&mut self) {
4640 self.ref_counts
4641 .lock()
4642 .dec_view(self.window_id, self.view_id);
4643 #[cfg(any(test, feature = "test-support"))]
4644 self.ref_counts
4645 .lock()
4646 .leak_detector
4647 .lock()
4648 .handle_dropped(self.view_id, self.handle_id);
4649 }
4650}
4651
4652impl<T: View> Handle<T> for ViewHandle<T> {
4653 type Weak = WeakViewHandle<T>;
4654
4655 fn id(&self) -> usize {
4656 self.view_id
4657 }
4658
4659 fn location(&self) -> EntityLocation {
4660 EntityLocation::View(self.window_id, self.view_id)
4661 }
4662
4663 fn downgrade(&self) -> Self::Weak {
4664 self.downgrade()
4665 }
4666
4667 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4668 where
4669 Self: Sized,
4670 {
4671 weak.upgrade(cx)
4672 }
4673}
4674
4675pub struct AnyViewHandle {
4676 window_id: usize,
4677 view_id: usize,
4678 view_type: TypeId,
4679 ref_counts: Arc<Mutex<RefCounts>>,
4680
4681 #[cfg(any(test, feature = "test-support"))]
4682 handle_id: usize,
4683}
4684
4685impl AnyViewHandle {
4686 fn new(
4687 window_id: usize,
4688 view_id: usize,
4689 view_type: TypeId,
4690 ref_counts: Arc<Mutex<RefCounts>>,
4691 ) -> Self {
4692 ref_counts.lock().inc_view(window_id, view_id);
4693
4694 #[cfg(any(test, feature = "test-support"))]
4695 let handle_id = ref_counts
4696 .lock()
4697 .leak_detector
4698 .lock()
4699 .handle_created(None, view_id);
4700
4701 Self {
4702 window_id,
4703 view_id,
4704 view_type,
4705 ref_counts,
4706 #[cfg(any(test, feature = "test-support"))]
4707 handle_id,
4708 }
4709 }
4710
4711 pub fn window_id(&self) -> usize {
4712 self.window_id
4713 }
4714
4715 pub fn id(&self) -> usize {
4716 self.view_id
4717 }
4718
4719 pub fn is<T: 'static>(&self) -> bool {
4720 TypeId::of::<T>() == self.view_type
4721 }
4722
4723 pub fn is_focused(&self, cx: &AppContext) -> bool {
4724 cx.focused_view_id(self.window_id)
4725 .map_or(false, |focused_id| focused_id == self.view_id)
4726 }
4727
4728 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
4729 if self.is::<T>() {
4730 let result = Some(ViewHandle {
4731 window_id: self.window_id,
4732 view_id: self.view_id,
4733 ref_counts: self.ref_counts.clone(),
4734 view_type: PhantomData,
4735 #[cfg(any(test, feature = "test-support"))]
4736 handle_id: self.handle_id,
4737 });
4738 unsafe {
4739 Arc::decrement_strong_count(Arc::as_ptr(&self.ref_counts));
4740 }
4741 std::mem::forget(self);
4742 result
4743 } else {
4744 None
4745 }
4746 }
4747
4748 pub fn downgrade(&self) -> AnyWeakViewHandle {
4749 AnyWeakViewHandle {
4750 window_id: self.window_id,
4751 view_id: self.view_id,
4752 view_type: self.view_type,
4753 }
4754 }
4755
4756 pub fn view_type(&self) -> TypeId {
4757 self.view_type
4758 }
4759
4760 pub fn debug_json(&self, cx: &AppContext) -> serde_json::Value {
4761 cx.views
4762 .get(&(self.window_id, self.view_id))
4763 .map_or_else(|| serde_json::Value::Null, |view| view.debug_json(cx))
4764 }
4765}
4766
4767impl Clone for AnyViewHandle {
4768 fn clone(&self) -> Self {
4769 Self::new(
4770 self.window_id,
4771 self.view_id,
4772 self.view_type,
4773 self.ref_counts.clone(),
4774 )
4775 }
4776}
4777
4778impl From<&AnyViewHandle> for AnyViewHandle {
4779 fn from(handle: &AnyViewHandle) -> Self {
4780 handle.clone()
4781 }
4782}
4783
4784impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
4785 fn from(handle: &ViewHandle<T>) -> Self {
4786 Self::new(
4787 handle.window_id,
4788 handle.view_id,
4789 TypeId::of::<T>(),
4790 handle.ref_counts.clone(),
4791 )
4792 }
4793}
4794
4795impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
4796 fn from(handle: ViewHandle<T>) -> Self {
4797 let any_handle = AnyViewHandle {
4798 window_id: handle.window_id,
4799 view_id: handle.view_id,
4800 view_type: TypeId::of::<T>(),
4801 ref_counts: handle.ref_counts.clone(),
4802 #[cfg(any(test, feature = "test-support"))]
4803 handle_id: handle.handle_id,
4804 };
4805
4806 unsafe {
4807 Arc::decrement_strong_count(Arc::as_ptr(&handle.ref_counts));
4808 }
4809 std::mem::forget(handle);
4810 any_handle
4811 }
4812}
4813
4814impl Drop for AnyViewHandle {
4815 fn drop(&mut self) {
4816 self.ref_counts
4817 .lock()
4818 .dec_view(self.window_id, self.view_id);
4819 #[cfg(any(test, feature = "test-support"))]
4820 self.ref_counts
4821 .lock()
4822 .leak_detector
4823 .lock()
4824 .handle_dropped(self.view_id, self.handle_id);
4825 }
4826}
4827
4828pub struct AnyModelHandle {
4829 model_id: usize,
4830 model_type: TypeId,
4831 ref_counts: Arc<Mutex<RefCounts>>,
4832
4833 #[cfg(any(test, feature = "test-support"))]
4834 handle_id: usize,
4835}
4836
4837impl AnyModelHandle {
4838 fn new(model_id: usize, model_type: TypeId, ref_counts: Arc<Mutex<RefCounts>>) -> Self {
4839 ref_counts.lock().inc_model(model_id);
4840
4841 #[cfg(any(test, feature = "test-support"))]
4842 let handle_id = ref_counts
4843 .lock()
4844 .leak_detector
4845 .lock()
4846 .handle_created(None, model_id);
4847
4848 Self {
4849 model_id,
4850 model_type,
4851 ref_counts,
4852
4853 #[cfg(any(test, feature = "test-support"))]
4854 handle_id,
4855 }
4856 }
4857
4858 pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> {
4859 if self.is::<T>() {
4860 let result = Some(ModelHandle {
4861 model_id: self.model_id,
4862 model_type: PhantomData,
4863 ref_counts: self.ref_counts.clone(),
4864
4865 #[cfg(any(test, feature = "test-support"))]
4866 handle_id: self.handle_id,
4867 });
4868 unsafe {
4869 Arc::decrement_strong_count(Arc::as_ptr(&self.ref_counts));
4870 }
4871 std::mem::forget(self);
4872 result
4873 } else {
4874 None
4875 }
4876 }
4877
4878 pub fn downgrade(&self) -> AnyWeakModelHandle {
4879 AnyWeakModelHandle {
4880 model_id: self.model_id,
4881 model_type: self.model_type,
4882 }
4883 }
4884
4885 pub fn is<T: Entity>(&self) -> bool {
4886 self.model_type == TypeId::of::<T>()
4887 }
4888
4889 pub fn model_type(&self) -> TypeId {
4890 self.model_type
4891 }
4892}
4893
4894impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
4895 fn from(handle: ModelHandle<T>) -> Self {
4896 Self::new(
4897 handle.model_id,
4898 TypeId::of::<T>(),
4899 handle.ref_counts.clone(),
4900 )
4901 }
4902}
4903
4904impl Clone for AnyModelHandle {
4905 fn clone(&self) -> Self {
4906 Self::new(self.model_id, self.model_type, self.ref_counts.clone())
4907 }
4908}
4909
4910impl Drop for AnyModelHandle {
4911 fn drop(&mut self) {
4912 let mut ref_counts = self.ref_counts.lock();
4913 ref_counts.dec_model(self.model_id);
4914
4915 #[cfg(any(test, feature = "test-support"))]
4916 ref_counts
4917 .leak_detector
4918 .lock()
4919 .handle_dropped(self.model_id, self.handle_id);
4920 }
4921}
4922
4923#[derive(Hash, PartialEq, Eq, Debug)]
4924pub struct AnyWeakModelHandle {
4925 model_id: usize,
4926 model_type: TypeId,
4927}
4928
4929impl AnyWeakModelHandle {
4930 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<AnyModelHandle> {
4931 cx.upgrade_any_model_handle(self)
4932 }
4933 pub fn model_type(&self) -> TypeId {
4934 self.model_type
4935 }
4936
4937 fn is<T: 'static>(&self) -> bool {
4938 TypeId::of::<T>() == self.model_type
4939 }
4940
4941 pub fn downcast<T: Entity>(&self) -> Option<WeakModelHandle<T>> {
4942 if self.is::<T>() {
4943 let result = Some(WeakModelHandle {
4944 model_id: self.model_id,
4945 model_type: PhantomData,
4946 });
4947
4948 result
4949 } else {
4950 None
4951 }
4952 }
4953}
4954
4955impl<T: Entity> From<WeakModelHandle<T>> for AnyWeakModelHandle {
4956 fn from(handle: WeakModelHandle<T>) -> Self {
4957 AnyWeakModelHandle {
4958 model_id: handle.model_id,
4959 model_type: TypeId::of::<T>(),
4960 }
4961 }
4962}
4963
4964#[derive(Debug)]
4965pub struct WeakViewHandle<T> {
4966 window_id: usize,
4967 view_id: usize,
4968 view_type: PhantomData<T>,
4969}
4970
4971impl<T> WeakHandle for WeakViewHandle<T> {
4972 fn id(&self) -> usize {
4973 self.view_id
4974 }
4975}
4976
4977impl<T: View> WeakViewHandle<T> {
4978 fn new(window_id: usize, view_id: usize) -> Self {
4979 Self {
4980 window_id,
4981 view_id,
4982 view_type: PhantomData,
4983 }
4984 }
4985
4986 pub fn id(&self) -> usize {
4987 self.view_id
4988 }
4989
4990 pub fn window_id(&self) -> usize {
4991 self.window_id
4992 }
4993
4994 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<ViewHandle<T>> {
4995 cx.upgrade_view_handle(self)
4996 }
4997}
4998
4999impl<T> Clone for WeakViewHandle<T> {
5000 fn clone(&self) -> Self {
5001 Self {
5002 window_id: self.window_id,
5003 view_id: self.view_id,
5004 view_type: PhantomData,
5005 }
5006 }
5007}
5008
5009impl<T> PartialEq for WeakViewHandle<T> {
5010 fn eq(&self, other: &Self) -> bool {
5011 self.window_id == other.window_id && self.view_id == other.view_id
5012 }
5013}
5014
5015impl<T> Eq for WeakViewHandle<T> {}
5016
5017impl<T> Hash for WeakViewHandle<T> {
5018 fn hash<H: Hasher>(&self, state: &mut H) {
5019 self.window_id.hash(state);
5020 self.view_id.hash(state);
5021 }
5022}
5023
5024pub struct AnyWeakViewHandle {
5025 window_id: usize,
5026 view_id: usize,
5027 view_type: TypeId,
5028}
5029
5030impl AnyWeakViewHandle {
5031 pub fn id(&self) -> usize {
5032 self.view_id
5033 }
5034
5035 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<AnyViewHandle> {
5036 cx.upgrade_any_view_handle(self)
5037 }
5038}
5039
5040impl<T: View> From<WeakViewHandle<T>> for AnyWeakViewHandle {
5041 fn from(handle: WeakViewHandle<T>) -> Self {
5042 AnyWeakViewHandle {
5043 window_id: handle.window_id,
5044 view_id: handle.view_id,
5045 view_type: TypeId::of::<T>(),
5046 }
5047 }
5048}
5049
5050#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
5051pub struct ElementStateId {
5052 view_id: usize,
5053 element_id: usize,
5054 tag: TypeId,
5055}
5056
5057pub struct ElementStateHandle<T> {
5058 value_type: PhantomData<T>,
5059 id: ElementStateId,
5060 ref_counts: Weak<Mutex<RefCounts>>,
5061}
5062
5063impl<T: 'static> ElementStateHandle<T> {
5064 fn new(id: ElementStateId, frame_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
5065 ref_counts.lock().inc_element_state(id, frame_id);
5066 Self {
5067 value_type: PhantomData,
5068 id,
5069 ref_counts: Arc::downgrade(ref_counts),
5070 }
5071 }
5072
5073 pub fn id(&self) -> ElementStateId {
5074 self.id
5075 }
5076
5077 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
5078 cx.element_states
5079 .get(&self.id)
5080 .unwrap()
5081 .downcast_ref()
5082 .unwrap()
5083 }
5084
5085 pub fn update<C, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R
5086 where
5087 C: DerefMut<Target = MutableAppContext>,
5088 {
5089 let mut element_state = cx.deref_mut().cx.element_states.remove(&self.id).unwrap();
5090 let result = f(element_state.downcast_mut().unwrap(), cx);
5091 cx.deref_mut()
5092 .cx
5093 .element_states
5094 .insert(self.id, element_state);
5095 result
5096 }
5097}
5098
5099impl<T> Drop for ElementStateHandle<T> {
5100 fn drop(&mut self) {
5101 if let Some(ref_counts) = self.ref_counts.upgrade() {
5102 ref_counts.lock().dec_element_state(self.id);
5103 }
5104 }
5105}
5106
5107#[must_use]
5108pub enum Subscription {
5109 Subscription {
5110 id: usize,
5111 entity_id: usize,
5112 subscriptions: Option<Weak<Mapping<usize, SubscriptionCallback>>>,
5113 },
5114 GlobalSubscription {
5115 id: usize,
5116 type_id: TypeId,
5117 subscriptions: Option<Weak<Mapping<TypeId, GlobalSubscriptionCallback>>>,
5118 },
5119 Observation {
5120 id: usize,
5121 entity_id: usize,
5122 observations: Option<Weak<Mapping<usize, ObservationCallback>>>,
5123 },
5124 GlobalObservation {
5125 id: usize,
5126 type_id: TypeId,
5127 observations: Option<Weak<Mapping<TypeId, GlobalObservationCallback>>>,
5128 },
5129 FocusObservation {
5130 id: usize,
5131 view_id: usize,
5132 observations: Option<Weak<Mapping<usize, FocusObservationCallback>>>,
5133 },
5134 WindowActivationObservation {
5135 id: usize,
5136 window_id: usize,
5137 observations: Option<Weak<Mapping<usize, WindowActivationCallback>>>,
5138 },
5139 WindowFullscreenObservation {
5140 id: usize,
5141 window_id: usize,
5142 observations: Option<Weak<Mapping<usize, WindowFullscreenCallback>>>,
5143 },
5144 KeystrokeObservation {
5145 id: usize,
5146 window_id: usize,
5147 observations: Option<Weak<Mapping<usize, KeystrokeCallback>>>,
5148 },
5149
5150 ReleaseObservation {
5151 id: usize,
5152 entity_id: usize,
5153 #[allow(clippy::type_complexity)]
5154 observations:
5155 Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>>,
5156 },
5157 ActionObservation {
5158 id: usize,
5159 observations: Option<Weak<Mutex<BTreeMap<usize, ActionObservationCallback>>>>,
5160 },
5161}
5162
5163impl Subscription {
5164 pub fn detach(&mut self) {
5165 match self {
5166 Subscription::Subscription { subscriptions, .. } => {
5167 subscriptions.take();
5168 }
5169 Subscription::GlobalSubscription { subscriptions, .. } => {
5170 subscriptions.take();
5171 }
5172 Subscription::Observation { observations, .. } => {
5173 observations.take();
5174 }
5175 Subscription::GlobalObservation { observations, .. } => {
5176 observations.take();
5177 }
5178 Subscription::ReleaseObservation { observations, .. } => {
5179 observations.take();
5180 }
5181 Subscription::FocusObservation { observations, .. } => {
5182 observations.take();
5183 }
5184 Subscription::ActionObservation { observations, .. } => {
5185 observations.take();
5186 }
5187 Subscription::KeystrokeObservation { observations, .. } => {
5188 observations.take();
5189 }
5190 Subscription::WindowActivationObservation { observations, .. } => {
5191 observations.take();
5192 }
5193 Subscription::WindowFullscreenObservation { observations, .. } => {
5194 observations.take();
5195 }
5196 }
5197 }
5198}
5199
5200impl Drop for Subscription {
5201 fn drop(&mut self) {
5202 match self {
5203 Subscription::Subscription {
5204 id,
5205 entity_id,
5206 subscriptions,
5207 } => {
5208 if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
5209 match subscriptions
5210 .lock()
5211 .entry(*entity_id)
5212 .or_default()
5213 .entry(*id)
5214 {
5215 btree_map::Entry::Vacant(entry) => {
5216 entry.insert(None);
5217 }
5218 btree_map::Entry::Occupied(entry) => {
5219 entry.remove();
5220 }
5221 }
5222 }
5223 }
5224 Subscription::GlobalSubscription {
5225 id,
5226 type_id,
5227 subscriptions,
5228 } => {
5229 if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
5230 match subscriptions.lock().entry(*type_id).or_default().entry(*id) {
5231 btree_map::Entry::Vacant(entry) => {
5232 entry.insert(None);
5233 }
5234 btree_map::Entry::Occupied(entry) => {
5235 entry.remove();
5236 }
5237 }
5238 }
5239 }
5240 Subscription::Observation {
5241 id,
5242 entity_id,
5243 observations,
5244 } => {
5245 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5246 match observations
5247 .lock()
5248 .entry(*entity_id)
5249 .or_default()
5250 .entry(*id)
5251 {
5252 btree_map::Entry::Vacant(entry) => {
5253 entry.insert(None);
5254 }
5255 btree_map::Entry::Occupied(entry) => {
5256 entry.remove();
5257 }
5258 }
5259 }
5260 }
5261 Subscription::GlobalObservation {
5262 id,
5263 type_id,
5264 observations,
5265 } => {
5266 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5267 match observations.lock().entry(*type_id).or_default().entry(*id) {
5268 collections::btree_map::Entry::Vacant(entry) => {
5269 entry.insert(None);
5270 }
5271 collections::btree_map::Entry::Occupied(entry) => {
5272 entry.remove();
5273 }
5274 }
5275 }
5276 }
5277 Subscription::ReleaseObservation {
5278 id,
5279 entity_id,
5280 observations,
5281 } => {
5282 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5283 if let Some(observations) = observations.lock().get_mut(entity_id) {
5284 observations.remove(id);
5285 }
5286 }
5287 }
5288 Subscription::FocusObservation {
5289 id,
5290 view_id,
5291 observations,
5292 } => {
5293 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5294 match observations.lock().entry(*view_id).or_default().entry(*id) {
5295 btree_map::Entry::Vacant(entry) => {
5296 entry.insert(None);
5297 }
5298 btree_map::Entry::Occupied(entry) => {
5299 entry.remove();
5300 }
5301 }
5302 }
5303 }
5304 Subscription::ActionObservation { id, observations } => {
5305 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5306 observations.lock().remove(id);
5307 }
5308 }
5309 Subscription::KeystrokeObservation {
5310 id,
5311 window_id,
5312 observations,
5313 } => {
5314 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5315 match observations
5316 .lock()
5317 .entry(*window_id)
5318 .or_default()
5319 .entry(*id)
5320 {
5321 btree_map::Entry::Vacant(entry) => {
5322 entry.insert(None);
5323 }
5324 btree_map::Entry::Occupied(entry) => {
5325 entry.remove();
5326 }
5327 }
5328 }
5329 }
5330 Subscription::WindowActivationObservation {
5331 id,
5332 window_id,
5333 observations,
5334 } => {
5335 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5336 match observations
5337 .lock()
5338 .entry(*window_id)
5339 .or_default()
5340 .entry(*id)
5341 {
5342 btree_map::Entry::Vacant(entry) => {
5343 entry.insert(None);
5344 }
5345 btree_map::Entry::Occupied(entry) => {
5346 entry.remove();
5347 }
5348 }
5349 }
5350 }
5351 Subscription::WindowFullscreenObservation {
5352 id,
5353 window_id,
5354 observations,
5355 } => {
5356 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5357 match observations
5358 .lock()
5359 .entry(*window_id)
5360 .or_default()
5361 .entry(*id)
5362 {
5363 btree_map::Entry::Vacant(entry) => {
5364 entry.insert(None);
5365 }
5366 btree_map::Entry::Occupied(entry) => {
5367 entry.remove();
5368 }
5369 }
5370 }
5371 }
5372 }
5373 }
5374}
5375
5376lazy_static! {
5377 static ref LEAK_BACKTRACE: bool =
5378 std::env::var("LEAK_BACKTRACE").map_or(false, |b| !b.is_empty());
5379}
5380
5381#[cfg(any(test, feature = "test-support"))]
5382#[derive(Default)]
5383pub struct LeakDetector {
5384 next_handle_id: usize,
5385 #[allow(clippy::type_complexity)]
5386 handle_backtraces: HashMap<
5387 usize,
5388 (
5389 Option<&'static str>,
5390 HashMap<usize, Option<backtrace::Backtrace>>,
5391 ),
5392 >,
5393}
5394
5395#[cfg(any(test, feature = "test-support"))]
5396impl LeakDetector {
5397 fn handle_created(&mut self, type_name: Option<&'static str>, entity_id: usize) -> usize {
5398 let handle_id = post_inc(&mut self.next_handle_id);
5399 let entry = self.handle_backtraces.entry(entity_id).or_default();
5400 let backtrace = if *LEAK_BACKTRACE {
5401 Some(backtrace::Backtrace::new_unresolved())
5402 } else {
5403 None
5404 };
5405 if let Some(type_name) = type_name {
5406 entry.0.get_or_insert(type_name);
5407 }
5408 entry.1.insert(handle_id, backtrace);
5409 handle_id
5410 }
5411
5412 fn handle_dropped(&mut self, entity_id: usize, handle_id: usize) {
5413 if let Some((_, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
5414 assert!(backtraces.remove(&handle_id).is_some());
5415 if backtraces.is_empty() {
5416 self.handle_backtraces.remove(&entity_id);
5417 }
5418 }
5419 }
5420
5421 pub fn assert_dropped(&mut self, entity_id: usize) {
5422 if let Some((type_name, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
5423 for trace in backtraces.values_mut().flatten() {
5424 trace.resolve();
5425 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
5426 }
5427
5428 let hint = if *LEAK_BACKTRACE {
5429 ""
5430 } else {
5431 " – set LEAK_BACKTRACE=1 for more information"
5432 };
5433
5434 panic!(
5435 "{} handles to {} {} still exist{}",
5436 backtraces.len(),
5437 type_name.unwrap_or("entity"),
5438 entity_id,
5439 hint
5440 );
5441 }
5442 }
5443
5444 pub fn detect(&mut self) {
5445 let mut found_leaks = false;
5446 for (id, (type_name, backtraces)) in self.handle_backtraces.iter_mut() {
5447 eprintln!(
5448 "leaked {} handles to {} {}",
5449 backtraces.len(),
5450 type_name.unwrap_or("entity"),
5451 id
5452 );
5453 for trace in backtraces.values_mut().flatten() {
5454 trace.resolve();
5455 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
5456 }
5457 found_leaks = true;
5458 }
5459
5460 let hint = if *LEAK_BACKTRACE {
5461 ""
5462 } else {
5463 " – set LEAK_BACKTRACE=1 for more information"
5464 };
5465 assert!(!found_leaks, "detected leaked handles{}", hint);
5466 }
5467}
5468
5469#[derive(Default)]
5470struct RefCounts {
5471 entity_counts: HashMap<usize, usize>,
5472 element_state_counts: HashMap<ElementStateId, ElementStateRefCount>,
5473 dropped_models: HashSet<usize>,
5474 dropped_views: HashSet<(usize, usize)>,
5475 dropped_element_states: HashSet<ElementStateId>,
5476
5477 #[cfg(any(test, feature = "test-support"))]
5478 leak_detector: Arc<Mutex<LeakDetector>>,
5479}
5480
5481struct ElementStateRefCount {
5482 ref_count: usize,
5483 frame_id: usize,
5484}
5485
5486impl RefCounts {
5487 fn inc_model(&mut self, model_id: usize) {
5488 match self.entity_counts.entry(model_id) {
5489 Entry::Occupied(mut entry) => {
5490 *entry.get_mut() += 1;
5491 }
5492 Entry::Vacant(entry) => {
5493 entry.insert(1);
5494 self.dropped_models.remove(&model_id);
5495 }
5496 }
5497 }
5498
5499 fn inc_view(&mut self, window_id: usize, view_id: usize) {
5500 match self.entity_counts.entry(view_id) {
5501 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
5502 Entry::Vacant(entry) => {
5503 entry.insert(1);
5504 self.dropped_views.remove(&(window_id, view_id));
5505 }
5506 }
5507 }
5508
5509 fn inc_element_state(&mut self, id: ElementStateId, frame_id: usize) {
5510 match self.element_state_counts.entry(id) {
5511 Entry::Occupied(mut entry) => {
5512 let entry = entry.get_mut();
5513 if entry.frame_id == frame_id || entry.ref_count >= 2 {
5514 panic!("used the same element state more than once in the same frame");
5515 }
5516 entry.ref_count += 1;
5517 entry.frame_id = frame_id;
5518 }
5519 Entry::Vacant(entry) => {
5520 entry.insert(ElementStateRefCount {
5521 ref_count: 1,
5522 frame_id,
5523 });
5524 self.dropped_element_states.remove(&id);
5525 }
5526 }
5527 }
5528
5529 fn dec_model(&mut self, model_id: usize) {
5530 let count = self.entity_counts.get_mut(&model_id).unwrap();
5531 *count -= 1;
5532 if *count == 0 {
5533 self.entity_counts.remove(&model_id);
5534 self.dropped_models.insert(model_id);
5535 }
5536 }
5537
5538 fn dec_view(&mut self, window_id: usize, view_id: usize) {
5539 let count = self.entity_counts.get_mut(&view_id).unwrap();
5540 *count -= 1;
5541 if *count == 0 {
5542 self.entity_counts.remove(&view_id);
5543 self.dropped_views.insert((window_id, view_id));
5544 }
5545 }
5546
5547 fn dec_element_state(&mut self, id: ElementStateId) {
5548 let entry = self.element_state_counts.get_mut(&id).unwrap();
5549 entry.ref_count -= 1;
5550 if entry.ref_count == 0 {
5551 self.element_state_counts.remove(&id);
5552 self.dropped_element_states.insert(id);
5553 }
5554 }
5555
5556 fn is_entity_alive(&self, entity_id: usize) -> bool {
5557 self.entity_counts.contains_key(&entity_id)
5558 }
5559
5560 fn take_dropped(
5561 &mut self,
5562 ) -> (
5563 HashSet<usize>,
5564 HashSet<(usize, usize)>,
5565 HashSet<ElementStateId>,
5566 ) {
5567 (
5568 std::mem::take(&mut self.dropped_models),
5569 std::mem::take(&mut self.dropped_views),
5570 std::mem::take(&mut self.dropped_element_states),
5571 )
5572 }
5573}
5574
5575#[cfg(test)]
5576mod tests {
5577 use super::*;
5578 use crate::{actions, elements::*, impl_actions, MouseButton, MouseButtonEvent};
5579 use serde::Deserialize;
5580 use smol::future::poll_once;
5581 use std::{
5582 cell::Cell,
5583 sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
5584 };
5585
5586 #[crate::test(self)]
5587 fn test_model_handles(cx: &mut MutableAppContext) {
5588 struct Model {
5589 other: Option<ModelHandle<Model>>,
5590 events: Vec<String>,
5591 }
5592
5593 impl Entity for Model {
5594 type Event = usize;
5595 }
5596
5597 impl Model {
5598 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
5599 if let Some(other) = other.as_ref() {
5600 cx.observe(other, |me, _, _| {
5601 me.events.push("notified".into());
5602 })
5603 .detach();
5604 cx.subscribe(other, |me, _, event, _| {
5605 me.events.push(format!("observed event {}", event));
5606 })
5607 .detach();
5608 }
5609
5610 Self {
5611 other,
5612 events: Vec::new(),
5613 }
5614 }
5615 }
5616
5617 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
5618 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
5619 assert_eq!(cx.cx.models.len(), 2);
5620
5621 handle_1.update(cx, |model, cx| {
5622 model.events.push("updated".into());
5623 cx.emit(1);
5624 cx.notify();
5625 cx.emit(2);
5626 });
5627 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5628 assert_eq!(
5629 handle_2.read(cx).events,
5630 vec![
5631 "observed event 1".to_string(),
5632 "notified".to_string(),
5633 "observed event 2".to_string(),
5634 ]
5635 );
5636
5637 handle_2.update(cx, |model, _| {
5638 drop(handle_1);
5639 model.other.take();
5640 });
5641
5642 assert_eq!(cx.cx.models.len(), 1);
5643 assert!(cx.subscriptions.is_empty());
5644 assert!(cx.observations.is_empty());
5645 }
5646
5647 #[crate::test(self)]
5648 fn test_model_events(cx: &mut MutableAppContext) {
5649 #[derive(Default)]
5650 struct Model {
5651 events: Vec<usize>,
5652 }
5653
5654 impl Entity for Model {
5655 type Event = usize;
5656 }
5657
5658 let handle_1 = cx.add_model(|_| Model::default());
5659 let handle_2 = cx.add_model(|_| Model::default());
5660
5661 handle_1.update(cx, |_, cx| {
5662 cx.subscribe(&handle_2, move |model: &mut Model, emitter, event, cx| {
5663 model.events.push(*event);
5664
5665 cx.subscribe(&emitter, |model, _, event, _| {
5666 model.events.push(*event * 2);
5667 })
5668 .detach();
5669 })
5670 .detach();
5671 });
5672
5673 handle_2.update(cx, |_, c| c.emit(7));
5674 assert_eq!(handle_1.read(cx).events, vec![7]);
5675
5676 handle_2.update(cx, |_, c| c.emit(5));
5677 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
5678 }
5679
5680 #[crate::test(self)]
5681 fn test_model_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
5682 #[derive(Default)]
5683 struct Model;
5684
5685 impl Entity for Model {
5686 type Event = ();
5687 }
5688
5689 let events = Rc::new(RefCell::new(Vec::new()));
5690 cx.add_model(|cx| {
5691 drop(cx.subscribe(&cx.handle(), {
5692 let events = events.clone();
5693 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
5694 }));
5695 cx.subscribe(&cx.handle(), {
5696 let events = events.clone();
5697 move |_, _, _, _| events.borrow_mut().push("before emit")
5698 })
5699 .detach();
5700 cx.emit(());
5701 cx.subscribe(&cx.handle(), {
5702 let events = events.clone();
5703 move |_, _, _, _| events.borrow_mut().push("after emit")
5704 })
5705 .detach();
5706 Model
5707 });
5708 assert_eq!(*events.borrow(), ["before emit"]);
5709 }
5710
5711 #[crate::test(self)]
5712 fn test_observe_and_notify_from_model(cx: &mut MutableAppContext) {
5713 #[derive(Default)]
5714 struct Model {
5715 count: usize,
5716 events: Vec<usize>,
5717 }
5718
5719 impl Entity for Model {
5720 type Event = ();
5721 }
5722
5723 let handle_1 = cx.add_model(|_| Model::default());
5724 let handle_2 = cx.add_model(|_| Model::default());
5725
5726 handle_1.update(cx, |_, c| {
5727 c.observe(&handle_2, move |model, observed, c| {
5728 model.events.push(observed.read(c).count);
5729 c.observe(&observed, |model, observed, c| {
5730 model.events.push(observed.read(c).count * 2);
5731 })
5732 .detach();
5733 })
5734 .detach();
5735 });
5736
5737 handle_2.update(cx, |model, c| {
5738 model.count = 7;
5739 c.notify()
5740 });
5741 assert_eq!(handle_1.read(cx).events, vec![7]);
5742
5743 handle_2.update(cx, |model, c| {
5744 model.count = 5;
5745 c.notify()
5746 });
5747 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10])
5748 }
5749
5750 #[crate::test(self)]
5751 fn test_model_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
5752 #[derive(Default)]
5753 struct Model;
5754
5755 impl Entity for Model {
5756 type Event = ();
5757 }
5758
5759 let events = Rc::new(RefCell::new(Vec::new()));
5760 cx.add_model(|cx| {
5761 drop(cx.observe(&cx.handle(), {
5762 let events = events.clone();
5763 move |_, _, _| events.borrow_mut().push("dropped before flush")
5764 }));
5765 cx.observe(&cx.handle(), {
5766 let events = events.clone();
5767 move |_, _, _| events.borrow_mut().push("before notify")
5768 })
5769 .detach();
5770 cx.notify();
5771 cx.observe(&cx.handle(), {
5772 let events = events.clone();
5773 move |_, _, _| events.borrow_mut().push("after notify")
5774 })
5775 .detach();
5776 Model
5777 });
5778 assert_eq!(*events.borrow(), ["before notify"]);
5779 }
5780
5781 #[crate::test(self)]
5782 fn test_defer_and_after_window_update(cx: &mut MutableAppContext) {
5783 struct View {
5784 render_count: usize,
5785 }
5786
5787 impl Entity for View {
5788 type Event = usize;
5789 }
5790
5791 impl super::View for View {
5792 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5793 post_inc(&mut self.render_count);
5794 Empty::new().boxed()
5795 }
5796
5797 fn ui_name() -> &'static str {
5798 "View"
5799 }
5800 }
5801
5802 let (_, view) = cx.add_window(Default::default(), |_| View { render_count: 0 });
5803 let called_defer = Rc::new(AtomicBool::new(false));
5804 let called_after_window_update = Rc::new(AtomicBool::new(false));
5805
5806 view.update(cx, |this, cx| {
5807 assert_eq!(this.render_count, 1);
5808 cx.defer({
5809 let called_defer = called_defer.clone();
5810 move |this, _| {
5811 assert_eq!(this.render_count, 1);
5812 called_defer.store(true, SeqCst);
5813 }
5814 });
5815 cx.after_window_update({
5816 let called_after_window_update = called_after_window_update.clone();
5817 move |this, cx| {
5818 assert_eq!(this.render_count, 2);
5819 called_after_window_update.store(true, SeqCst);
5820 cx.notify();
5821 }
5822 });
5823 assert!(!called_defer.load(SeqCst));
5824 assert!(!called_after_window_update.load(SeqCst));
5825 cx.notify();
5826 });
5827
5828 assert!(called_defer.load(SeqCst));
5829 assert!(called_after_window_update.load(SeqCst));
5830 assert_eq!(view.read(cx).render_count, 3);
5831 }
5832
5833 #[crate::test(self)]
5834 fn test_view_handles(cx: &mut MutableAppContext) {
5835 struct View {
5836 other: Option<ViewHandle<View>>,
5837 events: Vec<String>,
5838 }
5839
5840 impl Entity for View {
5841 type Event = usize;
5842 }
5843
5844 impl super::View for View {
5845 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5846 Empty::new().boxed()
5847 }
5848
5849 fn ui_name() -> &'static str {
5850 "View"
5851 }
5852 }
5853
5854 impl View {
5855 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
5856 if let Some(other) = other.as_ref() {
5857 cx.subscribe(other, |me, _, event, _| {
5858 me.events.push(format!("observed event {}", event));
5859 })
5860 .detach();
5861 }
5862 Self {
5863 other,
5864 events: Vec::new(),
5865 }
5866 }
5867 }
5868
5869 let (_, root_view) = cx.add_window(Default::default(), |cx| View::new(None, cx));
5870 let handle_1 = cx.add_view(&root_view, |cx| View::new(None, cx));
5871 let handle_2 = cx.add_view(&root_view, |cx| View::new(Some(handle_1.clone()), cx));
5872 assert_eq!(cx.cx.views.len(), 3);
5873
5874 handle_1.update(cx, |view, cx| {
5875 view.events.push("updated".into());
5876 cx.emit(1);
5877 cx.emit(2);
5878 });
5879 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5880 assert_eq!(
5881 handle_2.read(cx).events,
5882 vec![
5883 "observed event 1".to_string(),
5884 "observed event 2".to_string(),
5885 ]
5886 );
5887
5888 handle_2.update(cx, |view, _| {
5889 drop(handle_1);
5890 view.other.take();
5891 });
5892
5893 assert_eq!(cx.cx.views.len(), 2);
5894 assert!(cx.subscriptions.is_empty());
5895 assert!(cx.observations.is_empty());
5896 }
5897
5898 #[crate::test(self)]
5899 fn test_add_window(cx: &mut MutableAppContext) {
5900 struct View {
5901 mouse_down_count: Arc<AtomicUsize>,
5902 }
5903
5904 impl Entity for View {
5905 type Event = ();
5906 }
5907
5908 impl super::View for View {
5909 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
5910 enum Handler {}
5911 let mouse_down_count = self.mouse_down_count.clone();
5912 MouseEventHandler::<Handler>::new(0, cx, |_, _| Empty::new().boxed())
5913 .on_down(MouseButton::Left, move |_, _| {
5914 mouse_down_count.fetch_add(1, SeqCst);
5915 })
5916 .boxed()
5917 }
5918
5919 fn ui_name() -> &'static str {
5920 "View"
5921 }
5922 }
5923
5924 let mouse_down_count = Arc::new(AtomicUsize::new(0));
5925 let (window_id, _) = cx.add_window(Default::default(), |_| View {
5926 mouse_down_count: mouse_down_count.clone(),
5927 });
5928 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
5929 // Ensure window's root element is in a valid lifecycle state.
5930 presenter.borrow_mut().dispatch_event(
5931 Event::MouseDown(MouseButtonEvent {
5932 position: Default::default(),
5933 button: MouseButton::Left,
5934 modifiers: Default::default(),
5935 click_count: 1,
5936 }),
5937 false,
5938 cx,
5939 );
5940 assert_eq!(mouse_down_count.load(SeqCst), 1);
5941 }
5942
5943 #[crate::test(self)]
5944 fn test_entity_release_hooks(cx: &mut MutableAppContext) {
5945 struct Model {
5946 released: Rc<Cell<bool>>,
5947 }
5948
5949 struct View {
5950 released: Rc<Cell<bool>>,
5951 }
5952
5953 impl Entity for Model {
5954 type Event = ();
5955
5956 fn release(&mut self, _: &mut MutableAppContext) {
5957 self.released.set(true);
5958 }
5959 }
5960
5961 impl Entity for View {
5962 type Event = ();
5963
5964 fn release(&mut self, _: &mut MutableAppContext) {
5965 self.released.set(true);
5966 }
5967 }
5968
5969 impl super::View for View {
5970 fn ui_name() -> &'static str {
5971 "View"
5972 }
5973
5974 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5975 Empty::new().boxed()
5976 }
5977 }
5978
5979 let model_released = Rc::new(Cell::new(false));
5980 let model_release_observed = Rc::new(Cell::new(false));
5981 let view_released = Rc::new(Cell::new(false));
5982 let view_release_observed = Rc::new(Cell::new(false));
5983
5984 let model = cx.add_model(|_| Model {
5985 released: model_released.clone(),
5986 });
5987 let (window_id, view) = cx.add_window(Default::default(), |_| View {
5988 released: view_released.clone(),
5989 });
5990 assert!(!model_released.get());
5991 assert!(!view_released.get());
5992
5993 cx.observe_release(&model, {
5994 let model_release_observed = model_release_observed.clone();
5995 move |_, _| model_release_observed.set(true)
5996 })
5997 .detach();
5998 cx.observe_release(&view, {
5999 let view_release_observed = view_release_observed.clone();
6000 move |_, _| view_release_observed.set(true)
6001 })
6002 .detach();
6003
6004 cx.update(move |_| {
6005 drop(model);
6006 });
6007 assert!(model_released.get());
6008 assert!(model_release_observed.get());
6009
6010 drop(view);
6011 cx.remove_window(window_id);
6012 assert!(view_released.get());
6013 assert!(view_release_observed.get());
6014 }
6015
6016 #[crate::test(self)]
6017 fn test_view_events(cx: &mut MutableAppContext) {
6018 #[derive(Default)]
6019 struct View {
6020 events: Vec<usize>,
6021 }
6022
6023 impl Entity for View {
6024 type Event = usize;
6025 }
6026
6027 impl super::View for View {
6028 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6029 Empty::new().boxed()
6030 }
6031
6032 fn ui_name() -> &'static str {
6033 "View"
6034 }
6035 }
6036
6037 struct Model;
6038
6039 impl Entity for Model {
6040 type Event = usize;
6041 }
6042
6043 let (_, handle_1) = cx.add_window(Default::default(), |_| View::default());
6044 let handle_2 = cx.add_view(&handle_1, |_| View::default());
6045 let handle_3 = cx.add_model(|_| Model);
6046
6047 handle_1.update(cx, |_, cx| {
6048 cx.subscribe(&handle_2, move |me, emitter, event, cx| {
6049 me.events.push(*event);
6050
6051 cx.subscribe(&emitter, |me, _, event, _| {
6052 me.events.push(*event * 2);
6053 })
6054 .detach();
6055 })
6056 .detach();
6057
6058 cx.subscribe(&handle_3, |me, _, event, _| {
6059 me.events.push(*event);
6060 })
6061 .detach();
6062 });
6063
6064 handle_2.update(cx, |_, c| c.emit(7));
6065 assert_eq!(handle_1.read(cx).events, vec![7]);
6066
6067 handle_2.update(cx, |_, c| c.emit(5));
6068 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
6069
6070 handle_3.update(cx, |_, c| c.emit(9));
6071 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10, 9]);
6072 }
6073
6074 #[crate::test(self)]
6075 fn test_global_events(cx: &mut MutableAppContext) {
6076 #[derive(Clone, Debug, Eq, PartialEq)]
6077 struct GlobalEvent(u64);
6078
6079 let events = Rc::new(RefCell::new(Vec::new()));
6080 let first_subscription;
6081 let second_subscription;
6082
6083 {
6084 let events = events.clone();
6085 first_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
6086 events.borrow_mut().push(("First", e.clone()));
6087 });
6088 }
6089
6090 {
6091 let events = events.clone();
6092 second_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
6093 events.borrow_mut().push(("Second", e.clone()));
6094 });
6095 }
6096
6097 cx.update(|cx| {
6098 cx.emit_global(GlobalEvent(1));
6099 cx.emit_global(GlobalEvent(2));
6100 });
6101
6102 drop(first_subscription);
6103
6104 cx.update(|cx| {
6105 cx.emit_global(GlobalEvent(3));
6106 });
6107
6108 drop(second_subscription);
6109
6110 cx.update(|cx| {
6111 cx.emit_global(GlobalEvent(4));
6112 });
6113
6114 assert_eq!(
6115 &*events.borrow(),
6116 &[
6117 ("First", GlobalEvent(1)),
6118 ("Second", GlobalEvent(1)),
6119 ("First", GlobalEvent(2)),
6120 ("Second", GlobalEvent(2)),
6121 ("Second", GlobalEvent(3)),
6122 ]
6123 );
6124 }
6125
6126 #[crate::test(self)]
6127 fn test_global_events_emitted_before_subscription_in_same_update_cycle(
6128 cx: &mut MutableAppContext,
6129 ) {
6130 let events = Rc::new(RefCell::new(Vec::new()));
6131 cx.update(|cx| {
6132 {
6133 let events = events.clone();
6134 drop(cx.subscribe_global(move |_: &(), _| {
6135 events.borrow_mut().push("dropped before emit");
6136 }));
6137 }
6138
6139 {
6140 let events = events.clone();
6141 cx.subscribe_global(move |_: &(), _| {
6142 events.borrow_mut().push("before emit");
6143 })
6144 .detach();
6145 }
6146
6147 cx.emit_global(());
6148
6149 {
6150 let events = events.clone();
6151 cx.subscribe_global(move |_: &(), _| {
6152 events.borrow_mut().push("after emit");
6153 })
6154 .detach();
6155 }
6156 });
6157
6158 assert_eq!(*events.borrow(), ["before emit"]);
6159 }
6160
6161 #[crate::test(self)]
6162 fn test_global_nested_events(cx: &mut MutableAppContext) {
6163 #[derive(Clone, Debug, Eq, PartialEq)]
6164 struct GlobalEvent(u64);
6165
6166 let events = Rc::new(RefCell::new(Vec::new()));
6167
6168 {
6169 let events = events.clone();
6170 cx.subscribe_global(move |e: &GlobalEvent, cx| {
6171 events.borrow_mut().push(("Outer", e.clone()));
6172
6173 if e.0 == 1 {
6174 let events = events.clone();
6175 cx.subscribe_global(move |e: &GlobalEvent, _| {
6176 events.borrow_mut().push(("Inner", e.clone()));
6177 })
6178 .detach();
6179 }
6180 })
6181 .detach();
6182 }
6183
6184 cx.update(|cx| {
6185 cx.emit_global(GlobalEvent(1));
6186 cx.emit_global(GlobalEvent(2));
6187 cx.emit_global(GlobalEvent(3));
6188 });
6189 cx.update(|cx| {
6190 cx.emit_global(GlobalEvent(4));
6191 });
6192
6193 assert_eq!(
6194 &*events.borrow(),
6195 &[
6196 ("Outer", GlobalEvent(1)),
6197 ("Outer", GlobalEvent(2)),
6198 ("Outer", GlobalEvent(3)),
6199 ("Outer", GlobalEvent(4)),
6200 ("Inner", GlobalEvent(4)),
6201 ]
6202 );
6203 }
6204
6205 #[crate::test(self)]
6206 fn test_global(cx: &mut MutableAppContext) {
6207 type Global = usize;
6208
6209 let observation_count = Rc::new(RefCell::new(0));
6210 let subscription = cx.observe_global::<Global, _>({
6211 let observation_count = observation_count.clone();
6212 move |_| {
6213 *observation_count.borrow_mut() += 1;
6214 }
6215 });
6216
6217 assert!(!cx.has_global::<Global>());
6218 assert_eq!(cx.default_global::<Global>(), &0);
6219 assert_eq!(*observation_count.borrow(), 1);
6220 assert!(cx.has_global::<Global>());
6221 assert_eq!(
6222 cx.update_global::<Global, _, _>(|global, _| {
6223 *global = 1;
6224 "Update Result"
6225 }),
6226 "Update Result"
6227 );
6228 assert_eq!(*observation_count.borrow(), 2);
6229 assert_eq!(cx.global::<Global>(), &1);
6230
6231 drop(subscription);
6232 cx.update_global::<Global, _, _>(|global, _| {
6233 *global = 2;
6234 });
6235 assert_eq!(*observation_count.borrow(), 2);
6236
6237 type OtherGlobal = f32;
6238
6239 let observation_count = Rc::new(RefCell::new(0));
6240 cx.observe_global::<OtherGlobal, _>({
6241 let observation_count = observation_count.clone();
6242 move |_| {
6243 *observation_count.borrow_mut() += 1;
6244 }
6245 })
6246 .detach();
6247
6248 assert_eq!(
6249 cx.update_default_global::<OtherGlobal, _, _>(|global, _| {
6250 assert_eq!(global, &0.0);
6251 *global = 2.0;
6252 "Default update result"
6253 }),
6254 "Default update result"
6255 );
6256 assert_eq!(cx.global::<OtherGlobal>(), &2.0);
6257 assert_eq!(*observation_count.borrow(), 1);
6258 }
6259
6260 #[crate::test(self)]
6261 fn test_dropping_subscribers(cx: &mut MutableAppContext) {
6262 struct View;
6263
6264 impl Entity for View {
6265 type Event = ();
6266 }
6267
6268 impl super::View for View {
6269 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6270 Empty::new().boxed()
6271 }
6272
6273 fn ui_name() -> &'static str {
6274 "View"
6275 }
6276 }
6277
6278 struct Model;
6279
6280 impl Entity for Model {
6281 type Event = ();
6282 }
6283
6284 let (_, root_view) = cx.add_window(Default::default(), |_| View);
6285 let observing_view = cx.add_view(&root_view, |_| View);
6286 let emitting_view = cx.add_view(&root_view, |_| View);
6287 let observing_model = cx.add_model(|_| Model);
6288 let observed_model = cx.add_model(|_| Model);
6289
6290 observing_view.update(cx, |_, cx| {
6291 cx.subscribe(&emitting_view, |_, _, _, _| {}).detach();
6292 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
6293 });
6294 observing_model.update(cx, |_, cx| {
6295 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
6296 });
6297
6298 cx.update(|_| {
6299 drop(observing_view);
6300 drop(observing_model);
6301 });
6302
6303 emitting_view.update(cx, |_, cx| cx.emit(()));
6304 observed_model.update(cx, |_, cx| cx.emit(()));
6305 }
6306
6307 #[crate::test(self)]
6308 fn test_view_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
6309 #[derive(Default)]
6310 struct TestView;
6311
6312 impl Entity for TestView {
6313 type Event = ();
6314 }
6315
6316 impl View for TestView {
6317 fn ui_name() -> &'static str {
6318 "TestView"
6319 }
6320
6321 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6322 Empty::new().boxed()
6323 }
6324 }
6325
6326 let events = Rc::new(RefCell::new(Vec::new()));
6327 cx.add_window(Default::default(), |cx| {
6328 drop(cx.subscribe(&cx.handle(), {
6329 let events = events.clone();
6330 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
6331 }));
6332 cx.subscribe(&cx.handle(), {
6333 let events = events.clone();
6334 move |_, _, _, _| events.borrow_mut().push("before emit")
6335 })
6336 .detach();
6337 cx.emit(());
6338 cx.subscribe(&cx.handle(), {
6339 let events = events.clone();
6340 move |_, _, _, _| events.borrow_mut().push("after emit")
6341 })
6342 .detach();
6343 TestView
6344 });
6345 assert_eq!(*events.borrow(), ["before emit"]);
6346 }
6347
6348 #[crate::test(self)]
6349 fn test_observe_and_notify_from_view(cx: &mut MutableAppContext) {
6350 #[derive(Default)]
6351 struct View {
6352 events: Vec<usize>,
6353 }
6354
6355 impl Entity for View {
6356 type Event = usize;
6357 }
6358
6359 impl super::View for View {
6360 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6361 Empty::new().boxed()
6362 }
6363
6364 fn ui_name() -> &'static str {
6365 "View"
6366 }
6367 }
6368
6369 #[derive(Default)]
6370 struct Model {
6371 count: usize,
6372 }
6373
6374 impl Entity for Model {
6375 type Event = ();
6376 }
6377
6378 let (_, view) = cx.add_window(Default::default(), |_| View::default());
6379 let model = cx.add_model(|_| Model::default());
6380
6381 view.update(cx, |_, c| {
6382 c.observe(&model, |me, observed, c| {
6383 me.events.push(observed.read(c).count)
6384 })
6385 .detach();
6386 });
6387
6388 model.update(cx, |model, c| {
6389 model.count = 11;
6390 c.notify();
6391 });
6392 assert_eq!(view.read(cx).events, vec![11]);
6393 }
6394
6395 #[crate::test(self)]
6396 fn test_view_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
6397 #[derive(Default)]
6398 struct TestView;
6399
6400 impl Entity for TestView {
6401 type Event = ();
6402 }
6403
6404 impl View for TestView {
6405 fn ui_name() -> &'static str {
6406 "TestView"
6407 }
6408
6409 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6410 Empty::new().boxed()
6411 }
6412 }
6413
6414 let events = Rc::new(RefCell::new(Vec::new()));
6415 cx.add_window(Default::default(), |cx| {
6416 drop(cx.observe(&cx.handle(), {
6417 let events = events.clone();
6418 move |_, _, _| events.borrow_mut().push("dropped before flush")
6419 }));
6420 cx.observe(&cx.handle(), {
6421 let events = events.clone();
6422 move |_, _, _| events.borrow_mut().push("before notify")
6423 })
6424 .detach();
6425 cx.notify();
6426 cx.observe(&cx.handle(), {
6427 let events = events.clone();
6428 move |_, _, _| events.borrow_mut().push("after notify")
6429 })
6430 .detach();
6431 TestView
6432 });
6433 assert_eq!(*events.borrow(), ["before notify"]);
6434 }
6435
6436 #[crate::test(self)]
6437 fn test_dropping_observers(cx: &mut MutableAppContext) {
6438 struct View;
6439
6440 impl Entity for View {
6441 type Event = ();
6442 }
6443
6444 impl super::View for View {
6445 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6446 Empty::new().boxed()
6447 }
6448
6449 fn ui_name() -> &'static str {
6450 "View"
6451 }
6452 }
6453
6454 struct Model;
6455
6456 impl Entity for Model {
6457 type Event = ();
6458 }
6459
6460 let (_, root_view) = cx.add_window(Default::default(), |_| View);
6461 let observing_view = cx.add_view(root_view, |_| View);
6462 let observing_model = cx.add_model(|_| Model);
6463 let observed_model = cx.add_model(|_| Model);
6464
6465 observing_view.update(cx, |_, cx| {
6466 cx.observe(&observed_model, |_, _, _| {}).detach();
6467 });
6468 observing_model.update(cx, |_, cx| {
6469 cx.observe(&observed_model, |_, _, _| {}).detach();
6470 });
6471
6472 cx.update(|_| {
6473 drop(observing_view);
6474 drop(observing_model);
6475 });
6476
6477 observed_model.update(cx, |_, cx| cx.notify());
6478 }
6479
6480 #[crate::test(self)]
6481 fn test_dropping_subscriptions_during_callback(cx: &mut MutableAppContext) {
6482 struct Model;
6483
6484 impl Entity for Model {
6485 type Event = u64;
6486 }
6487
6488 // Events
6489 let observing_model = cx.add_model(|_| Model);
6490 let observed_model = cx.add_model(|_| Model);
6491
6492 let events = Rc::new(RefCell::new(Vec::new()));
6493
6494 observing_model.update(cx, |_, cx| {
6495 let events = events.clone();
6496 let subscription = Rc::new(RefCell::new(None));
6497 *subscription.borrow_mut() = Some(cx.subscribe(&observed_model, {
6498 let subscription = subscription.clone();
6499 move |_, _, e, _| {
6500 subscription.borrow_mut().take();
6501 events.borrow_mut().push(*e);
6502 }
6503 }));
6504 });
6505
6506 observed_model.update(cx, |_, cx| {
6507 cx.emit(1);
6508 cx.emit(2);
6509 });
6510
6511 assert_eq!(*events.borrow(), [1]);
6512
6513 // Global Events
6514 #[derive(Clone, Debug, Eq, PartialEq)]
6515 struct GlobalEvent(u64);
6516
6517 let events = Rc::new(RefCell::new(Vec::new()));
6518
6519 {
6520 let events = events.clone();
6521 let subscription = Rc::new(RefCell::new(None));
6522 *subscription.borrow_mut() = Some(cx.subscribe_global({
6523 let subscription = subscription.clone();
6524 move |e: &GlobalEvent, _| {
6525 subscription.borrow_mut().take();
6526 events.borrow_mut().push(e.clone());
6527 }
6528 }));
6529 }
6530
6531 cx.update(|cx| {
6532 cx.emit_global(GlobalEvent(1));
6533 cx.emit_global(GlobalEvent(2));
6534 });
6535
6536 assert_eq!(*events.borrow(), [GlobalEvent(1)]);
6537
6538 // Model Observation
6539 let observing_model = cx.add_model(|_| Model);
6540 let observed_model = cx.add_model(|_| Model);
6541
6542 let observation_count = Rc::new(RefCell::new(0));
6543
6544 observing_model.update(cx, |_, cx| {
6545 let observation_count = observation_count.clone();
6546 let subscription = Rc::new(RefCell::new(None));
6547 *subscription.borrow_mut() = Some(cx.observe(&observed_model, {
6548 let subscription = subscription.clone();
6549 move |_, _, _| {
6550 subscription.borrow_mut().take();
6551 *observation_count.borrow_mut() += 1;
6552 }
6553 }));
6554 });
6555
6556 observed_model.update(cx, |_, cx| {
6557 cx.notify();
6558 });
6559
6560 observed_model.update(cx, |_, cx| {
6561 cx.notify();
6562 });
6563
6564 assert_eq!(*observation_count.borrow(), 1);
6565
6566 // View Observation
6567 struct View;
6568
6569 impl Entity for View {
6570 type Event = ();
6571 }
6572
6573 impl super::View for View {
6574 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6575 Empty::new().boxed()
6576 }
6577
6578 fn ui_name() -> &'static str {
6579 "View"
6580 }
6581 }
6582
6583 let (_, root_view) = cx.add_window(Default::default(), |_| View);
6584 let observing_view = cx.add_view(&root_view, |_| View);
6585 let observed_view = cx.add_view(&root_view, |_| View);
6586
6587 let observation_count = Rc::new(RefCell::new(0));
6588 observing_view.update(cx, |_, cx| {
6589 let observation_count = observation_count.clone();
6590 let subscription = Rc::new(RefCell::new(None));
6591 *subscription.borrow_mut() = Some(cx.observe(&observed_view, {
6592 let subscription = subscription.clone();
6593 move |_, _, _| {
6594 subscription.borrow_mut().take();
6595 *observation_count.borrow_mut() += 1;
6596 }
6597 }));
6598 });
6599
6600 observed_view.update(cx, |_, cx| {
6601 cx.notify();
6602 });
6603
6604 observed_view.update(cx, |_, cx| {
6605 cx.notify();
6606 });
6607
6608 assert_eq!(*observation_count.borrow(), 1);
6609
6610 // Global Observation
6611 let observation_count = Rc::new(RefCell::new(0));
6612 let subscription = Rc::new(RefCell::new(None));
6613 *subscription.borrow_mut() = Some(cx.observe_global::<(), _>({
6614 let observation_count = observation_count.clone();
6615 let subscription = subscription.clone();
6616 move |_| {
6617 subscription.borrow_mut().take();
6618 *observation_count.borrow_mut() += 1;
6619 }
6620 }));
6621
6622 cx.default_global::<()>();
6623 cx.set_global(());
6624 assert_eq!(*observation_count.borrow(), 1);
6625 }
6626
6627 #[crate::test(self)]
6628 fn test_focus(cx: &mut MutableAppContext) {
6629 struct View {
6630 name: String,
6631 events: Arc<Mutex<Vec<String>>>,
6632 }
6633
6634 impl Entity for View {
6635 type Event = ();
6636 }
6637
6638 impl super::View for View {
6639 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6640 Empty::new().boxed()
6641 }
6642
6643 fn ui_name() -> &'static str {
6644 "View"
6645 }
6646
6647 fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
6648 if cx.handle().id() == focused.id() {
6649 self.events.lock().push(format!("{} focused", &self.name));
6650 }
6651 }
6652
6653 fn focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
6654 if cx.handle().id() == blurred.id() {
6655 self.events.lock().push(format!("{} blurred", &self.name));
6656 }
6657 }
6658 }
6659
6660 let view_events: Arc<Mutex<Vec<String>>> = Default::default();
6661 let (_, view_1) = cx.add_window(Default::default(), |_| View {
6662 events: view_events.clone(),
6663 name: "view 1".to_string(),
6664 });
6665 let view_2 = cx.add_view(&view_1, |_| View {
6666 events: view_events.clone(),
6667 name: "view 2".to_string(),
6668 });
6669
6670 let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
6671 view_1.update(cx, |_, cx| {
6672 cx.observe_focus(&view_2, {
6673 let observed_events = observed_events.clone();
6674 move |this, view, focused, cx| {
6675 let label = if focused { "focus" } else { "blur" };
6676 observed_events.lock().push(format!(
6677 "{} observed {}'s {}",
6678 this.name,
6679 view.read(cx).name,
6680 label
6681 ))
6682 }
6683 })
6684 .detach();
6685 });
6686 view_2.update(cx, |_, cx| {
6687 cx.observe_focus(&view_1, {
6688 let observed_events = observed_events.clone();
6689 move |this, view, focused, cx| {
6690 let label = if focused { "focus" } else { "blur" };
6691 observed_events.lock().push(format!(
6692 "{} observed {}'s {}",
6693 this.name,
6694 view.read(cx).name,
6695 label
6696 ))
6697 }
6698 })
6699 .detach();
6700 });
6701 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
6702 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
6703
6704 view_1.update(cx, |_, cx| {
6705 // Ensure focus events are sent for all intermediate focuses
6706 cx.focus(&view_2);
6707 cx.focus(&view_1);
6708 cx.focus(&view_2);
6709 });
6710 assert_eq!(
6711 mem::take(&mut *view_events.lock()),
6712 [
6713 "view 1 blurred",
6714 "view 2 focused",
6715 "view 2 blurred",
6716 "view 1 focused",
6717 "view 1 blurred",
6718 "view 2 focused"
6719 ],
6720 );
6721 assert_eq!(
6722 mem::take(&mut *observed_events.lock()),
6723 [
6724 "view 2 observed view 1's blur",
6725 "view 1 observed view 2's focus",
6726 "view 1 observed view 2's blur",
6727 "view 2 observed view 1's focus",
6728 "view 2 observed view 1's blur",
6729 "view 1 observed view 2's focus"
6730 ]
6731 );
6732
6733 view_1.update(cx, |_, cx| cx.focus(&view_1));
6734 assert_eq!(
6735 mem::take(&mut *view_events.lock()),
6736 ["view 2 blurred", "view 1 focused"],
6737 );
6738 assert_eq!(
6739 mem::take(&mut *observed_events.lock()),
6740 [
6741 "view 1 observed view 2's blur",
6742 "view 2 observed view 1's focus"
6743 ]
6744 );
6745
6746 view_1.update(cx, |_, cx| cx.focus(&view_2));
6747 assert_eq!(
6748 mem::take(&mut *view_events.lock()),
6749 ["view 1 blurred", "view 2 focused"],
6750 );
6751 assert_eq!(
6752 mem::take(&mut *observed_events.lock()),
6753 [
6754 "view 2 observed view 1's blur",
6755 "view 1 observed view 2's focus"
6756 ]
6757 );
6758
6759 view_1.update(cx, |_, _| drop(view_2));
6760 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
6761 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
6762 }
6763
6764 #[crate::test(self)]
6765 fn test_deserialize_actions(cx: &mut MutableAppContext) {
6766 #[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
6767 pub struct ComplexAction {
6768 arg: String,
6769 count: usize,
6770 }
6771
6772 actions!(test::something, [SimpleAction]);
6773 impl_actions!(test::something, [ComplexAction]);
6774
6775 cx.add_global_action(move |_: &SimpleAction, _: &mut MutableAppContext| {});
6776 cx.add_global_action(move |_: &ComplexAction, _: &mut MutableAppContext| {});
6777
6778 let action1 = cx
6779 .deserialize_action(
6780 "test::something::ComplexAction",
6781 Some(r#"{"arg": "a", "count": 5}"#),
6782 )
6783 .unwrap();
6784 let action2 = cx
6785 .deserialize_action("test::something::SimpleAction", None)
6786 .unwrap();
6787 assert_eq!(
6788 action1.as_any().downcast_ref::<ComplexAction>().unwrap(),
6789 &ComplexAction {
6790 arg: "a".to_string(),
6791 count: 5,
6792 }
6793 );
6794 assert_eq!(
6795 action2.as_any().downcast_ref::<SimpleAction>().unwrap(),
6796 &SimpleAction
6797 );
6798 }
6799
6800 #[crate::test(self)]
6801 fn test_dispatch_action(cx: &mut MutableAppContext) {
6802 struct ViewA {
6803 id: usize,
6804 }
6805
6806 impl Entity for ViewA {
6807 type Event = ();
6808 }
6809
6810 impl View for ViewA {
6811 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6812 Empty::new().boxed()
6813 }
6814
6815 fn ui_name() -> &'static str {
6816 "View"
6817 }
6818 }
6819
6820 struct ViewB {
6821 id: usize,
6822 }
6823
6824 impl Entity for ViewB {
6825 type Event = ();
6826 }
6827
6828 impl View for ViewB {
6829 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6830 Empty::new().boxed()
6831 }
6832
6833 fn ui_name() -> &'static str {
6834 "View"
6835 }
6836 }
6837
6838 #[derive(Clone, Default, Deserialize, PartialEq)]
6839 pub struct Action(pub String);
6840
6841 impl_actions!(test, [Action]);
6842
6843 let actions = Rc::new(RefCell::new(Vec::new()));
6844
6845 cx.add_global_action({
6846 let actions = actions.clone();
6847 move |_: &Action, _: &mut MutableAppContext| {
6848 actions.borrow_mut().push("global".to_string());
6849 }
6850 });
6851
6852 cx.add_action({
6853 let actions = actions.clone();
6854 move |view: &mut ViewA, action: &Action, cx| {
6855 assert_eq!(action.0, "bar");
6856 cx.propagate_action();
6857 actions.borrow_mut().push(format!("{} a", view.id));
6858 }
6859 });
6860
6861 cx.add_action({
6862 let actions = actions.clone();
6863 move |view: &mut ViewA, _: &Action, cx| {
6864 if view.id != 1 {
6865 cx.add_view(|cx| {
6866 cx.propagate_action(); // Still works on a nested ViewContext
6867 ViewB { id: 5 }
6868 });
6869 }
6870 actions.borrow_mut().push(format!("{} b", view.id));
6871 }
6872 });
6873
6874 cx.add_action({
6875 let actions = actions.clone();
6876 move |view: &mut ViewB, _: &Action, cx| {
6877 cx.propagate_action();
6878 actions.borrow_mut().push(format!("{} c", view.id));
6879 }
6880 });
6881
6882 cx.add_action({
6883 let actions = actions.clone();
6884 move |view: &mut ViewB, _: &Action, cx| {
6885 cx.propagate_action();
6886 actions.borrow_mut().push(format!("{} d", view.id));
6887 }
6888 });
6889
6890 cx.capture_action({
6891 let actions = actions.clone();
6892 move |view: &mut ViewA, _: &Action, cx| {
6893 cx.propagate_action();
6894 actions.borrow_mut().push(format!("{} capture", view.id));
6895 }
6896 });
6897
6898 let observed_actions = Rc::new(RefCell::new(Vec::new()));
6899 cx.observe_actions({
6900 let observed_actions = observed_actions.clone();
6901 move |action_id, _| observed_actions.borrow_mut().push(action_id)
6902 })
6903 .detach();
6904
6905 let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 });
6906 let view_2 = cx.add_view(&view_1, |_| ViewB { id: 2 });
6907 let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 });
6908 let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 });
6909
6910 cx.handle_dispatch_action_from_effect(
6911 window_id,
6912 Some(view_4.id()),
6913 &Action("bar".to_string()),
6914 );
6915
6916 assert_eq!(
6917 *actions.borrow(),
6918 vec![
6919 "1 capture",
6920 "3 capture",
6921 "4 d",
6922 "4 c",
6923 "3 b",
6924 "3 a",
6925 "2 d",
6926 "2 c",
6927 "1 b"
6928 ]
6929 );
6930 assert_eq!(*observed_actions.borrow(), [Action::default().id()]);
6931
6932 // Remove view_1, which doesn't propagate the action
6933
6934 let (window_id, view_2) = cx.add_window(Default::default(), |_| ViewB { id: 2 });
6935 let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 });
6936 let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 });
6937
6938 actions.borrow_mut().clear();
6939 cx.handle_dispatch_action_from_effect(
6940 window_id,
6941 Some(view_4.id()),
6942 &Action("bar".to_string()),
6943 );
6944
6945 assert_eq!(
6946 *actions.borrow(),
6947 vec![
6948 "3 capture",
6949 "4 d",
6950 "4 c",
6951 "3 b",
6952 "3 a",
6953 "2 d",
6954 "2 c",
6955 "global"
6956 ]
6957 );
6958 assert_eq!(
6959 *observed_actions.borrow(),
6960 [Action::default().id(), Action::default().id()]
6961 );
6962 }
6963
6964 #[crate::test(self)]
6965 fn test_dispatch_keystroke(cx: &mut MutableAppContext) {
6966 #[derive(Clone, Deserialize, PartialEq)]
6967 pub struct Action(String);
6968
6969 impl_actions!(test, [Action]);
6970
6971 struct View {
6972 id: usize,
6973 keymap_context: keymap::Context,
6974 }
6975
6976 impl Entity for View {
6977 type Event = ();
6978 }
6979
6980 impl super::View for View {
6981 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6982 Empty::new().boxed()
6983 }
6984
6985 fn ui_name() -> &'static str {
6986 "View"
6987 }
6988
6989 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
6990 self.keymap_context.clone()
6991 }
6992 }
6993
6994 impl View {
6995 fn new(id: usize) -> Self {
6996 View {
6997 id,
6998 keymap_context: keymap::Context::default(),
6999 }
7000 }
7001 }
7002
7003 let mut view_1 = View::new(1);
7004 let mut view_2 = View::new(2);
7005 let mut view_3 = View::new(3);
7006 view_1.keymap_context.set.insert("a".into());
7007 view_2.keymap_context.set.insert("a".into());
7008 view_2.keymap_context.set.insert("b".into());
7009 view_3.keymap_context.set.insert("a".into());
7010 view_3.keymap_context.set.insert("b".into());
7011 view_3.keymap_context.set.insert("c".into());
7012
7013 let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1);
7014 let view_2 = cx.add_view(&view_1, |_| view_2);
7015 let _view_3 = cx.add_view(&view_2, |cx| {
7016 cx.focus_self();
7017 view_3
7018 });
7019
7020 // This keymap's only binding dispatches an action on view 2 because that view will have
7021 // "a" and "b" in its context, but not "c".
7022 cx.add_bindings(vec![keymap::Binding::new(
7023 "a",
7024 Action("a".to_string()),
7025 Some("a && b && !c"),
7026 )]);
7027
7028 cx.add_bindings(vec![keymap::Binding::new(
7029 "b",
7030 Action("b".to_string()),
7031 None,
7032 )]);
7033
7034 let actions = Rc::new(RefCell::new(Vec::new()));
7035 cx.add_action({
7036 let actions = actions.clone();
7037 move |view: &mut View, action: &Action, cx| {
7038 if action.0 == "a" {
7039 actions.borrow_mut().push(format!("{} a", view.id));
7040 } else {
7041 actions
7042 .borrow_mut()
7043 .push(format!("{} {}", view.id, action.0));
7044 cx.propagate_action();
7045 }
7046 }
7047 });
7048
7049 cx.add_global_action({
7050 let actions = actions.clone();
7051 move |action: &Action, _| {
7052 actions.borrow_mut().push(format!("global {}", action.0));
7053 }
7054 });
7055
7056 cx.dispatch_keystroke(window_id, &Keystroke::parse("a").unwrap());
7057
7058 assert_eq!(&*actions.borrow(), &["2 a"]);
7059
7060 actions.borrow_mut().clear();
7061
7062 cx.dispatch_keystroke(window_id, &Keystroke::parse("b").unwrap());
7063
7064 assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
7065 }
7066
7067 #[crate::test(self)]
7068 async fn test_model_condition(cx: &mut TestAppContext) {
7069 struct Counter(usize);
7070
7071 impl super::Entity for Counter {
7072 type Event = ();
7073 }
7074
7075 impl Counter {
7076 fn inc(&mut self, cx: &mut ModelContext<Self>) {
7077 self.0 += 1;
7078 cx.notify();
7079 }
7080 }
7081
7082 let model = cx.add_model(|_| Counter(0));
7083
7084 let condition1 = model.condition(cx, |model, _| model.0 == 2);
7085 let condition2 = model.condition(cx, |model, _| model.0 == 3);
7086 smol::pin!(condition1, condition2);
7087
7088 model.update(cx, |model, cx| model.inc(cx));
7089 assert_eq!(poll_once(&mut condition1).await, None);
7090 assert_eq!(poll_once(&mut condition2).await, None);
7091
7092 model.update(cx, |model, cx| model.inc(cx));
7093 assert_eq!(poll_once(&mut condition1).await, Some(()));
7094 assert_eq!(poll_once(&mut condition2).await, None);
7095
7096 model.update(cx, |model, cx| model.inc(cx));
7097 assert_eq!(poll_once(&mut condition2).await, Some(()));
7098
7099 model.update(cx, |_, cx| cx.notify());
7100 }
7101
7102 #[crate::test(self)]
7103 #[should_panic]
7104 async fn test_model_condition_timeout(cx: &mut TestAppContext) {
7105 struct Model;
7106
7107 impl super::Entity for Model {
7108 type Event = ();
7109 }
7110
7111 let model = cx.add_model(|_| Model);
7112 model.condition(cx, |_, _| false).await;
7113 }
7114
7115 #[crate::test(self)]
7116 #[should_panic(expected = "model dropped with pending condition")]
7117 async fn test_model_condition_panic_on_drop(cx: &mut TestAppContext) {
7118 struct Model;
7119
7120 impl super::Entity for Model {
7121 type Event = ();
7122 }
7123
7124 let model = cx.add_model(|_| Model);
7125 let condition = model.condition(cx, |_, _| false);
7126 cx.update(|_| drop(model));
7127 condition.await;
7128 }
7129
7130 #[crate::test(self)]
7131 async fn test_view_condition(cx: &mut TestAppContext) {
7132 struct Counter(usize);
7133
7134 impl super::Entity for Counter {
7135 type Event = ();
7136 }
7137
7138 impl super::View for Counter {
7139 fn ui_name() -> &'static str {
7140 "test view"
7141 }
7142
7143 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7144 Empty::new().boxed()
7145 }
7146 }
7147
7148 impl Counter {
7149 fn inc(&mut self, cx: &mut ViewContext<Self>) {
7150 self.0 += 1;
7151 cx.notify();
7152 }
7153 }
7154
7155 let (_, view) = cx.add_window(|_| Counter(0));
7156
7157 let condition1 = view.condition(cx, |view, _| view.0 == 2);
7158 let condition2 = view.condition(cx, |view, _| view.0 == 3);
7159 smol::pin!(condition1, condition2);
7160
7161 view.update(cx, |view, cx| view.inc(cx));
7162 assert_eq!(poll_once(&mut condition1).await, None);
7163 assert_eq!(poll_once(&mut condition2).await, None);
7164
7165 view.update(cx, |view, cx| view.inc(cx));
7166 assert_eq!(poll_once(&mut condition1).await, Some(()));
7167 assert_eq!(poll_once(&mut condition2).await, None);
7168
7169 view.update(cx, |view, cx| view.inc(cx));
7170 assert_eq!(poll_once(&mut condition2).await, Some(()));
7171 view.update(cx, |_, cx| cx.notify());
7172 }
7173
7174 #[crate::test(self)]
7175 #[should_panic]
7176 async fn test_view_condition_timeout(cx: &mut TestAppContext) {
7177 struct View;
7178
7179 impl super::Entity for View {
7180 type Event = ();
7181 }
7182
7183 impl super::View for View {
7184 fn ui_name() -> &'static str {
7185 "test view"
7186 }
7187
7188 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7189 Empty::new().boxed()
7190 }
7191 }
7192
7193 let (_, view) = cx.add_window(|_| View);
7194 view.condition(cx, |_, _| false).await;
7195 }
7196
7197 #[crate::test(self)]
7198 #[should_panic(expected = "view dropped with pending condition")]
7199 async fn test_view_condition_panic_on_drop(cx: &mut TestAppContext) {
7200 struct View;
7201
7202 impl super::Entity for View {
7203 type Event = ();
7204 }
7205
7206 impl super::View for View {
7207 fn ui_name() -> &'static str {
7208 "test view"
7209 }
7210
7211 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7212 Empty::new().boxed()
7213 }
7214 }
7215
7216 let (_, root_view) = cx.add_window(|_| View);
7217 let view = cx.add_view(&root_view, |_| View);
7218
7219 let condition = view.condition(cx, |_, _| false);
7220 cx.update(|_| drop(view));
7221 condition.await;
7222 }
7223
7224 #[crate::test(self)]
7225 fn test_refresh_windows(cx: &mut MutableAppContext) {
7226 struct View(usize);
7227
7228 impl super::Entity for View {
7229 type Event = ();
7230 }
7231
7232 impl super::View for View {
7233 fn ui_name() -> &'static str {
7234 "test view"
7235 }
7236
7237 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7238 Empty::new().named(format!("render count: {}", post_inc(&mut self.0)))
7239 }
7240 }
7241
7242 let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0));
7243 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
7244
7245 assert_eq!(
7246 presenter.borrow().rendered_views[&root_view.id()].name(),
7247 Some("render count: 0")
7248 );
7249
7250 let view = cx.add_view(&root_view, |cx| {
7251 cx.refresh_windows();
7252 View(0)
7253 });
7254
7255 assert_eq!(
7256 presenter.borrow().rendered_views[&root_view.id()].name(),
7257 Some("render count: 1")
7258 );
7259 assert_eq!(
7260 presenter.borrow().rendered_views[&view.id()].name(),
7261 Some("render count: 0")
7262 );
7263
7264 cx.update(|cx| cx.refresh_windows());
7265 assert_eq!(
7266 presenter.borrow().rendered_views[&root_view.id()].name(),
7267 Some("render count: 2")
7268 );
7269 assert_eq!(
7270 presenter.borrow().rendered_views[&view.id()].name(),
7271 Some("render count: 1")
7272 );
7273
7274 cx.update(|cx| {
7275 cx.refresh_windows();
7276 drop(view);
7277 });
7278 assert_eq!(
7279 presenter.borrow().rendered_views[&root_view.id()].name(),
7280 Some("render count: 3")
7281 );
7282 assert_eq!(presenter.borrow().rendered_views.len(), 1);
7283 }
7284
7285 #[crate::test(self)]
7286 async fn test_window_activation(cx: &mut TestAppContext) {
7287 struct View(&'static str);
7288
7289 impl super::Entity for View {
7290 type Event = ();
7291 }
7292
7293 impl super::View for View {
7294 fn ui_name() -> &'static str {
7295 "test view"
7296 }
7297
7298 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7299 Empty::new().boxed()
7300 }
7301 }
7302
7303 let events = Rc::new(RefCell::new(Vec::new()));
7304 let (window_1, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7305 cx.observe_window_activation({
7306 let events = events.clone();
7307 move |this, active, _| events.borrow_mut().push((this.0, active))
7308 })
7309 .detach();
7310 View("window 1")
7311 });
7312 assert_eq!(mem::take(&mut *events.borrow_mut()), [("window 1", true)]);
7313
7314 let (window_2, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7315 cx.observe_window_activation({
7316 let events = events.clone();
7317 move |this, active, _| events.borrow_mut().push((this.0, active))
7318 })
7319 .detach();
7320 View("window 2")
7321 });
7322 assert_eq!(
7323 mem::take(&mut *events.borrow_mut()),
7324 [("window 1", false), ("window 2", true)]
7325 );
7326
7327 let (window_3, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7328 cx.observe_window_activation({
7329 let events = events.clone();
7330 move |this, active, _| events.borrow_mut().push((this.0, active))
7331 })
7332 .detach();
7333 View("window 3")
7334 });
7335 assert_eq!(
7336 mem::take(&mut *events.borrow_mut()),
7337 [("window 2", false), ("window 3", true)]
7338 );
7339
7340 cx.simulate_window_activation(Some(window_2));
7341 assert_eq!(
7342 mem::take(&mut *events.borrow_mut()),
7343 [("window 3", false), ("window 2", true)]
7344 );
7345
7346 cx.simulate_window_activation(Some(window_1));
7347 assert_eq!(
7348 mem::take(&mut *events.borrow_mut()),
7349 [("window 2", false), ("window 1", true)]
7350 );
7351
7352 cx.simulate_window_activation(Some(window_3));
7353 assert_eq!(
7354 mem::take(&mut *events.borrow_mut()),
7355 [("window 1", false), ("window 3", true)]
7356 );
7357
7358 cx.simulate_window_activation(Some(window_3));
7359 assert_eq!(mem::take(&mut *events.borrow_mut()), []);
7360 }
7361
7362 #[crate::test(self)]
7363 fn test_child_view(cx: &mut MutableAppContext) {
7364 struct Child {
7365 rendered: Rc<Cell<bool>>,
7366 dropped: Rc<Cell<bool>>,
7367 }
7368
7369 impl super::Entity for Child {
7370 type Event = ();
7371 }
7372
7373 impl super::View for Child {
7374 fn ui_name() -> &'static str {
7375 "child view"
7376 }
7377
7378 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7379 self.rendered.set(true);
7380 Empty::new().boxed()
7381 }
7382 }
7383
7384 impl Drop for Child {
7385 fn drop(&mut self) {
7386 self.dropped.set(true);
7387 }
7388 }
7389
7390 struct Parent {
7391 child: Option<ViewHandle<Child>>,
7392 }
7393
7394 impl super::Entity for Parent {
7395 type Event = ();
7396 }
7397
7398 impl super::View for Parent {
7399 fn ui_name() -> &'static str {
7400 "parent view"
7401 }
7402
7403 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
7404 if let Some(child) = self.child.as_ref() {
7405 ChildView::new(child, cx).boxed()
7406 } else {
7407 Empty::new().boxed()
7408 }
7409 }
7410 }
7411
7412 let child_rendered = Rc::new(Cell::new(false));
7413 let child_dropped = Rc::new(Cell::new(false));
7414 let (_, root_view) = cx.add_window(Default::default(), |cx| Parent {
7415 child: Some(cx.add_view(|_| Child {
7416 rendered: child_rendered.clone(),
7417 dropped: child_dropped.clone(),
7418 })),
7419 });
7420 assert!(child_rendered.take());
7421 assert!(!child_dropped.take());
7422
7423 root_view.update(cx, |view, cx| {
7424 view.child.take();
7425 cx.notify();
7426 });
7427 assert!(!child_rendered.take());
7428 assert!(child_dropped.take());
7429 }
7430}