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 .any(|parent| parent == self.view_id)
3699 }
3700
3701 pub fn blur(&mut self) {
3702 self.app.focus(self.window_id, None);
3703 }
3704
3705 pub fn set_window_title(&mut self, title: &str) {
3706 let window_id = self.window_id();
3707 if let Some((_, window)) = self.presenters_and_platform_windows.get_mut(&window_id) {
3708 window.set_title(title);
3709 }
3710 }
3711
3712 pub fn set_window_edited(&mut self, edited: bool) {
3713 let window_id = self.window_id();
3714 if let Some((_, window)) = self.presenters_and_platform_windows.get_mut(&window_id) {
3715 window.set_edited(edited);
3716 }
3717 }
3718
3719 pub fn on_window_should_close<F>(&mut self, mut callback: F)
3720 where
3721 F: 'static + FnMut(&mut T, &mut ViewContext<T>) -> bool,
3722 {
3723 let window_id = self.window_id();
3724 let view = self.weak_handle();
3725 self.pending_effects
3726 .push_back(Effect::WindowShouldCloseSubscription {
3727 window_id,
3728 callback: Box::new(move |cx| {
3729 if let Some(view) = view.upgrade(cx) {
3730 view.update(cx, |view, cx| callback(view, cx))
3731 } else {
3732 true
3733 }
3734 }),
3735 });
3736 }
3737
3738 pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
3739 where
3740 S: Entity,
3741 F: FnOnce(&mut ModelContext<S>) -> S,
3742 {
3743 self.app.add_model(build_model)
3744 }
3745
3746 pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
3747 where
3748 S: View,
3749 F: FnOnce(&mut ViewContext<S>) -> S,
3750 {
3751 self.app
3752 .build_and_insert_view(self.window_id, ParentId::View(self.view_id), |cx| {
3753 Some(build_view(cx))
3754 })
3755 .unwrap()
3756 }
3757
3758 pub fn add_option_view<S, F>(&mut self, build_view: F) -> Option<ViewHandle<S>>
3759 where
3760 S: View,
3761 F: FnOnce(&mut ViewContext<S>) -> Option<S>,
3762 {
3763 self.app
3764 .build_and_insert_view(self.window_id, ParentId::View(self.view_id), build_view)
3765 }
3766
3767 pub fn reparent(&mut self, view_handle: impl Into<AnyViewHandle>) {
3768 let view_handle = view_handle.into();
3769 if self.window_id != view_handle.window_id {
3770 panic!("Can't reparent view to a view from a different window");
3771 }
3772 self.cx
3773 .parents
3774 .remove(&(view_handle.window_id, view_handle.view_id));
3775 let new_parent_id = self.view_id;
3776 self.cx.parents.insert(
3777 (view_handle.window_id, view_handle.view_id),
3778 ParentId::View(new_parent_id),
3779 );
3780 }
3781
3782 pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
3783 where
3784 V: View,
3785 F: FnOnce(&mut ViewContext<V>) -> V,
3786 {
3787 let window_id = self.window_id;
3788 self.update(|this| {
3789 let root_view = this
3790 .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
3791 .unwrap();
3792 let window = this.cx.windows.get_mut(&window_id).unwrap();
3793 window.root_view = root_view.clone().into();
3794 window.focused_view_id = Some(root_view.id());
3795 root_view
3796 })
3797 }
3798
3799 pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
3800 where
3801 E: Entity,
3802 E::Event: 'static,
3803 H: Handle<E>,
3804 F: 'static + FnMut(&mut T, H, &E::Event, &mut ViewContext<T>),
3805 {
3806 let subscriber = self.weak_handle();
3807 self.app
3808 .subscribe_internal(handle, move |emitter, event, cx| {
3809 if let Some(subscriber) = subscriber.upgrade(cx) {
3810 subscriber.update(cx, |subscriber, cx| {
3811 callback(subscriber, emitter, event, cx);
3812 });
3813 true
3814 } else {
3815 false
3816 }
3817 })
3818 }
3819
3820 pub fn observe<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
3821 where
3822 E: Entity,
3823 H: Handle<E>,
3824 F: 'static + FnMut(&mut T, H, &mut ViewContext<T>),
3825 {
3826 let observer = self.weak_handle();
3827 self.app.observe_internal(handle, move |observed, cx| {
3828 if let Some(observer) = observer.upgrade(cx) {
3829 observer.update(cx, |observer, cx| {
3830 callback(observer, observed, cx);
3831 });
3832 true
3833 } else {
3834 false
3835 }
3836 })
3837 }
3838
3839 pub fn observe_focus<F, V>(&mut self, handle: &ViewHandle<V>, mut callback: F) -> Subscription
3840 where
3841 F: 'static + FnMut(&mut T, ViewHandle<V>, bool, &mut ViewContext<T>),
3842 V: View,
3843 {
3844 let observer = self.weak_handle();
3845 self.app
3846 .observe_focus(handle, move |observed, focused, cx| {
3847 if let Some(observer) = observer.upgrade(cx) {
3848 observer.update(cx, |observer, cx| {
3849 callback(observer, observed, focused, cx);
3850 });
3851 true
3852 } else {
3853 false
3854 }
3855 })
3856 }
3857
3858 pub fn observe_release<E, F, H>(&mut self, handle: &H, mut callback: F) -> Subscription
3859 where
3860 E: Entity,
3861 H: Handle<E>,
3862 F: 'static + FnMut(&mut T, &E, &mut ViewContext<T>),
3863 {
3864 let observer = self.weak_handle();
3865 self.app.observe_release(handle, move |released, cx| {
3866 if let Some(observer) = observer.upgrade(cx) {
3867 observer.update(cx, |observer, cx| {
3868 callback(observer, released, cx);
3869 });
3870 }
3871 })
3872 }
3873
3874 pub fn observe_actions<F>(&mut self, mut callback: F) -> Subscription
3875 where
3876 F: 'static + FnMut(&mut T, TypeId, &mut ViewContext<T>),
3877 {
3878 let observer = self.weak_handle();
3879 self.app.observe_actions(move |action_id, cx| {
3880 if let Some(observer) = observer.upgrade(cx) {
3881 observer.update(cx, |observer, cx| {
3882 callback(observer, action_id, cx);
3883 });
3884 }
3885 })
3886 }
3887
3888 pub fn observe_window_activation<F>(&mut self, mut callback: F) -> Subscription
3889 where
3890 F: 'static + FnMut(&mut T, bool, &mut ViewContext<T>),
3891 {
3892 let observer = self.weak_handle();
3893 self.app
3894 .observe_window_activation(self.window_id(), move |active, cx| {
3895 if let Some(observer) = observer.upgrade(cx) {
3896 observer.update(cx, |observer, cx| {
3897 callback(observer, active, cx);
3898 });
3899 true
3900 } else {
3901 false
3902 }
3903 })
3904 }
3905
3906 pub fn observe_fullscreen<F>(&mut self, mut callback: F) -> Subscription
3907 where
3908 F: 'static + FnMut(&mut T, bool, &mut ViewContext<T>),
3909 {
3910 let observer = self.weak_handle();
3911 self.app
3912 .observe_fullscreen(self.window_id(), move |active, cx| {
3913 if let Some(observer) = observer.upgrade(cx) {
3914 observer.update(cx, |observer, cx| {
3915 callback(observer, active, cx);
3916 });
3917 true
3918 } else {
3919 false
3920 }
3921 })
3922 }
3923
3924 pub fn observe_keystroke<F>(&mut self, mut callback: F) -> Subscription
3925 where
3926 F: 'static
3927 + FnMut(
3928 &mut T,
3929 &Keystroke,
3930 Option<&Box<dyn Action>>,
3931 &MatchResult,
3932 &mut ViewContext<T>,
3933 ) -> bool,
3934 {
3935 let observer = self.weak_handle();
3936 self.app.observe_keystrokes(
3937 self.window_id(),
3938 move |keystroke, result, handled_by, cx| {
3939 if let Some(observer) = observer.upgrade(cx) {
3940 observer.update(cx, |observer, cx| {
3941 callback(observer, keystroke, handled_by, result, cx);
3942 });
3943 true
3944 } else {
3945 false
3946 }
3947 },
3948 )
3949 }
3950
3951 pub fn emit(&mut self, payload: T::Event) {
3952 self.app.pending_effects.push_back(Effect::Event {
3953 entity_id: self.view_id,
3954 payload: Box::new(payload),
3955 });
3956 }
3957
3958 pub fn notify(&mut self) {
3959 self.app.notify_view(self.window_id, self.view_id);
3960 }
3961
3962 pub fn dispatch_action(&mut self, action: impl Action) {
3963 self.app
3964 .dispatch_action_at(self.window_id, self.view_id, action)
3965 }
3966
3967 pub fn dispatch_any_action(&mut self, action: Box<dyn Action>) {
3968 self.app
3969 .dispatch_any_action_at(self.window_id, self.view_id, action)
3970 }
3971
3972 pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>)) {
3973 let handle = self.handle();
3974 self.app.defer(move |cx| {
3975 handle.update(cx, |view, cx| {
3976 callback(view, cx);
3977 })
3978 })
3979 }
3980
3981 pub fn after_window_update(
3982 &mut self,
3983 callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>),
3984 ) {
3985 let handle = self.handle();
3986 self.app.after_window_update(move |cx| {
3987 handle.update(cx, |view, cx| {
3988 callback(view, cx);
3989 })
3990 })
3991 }
3992
3993 pub fn propagate_action(&mut self) {
3994 self.app.halt_action_dispatch = false;
3995 }
3996
3997 pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
3998 where
3999 F: FnOnce(ViewHandle<T>, AsyncAppContext) -> Fut,
4000 Fut: 'static + Future<Output = S>,
4001 S: 'static,
4002 {
4003 let handle = self.handle();
4004 self.app.spawn(|cx| f(handle, cx))
4005 }
4006
4007 pub fn spawn_weak<F, Fut, S>(&self, f: F) -> Task<S>
4008 where
4009 F: FnOnce(WeakViewHandle<T>, AsyncAppContext) -> Fut,
4010 Fut: 'static + Future<Output = S>,
4011 S: 'static,
4012 {
4013 let handle = self.weak_handle();
4014 self.app.spawn(|cx| f(handle, cx))
4015 }
4016}
4017
4018pub struct RenderParams {
4019 pub window_id: usize,
4020 pub view_id: usize,
4021 pub titlebar_height: f32,
4022 pub hovered_region_ids: HashSet<MouseRegionId>,
4023 pub clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
4024 pub refreshing: bool,
4025 pub appearance: Appearance,
4026}
4027
4028pub struct RenderContext<'a, T: View> {
4029 pub(crate) window_id: usize,
4030 pub(crate) view_id: usize,
4031 pub(crate) view_type: PhantomData<T>,
4032 pub(crate) hovered_region_ids: HashSet<MouseRegionId>,
4033 pub(crate) clicked_region_ids: Option<(HashSet<MouseRegionId>, MouseButton)>,
4034 pub app: &'a mut MutableAppContext,
4035 pub titlebar_height: f32,
4036 pub appearance: Appearance,
4037 pub refreshing: bool,
4038}
4039
4040#[derive(Clone, Default)]
4041pub struct MouseState {
4042 hovered: bool,
4043 clicked: Option<MouseButton>,
4044 accessed_hovered: bool,
4045 accessed_clicked: bool,
4046}
4047
4048impl MouseState {
4049 pub fn hovered(&mut self) -> bool {
4050 self.accessed_hovered = true;
4051 self.hovered
4052 }
4053
4054 pub fn clicked(&mut self) -> Option<MouseButton> {
4055 self.accessed_clicked = true;
4056 self.clicked
4057 }
4058
4059 pub fn accessed_hovered(&self) -> bool {
4060 self.accessed_hovered
4061 }
4062
4063 pub fn accessed_clicked(&self) -> bool {
4064 self.accessed_clicked
4065 }
4066}
4067
4068impl<'a, V: View> RenderContext<'a, V> {
4069 fn new(params: RenderParams, app: &'a mut MutableAppContext) -> Self {
4070 Self {
4071 app,
4072 window_id: params.window_id,
4073 view_id: params.view_id,
4074 view_type: PhantomData,
4075 titlebar_height: params.titlebar_height,
4076 hovered_region_ids: params.hovered_region_ids.clone(),
4077 clicked_region_ids: params.clicked_region_ids.clone(),
4078 refreshing: params.refreshing,
4079 appearance: params.appearance,
4080 }
4081 }
4082
4083 pub fn handle(&self) -> WeakViewHandle<V> {
4084 WeakViewHandle::new(self.window_id, self.view_id)
4085 }
4086
4087 pub fn window_id(&self) -> usize {
4088 self.window_id
4089 }
4090
4091 pub fn view_id(&self) -> usize {
4092 self.view_id
4093 }
4094
4095 pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
4096 let region_id = MouseRegionId::new::<Tag>(self.view_id, region_id);
4097 MouseState {
4098 hovered: self.hovered_region_ids.contains(®ion_id),
4099 clicked: self.clicked_region_ids.as_ref().and_then(|(ids, button)| {
4100 if ids.contains(®ion_id) {
4101 Some(*button)
4102 } else {
4103 None
4104 }
4105 }),
4106 accessed_hovered: false,
4107 accessed_clicked: false,
4108 }
4109 }
4110
4111 pub fn element_state<Tag: 'static, T: 'static>(
4112 &mut self,
4113 element_id: usize,
4114 initial: T,
4115 ) -> ElementStateHandle<T> {
4116 let id = ElementStateId {
4117 view_id: self.view_id(),
4118 element_id,
4119 tag: TypeId::of::<Tag>(),
4120 };
4121 self.cx
4122 .element_states
4123 .entry(id)
4124 .or_insert_with(|| Box::new(initial));
4125 ElementStateHandle::new(id, self.frame_count, &self.cx.ref_counts)
4126 }
4127
4128 pub fn default_element_state<Tag: 'static, T: 'static + Default>(
4129 &mut self,
4130 element_id: usize,
4131 ) -> ElementStateHandle<T> {
4132 self.element_state::<Tag, T>(element_id, T::default())
4133 }
4134}
4135
4136impl AsRef<AppContext> for &AppContext {
4137 fn as_ref(&self) -> &AppContext {
4138 self
4139 }
4140}
4141
4142impl<V: View> Deref for RenderContext<'_, V> {
4143 type Target = MutableAppContext;
4144
4145 fn deref(&self) -> &Self::Target {
4146 self.app
4147 }
4148}
4149
4150impl<V: View> DerefMut for RenderContext<'_, V> {
4151 fn deref_mut(&mut self) -> &mut Self::Target {
4152 self.app
4153 }
4154}
4155
4156impl<V: View> ReadModel for RenderContext<'_, V> {
4157 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
4158 self.app.read_model(handle)
4159 }
4160}
4161
4162impl<V: View> UpdateModel for RenderContext<'_, V> {
4163 fn update_model<T: Entity, O>(
4164 &mut self,
4165 handle: &ModelHandle<T>,
4166 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
4167 ) -> O {
4168 self.app.update_model(handle, update)
4169 }
4170}
4171
4172impl<V: View> ReadView for RenderContext<'_, V> {
4173 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
4174 self.app.read_view(handle)
4175 }
4176}
4177
4178impl<M> AsRef<AppContext> for ViewContext<'_, M> {
4179 fn as_ref(&self) -> &AppContext {
4180 &self.app.cx
4181 }
4182}
4183
4184impl<M> Deref for ViewContext<'_, M> {
4185 type Target = MutableAppContext;
4186
4187 fn deref(&self) -> &Self::Target {
4188 self.app
4189 }
4190}
4191
4192impl<M> DerefMut for ViewContext<'_, M> {
4193 fn deref_mut(&mut self) -> &mut Self::Target {
4194 &mut self.app
4195 }
4196}
4197
4198impl<M> AsMut<MutableAppContext> for ViewContext<'_, M> {
4199 fn as_mut(&mut self) -> &mut MutableAppContext {
4200 self.app
4201 }
4202}
4203
4204impl<V> ReadModel for ViewContext<'_, V> {
4205 fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
4206 self.app.read_model(handle)
4207 }
4208}
4209
4210impl<V> UpgradeModelHandle for ViewContext<'_, V> {
4211 fn upgrade_model_handle<T: Entity>(
4212 &self,
4213 handle: &WeakModelHandle<T>,
4214 ) -> Option<ModelHandle<T>> {
4215 self.cx.upgrade_model_handle(handle)
4216 }
4217
4218 fn model_handle_is_upgradable<T: Entity>(&self, handle: &WeakModelHandle<T>) -> bool {
4219 self.cx.model_handle_is_upgradable(handle)
4220 }
4221
4222 fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
4223 self.cx.upgrade_any_model_handle(handle)
4224 }
4225}
4226
4227impl<V> UpgradeViewHandle for ViewContext<'_, V> {
4228 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
4229 self.cx.upgrade_view_handle(handle)
4230 }
4231
4232 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
4233 self.cx.upgrade_any_view_handle(handle)
4234 }
4235}
4236
4237impl<V: View> UpgradeViewHandle for RenderContext<'_, V> {
4238 fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
4239 self.cx.upgrade_view_handle(handle)
4240 }
4241
4242 fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
4243 self.cx.upgrade_any_view_handle(handle)
4244 }
4245}
4246
4247impl<V: View> UpdateModel for ViewContext<'_, V> {
4248 fn update_model<T: Entity, O>(
4249 &mut self,
4250 handle: &ModelHandle<T>,
4251 update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
4252 ) -> O {
4253 self.app.update_model(handle, update)
4254 }
4255}
4256
4257impl<V: View> ReadView for ViewContext<'_, V> {
4258 fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
4259 self.app.read_view(handle)
4260 }
4261}
4262
4263impl<V: View> UpdateView for ViewContext<'_, V> {
4264 fn update_view<T, S>(
4265 &mut self,
4266 handle: &ViewHandle<T>,
4267 update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
4268 ) -> S
4269 where
4270 T: View,
4271 {
4272 self.app.update_view(handle, update)
4273 }
4274}
4275
4276pub trait Handle<T> {
4277 type Weak: 'static;
4278 fn id(&self) -> usize;
4279 fn location(&self) -> EntityLocation;
4280 fn downgrade(&self) -> Self::Weak;
4281 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4282 where
4283 Self: Sized;
4284}
4285
4286pub trait WeakHandle {
4287 fn id(&self) -> usize;
4288}
4289
4290#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
4291pub enum EntityLocation {
4292 Model(usize),
4293 View(usize, usize),
4294}
4295
4296pub struct ModelHandle<T: Entity> {
4297 model_id: usize,
4298 model_type: PhantomData<T>,
4299 ref_counts: Arc<Mutex<RefCounts>>,
4300
4301 #[cfg(any(test, feature = "test-support"))]
4302 handle_id: usize,
4303}
4304
4305impl<T: Entity> ModelHandle<T> {
4306 fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4307 ref_counts.lock().inc_model(model_id);
4308
4309 #[cfg(any(test, feature = "test-support"))]
4310 let handle_id = ref_counts
4311 .lock()
4312 .leak_detector
4313 .lock()
4314 .handle_created(Some(type_name::<T>()), model_id);
4315
4316 Self {
4317 model_id,
4318 model_type: PhantomData,
4319 ref_counts: ref_counts.clone(),
4320
4321 #[cfg(any(test, feature = "test-support"))]
4322 handle_id,
4323 }
4324 }
4325
4326 pub fn downgrade(&self) -> WeakModelHandle<T> {
4327 WeakModelHandle::new(self.model_id)
4328 }
4329
4330 pub fn id(&self) -> usize {
4331 self.model_id
4332 }
4333
4334 pub fn read<'a, C: ReadModel>(&self, cx: &'a C) -> &'a T {
4335 cx.read_model(self)
4336 }
4337
4338 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
4339 where
4340 C: ReadModelWith,
4341 F: FnOnce(&T, &AppContext) -> S,
4342 {
4343 let mut read = Some(read);
4344 cx.read_model_with(self, &mut |model, cx| {
4345 let read = read.take().unwrap();
4346 read(model, cx)
4347 })
4348 }
4349
4350 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
4351 where
4352 C: UpdateModel,
4353 F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
4354 {
4355 let mut update = Some(update);
4356 cx.update_model(self, &mut |model, cx| {
4357 let update = update.take().unwrap();
4358 update(model, cx)
4359 })
4360 }
4361}
4362
4363impl<T: Entity> Clone for ModelHandle<T> {
4364 fn clone(&self) -> Self {
4365 Self::new(self.model_id, &self.ref_counts)
4366 }
4367}
4368
4369impl<T: Entity> PartialEq for ModelHandle<T> {
4370 fn eq(&self, other: &Self) -> bool {
4371 self.model_id == other.model_id
4372 }
4373}
4374
4375impl<T: Entity> Eq for ModelHandle<T> {}
4376
4377impl<T: Entity> PartialEq<WeakModelHandle<T>> for ModelHandle<T> {
4378 fn eq(&self, other: &WeakModelHandle<T>) -> bool {
4379 self.model_id == other.model_id
4380 }
4381}
4382
4383impl<T: Entity> Hash for ModelHandle<T> {
4384 fn hash<H: Hasher>(&self, state: &mut H) {
4385 self.model_id.hash(state);
4386 }
4387}
4388
4389impl<T: Entity> std::borrow::Borrow<usize> for ModelHandle<T> {
4390 fn borrow(&self) -> &usize {
4391 &self.model_id
4392 }
4393}
4394
4395impl<T: Entity> Debug for ModelHandle<T> {
4396 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4397 f.debug_tuple(&format!("ModelHandle<{}>", type_name::<T>()))
4398 .field(&self.model_id)
4399 .finish()
4400 }
4401}
4402
4403unsafe impl<T: Entity> Send for ModelHandle<T> {}
4404unsafe impl<T: Entity> Sync for ModelHandle<T> {}
4405
4406impl<T: Entity> Drop for ModelHandle<T> {
4407 fn drop(&mut self) {
4408 let mut ref_counts = self.ref_counts.lock();
4409 ref_counts.dec_model(self.model_id);
4410
4411 #[cfg(any(test, feature = "test-support"))]
4412 ref_counts
4413 .leak_detector
4414 .lock()
4415 .handle_dropped(self.model_id, self.handle_id);
4416 }
4417}
4418
4419impl<T: Entity> Handle<T> for ModelHandle<T> {
4420 type Weak = WeakModelHandle<T>;
4421
4422 fn id(&self) -> usize {
4423 self.model_id
4424 }
4425
4426 fn location(&self) -> EntityLocation {
4427 EntityLocation::Model(self.model_id)
4428 }
4429
4430 fn downgrade(&self) -> Self::Weak {
4431 self.downgrade()
4432 }
4433
4434 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4435 where
4436 Self: Sized,
4437 {
4438 weak.upgrade(cx)
4439 }
4440}
4441
4442pub struct WeakModelHandle<T> {
4443 model_id: usize,
4444 model_type: PhantomData<T>,
4445}
4446
4447impl<T> WeakHandle for WeakModelHandle<T> {
4448 fn id(&self) -> usize {
4449 self.model_id
4450 }
4451}
4452
4453unsafe impl<T> Send for WeakModelHandle<T> {}
4454unsafe impl<T> Sync for WeakModelHandle<T> {}
4455
4456impl<T: Entity> WeakModelHandle<T> {
4457 fn new(model_id: usize) -> Self {
4458 Self {
4459 model_id,
4460 model_type: PhantomData,
4461 }
4462 }
4463
4464 pub fn id(&self) -> usize {
4465 self.model_id
4466 }
4467
4468 pub fn is_upgradable(&self, cx: &impl UpgradeModelHandle) -> bool {
4469 cx.model_handle_is_upgradable(self)
4470 }
4471
4472 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<ModelHandle<T>> {
4473 cx.upgrade_model_handle(self)
4474 }
4475}
4476
4477impl<T> Hash for WeakModelHandle<T> {
4478 fn hash<H: Hasher>(&self, state: &mut H) {
4479 self.model_id.hash(state)
4480 }
4481}
4482
4483impl<T> PartialEq for WeakModelHandle<T> {
4484 fn eq(&self, other: &Self) -> bool {
4485 self.model_id == other.model_id
4486 }
4487}
4488
4489impl<T> Eq for WeakModelHandle<T> {}
4490
4491impl<T: Entity> PartialEq<ModelHandle<T>> for WeakModelHandle<T> {
4492 fn eq(&self, other: &ModelHandle<T>) -> bool {
4493 self.model_id == other.model_id
4494 }
4495}
4496
4497impl<T> Clone for WeakModelHandle<T> {
4498 fn clone(&self) -> Self {
4499 Self {
4500 model_id: self.model_id,
4501 model_type: PhantomData,
4502 }
4503 }
4504}
4505
4506impl<T> Copy for WeakModelHandle<T> {}
4507
4508pub struct ViewHandle<T> {
4509 window_id: usize,
4510 view_id: usize,
4511 view_type: PhantomData<T>,
4512 ref_counts: Arc<Mutex<RefCounts>>,
4513 #[cfg(any(test, feature = "test-support"))]
4514 handle_id: usize,
4515}
4516
4517impl<T: View> ViewHandle<T> {
4518 fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
4519 ref_counts.lock().inc_view(window_id, view_id);
4520 #[cfg(any(test, feature = "test-support"))]
4521 let handle_id = ref_counts
4522 .lock()
4523 .leak_detector
4524 .lock()
4525 .handle_created(Some(type_name::<T>()), view_id);
4526
4527 Self {
4528 window_id,
4529 view_id,
4530 view_type: PhantomData,
4531 ref_counts: ref_counts.clone(),
4532
4533 #[cfg(any(test, feature = "test-support"))]
4534 handle_id,
4535 }
4536 }
4537
4538 pub fn downgrade(&self) -> WeakViewHandle<T> {
4539 WeakViewHandle::new(self.window_id, self.view_id)
4540 }
4541
4542 pub fn window_id(&self) -> usize {
4543 self.window_id
4544 }
4545
4546 pub fn id(&self) -> usize {
4547 self.view_id
4548 }
4549
4550 pub fn read<'a, C: ReadView>(&self, cx: &'a C) -> &'a T {
4551 cx.read_view(self)
4552 }
4553
4554 pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> S
4555 where
4556 C: ReadViewWith,
4557 F: FnOnce(&T, &AppContext) -> S,
4558 {
4559 let mut read = Some(read);
4560 cx.read_view_with(self, &mut |view, cx| {
4561 let read = read.take().unwrap();
4562 read(view, cx)
4563 })
4564 }
4565
4566 pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
4567 where
4568 C: UpdateView,
4569 F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
4570 {
4571 let mut update = Some(update);
4572 cx.update_view(self, &mut |view, cx| {
4573 let update = update.take().unwrap();
4574 update(view, cx)
4575 })
4576 }
4577
4578 pub fn defer<C, F>(&self, cx: &mut C, update: F)
4579 where
4580 C: AsMut<MutableAppContext>,
4581 F: 'static + FnOnce(&mut T, &mut ViewContext<T>),
4582 {
4583 let this = self.clone();
4584 cx.as_mut().defer(move |cx| {
4585 this.update(cx, |view, cx| update(view, cx));
4586 });
4587 }
4588
4589 pub fn is_focused(&self, cx: &AppContext) -> bool {
4590 cx.focused_view_id(self.window_id)
4591 .map_or(false, |focused_id| focused_id == self.view_id)
4592 }
4593}
4594
4595impl<T: View> Clone for ViewHandle<T> {
4596 fn clone(&self) -> Self {
4597 ViewHandle::new(self.window_id, self.view_id, &self.ref_counts)
4598 }
4599}
4600
4601impl<T> PartialEq for ViewHandle<T> {
4602 fn eq(&self, other: &Self) -> bool {
4603 self.window_id == other.window_id && self.view_id == other.view_id
4604 }
4605}
4606
4607impl<T> PartialEq<WeakViewHandle<T>> for ViewHandle<T> {
4608 fn eq(&self, other: &WeakViewHandle<T>) -> bool {
4609 self.window_id == other.window_id && self.view_id == other.view_id
4610 }
4611}
4612
4613impl<T> PartialEq<ViewHandle<T>> for WeakViewHandle<T> {
4614 fn eq(&self, other: &ViewHandle<T>) -> bool {
4615 self.window_id == other.window_id && self.view_id == other.view_id
4616 }
4617}
4618
4619impl<T> Eq for ViewHandle<T> {}
4620
4621impl<T> Hash for ViewHandle<T> {
4622 fn hash<H: Hasher>(&self, state: &mut H) {
4623 self.window_id.hash(state);
4624 self.view_id.hash(state);
4625 }
4626}
4627
4628impl<T> Debug for ViewHandle<T> {
4629 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4630 f.debug_struct(&format!("ViewHandle<{}>", type_name::<T>()))
4631 .field("window_id", &self.window_id)
4632 .field("view_id", &self.view_id)
4633 .finish()
4634 }
4635}
4636
4637impl<T> Drop for ViewHandle<T> {
4638 fn drop(&mut self) {
4639 self.ref_counts
4640 .lock()
4641 .dec_view(self.window_id, self.view_id);
4642 #[cfg(any(test, feature = "test-support"))]
4643 self.ref_counts
4644 .lock()
4645 .leak_detector
4646 .lock()
4647 .handle_dropped(self.view_id, self.handle_id);
4648 }
4649}
4650
4651impl<T: View> Handle<T> for ViewHandle<T> {
4652 type Weak = WeakViewHandle<T>;
4653
4654 fn id(&self) -> usize {
4655 self.view_id
4656 }
4657
4658 fn location(&self) -> EntityLocation {
4659 EntityLocation::View(self.window_id, self.view_id)
4660 }
4661
4662 fn downgrade(&self) -> Self::Weak {
4663 self.downgrade()
4664 }
4665
4666 fn upgrade_from(weak: &Self::Weak, cx: &AppContext) -> Option<Self>
4667 where
4668 Self: Sized,
4669 {
4670 weak.upgrade(cx)
4671 }
4672}
4673
4674pub struct AnyViewHandle {
4675 window_id: usize,
4676 view_id: usize,
4677 view_type: TypeId,
4678 ref_counts: Arc<Mutex<RefCounts>>,
4679
4680 #[cfg(any(test, feature = "test-support"))]
4681 handle_id: usize,
4682}
4683
4684impl AnyViewHandle {
4685 fn new(
4686 window_id: usize,
4687 view_id: usize,
4688 view_type: TypeId,
4689 ref_counts: Arc<Mutex<RefCounts>>,
4690 ) -> Self {
4691 ref_counts.lock().inc_view(window_id, view_id);
4692
4693 #[cfg(any(test, feature = "test-support"))]
4694 let handle_id = ref_counts
4695 .lock()
4696 .leak_detector
4697 .lock()
4698 .handle_created(None, view_id);
4699
4700 Self {
4701 window_id,
4702 view_id,
4703 view_type,
4704 ref_counts,
4705 #[cfg(any(test, feature = "test-support"))]
4706 handle_id,
4707 }
4708 }
4709
4710 pub fn window_id(&self) -> usize {
4711 self.window_id
4712 }
4713
4714 pub fn id(&self) -> usize {
4715 self.view_id
4716 }
4717
4718 pub fn is<T: 'static>(&self) -> bool {
4719 TypeId::of::<T>() == self.view_type
4720 }
4721
4722 pub fn is_focused(&self, cx: &AppContext) -> bool {
4723 cx.focused_view_id(self.window_id)
4724 .map_or(false, |focused_id| focused_id == self.view_id)
4725 }
4726
4727 pub fn downcast<T: View>(self) -> Option<ViewHandle<T>> {
4728 if self.is::<T>() {
4729 let result = Some(ViewHandle {
4730 window_id: self.window_id,
4731 view_id: self.view_id,
4732 ref_counts: self.ref_counts.clone(),
4733 view_type: PhantomData,
4734 #[cfg(any(test, feature = "test-support"))]
4735 handle_id: self.handle_id,
4736 });
4737 unsafe {
4738 Arc::decrement_strong_count(Arc::as_ptr(&self.ref_counts));
4739 }
4740 std::mem::forget(self);
4741 result
4742 } else {
4743 None
4744 }
4745 }
4746
4747 pub fn downgrade(&self) -> AnyWeakViewHandle {
4748 AnyWeakViewHandle {
4749 window_id: self.window_id,
4750 view_id: self.view_id,
4751 view_type: self.view_type,
4752 }
4753 }
4754
4755 pub fn view_type(&self) -> TypeId {
4756 self.view_type
4757 }
4758
4759 pub fn debug_json(&self, cx: &AppContext) -> serde_json::Value {
4760 cx.views
4761 .get(&(self.window_id, self.view_id))
4762 .map_or_else(|| serde_json::Value::Null, |view| view.debug_json(cx))
4763 }
4764}
4765
4766impl Clone for AnyViewHandle {
4767 fn clone(&self) -> Self {
4768 Self::new(
4769 self.window_id,
4770 self.view_id,
4771 self.view_type,
4772 self.ref_counts.clone(),
4773 )
4774 }
4775}
4776
4777impl From<&AnyViewHandle> for AnyViewHandle {
4778 fn from(handle: &AnyViewHandle) -> Self {
4779 handle.clone()
4780 }
4781}
4782
4783impl<T: View> From<&ViewHandle<T>> for AnyViewHandle {
4784 fn from(handle: &ViewHandle<T>) -> Self {
4785 Self::new(
4786 handle.window_id,
4787 handle.view_id,
4788 TypeId::of::<T>(),
4789 handle.ref_counts.clone(),
4790 )
4791 }
4792}
4793
4794impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
4795 fn from(handle: ViewHandle<T>) -> Self {
4796 let any_handle = AnyViewHandle {
4797 window_id: handle.window_id,
4798 view_id: handle.view_id,
4799 view_type: TypeId::of::<T>(),
4800 ref_counts: handle.ref_counts.clone(),
4801 #[cfg(any(test, feature = "test-support"))]
4802 handle_id: handle.handle_id,
4803 };
4804
4805 unsafe {
4806 Arc::decrement_strong_count(Arc::as_ptr(&handle.ref_counts));
4807 }
4808 std::mem::forget(handle);
4809 any_handle
4810 }
4811}
4812
4813impl Drop for AnyViewHandle {
4814 fn drop(&mut self) {
4815 self.ref_counts
4816 .lock()
4817 .dec_view(self.window_id, self.view_id);
4818 #[cfg(any(test, feature = "test-support"))]
4819 self.ref_counts
4820 .lock()
4821 .leak_detector
4822 .lock()
4823 .handle_dropped(self.view_id, self.handle_id);
4824 }
4825}
4826
4827pub struct AnyModelHandle {
4828 model_id: usize,
4829 model_type: TypeId,
4830 ref_counts: Arc<Mutex<RefCounts>>,
4831
4832 #[cfg(any(test, feature = "test-support"))]
4833 handle_id: usize,
4834}
4835
4836impl AnyModelHandle {
4837 fn new(model_id: usize, model_type: TypeId, ref_counts: Arc<Mutex<RefCounts>>) -> Self {
4838 ref_counts.lock().inc_model(model_id);
4839
4840 #[cfg(any(test, feature = "test-support"))]
4841 let handle_id = ref_counts
4842 .lock()
4843 .leak_detector
4844 .lock()
4845 .handle_created(None, model_id);
4846
4847 Self {
4848 model_id,
4849 model_type,
4850 ref_counts,
4851
4852 #[cfg(any(test, feature = "test-support"))]
4853 handle_id,
4854 }
4855 }
4856
4857 pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> {
4858 if self.is::<T>() {
4859 let result = Some(ModelHandle {
4860 model_id: self.model_id,
4861 model_type: PhantomData,
4862 ref_counts: self.ref_counts.clone(),
4863
4864 #[cfg(any(test, feature = "test-support"))]
4865 handle_id: self.handle_id,
4866 });
4867 unsafe {
4868 Arc::decrement_strong_count(Arc::as_ptr(&self.ref_counts));
4869 }
4870 std::mem::forget(self);
4871 result
4872 } else {
4873 None
4874 }
4875 }
4876
4877 pub fn downgrade(&self) -> AnyWeakModelHandle {
4878 AnyWeakModelHandle {
4879 model_id: self.model_id,
4880 model_type: self.model_type,
4881 }
4882 }
4883
4884 pub fn is<T: Entity>(&self) -> bool {
4885 self.model_type == TypeId::of::<T>()
4886 }
4887
4888 pub fn model_type(&self) -> TypeId {
4889 self.model_type
4890 }
4891}
4892
4893impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
4894 fn from(handle: ModelHandle<T>) -> Self {
4895 Self::new(
4896 handle.model_id,
4897 TypeId::of::<T>(),
4898 handle.ref_counts.clone(),
4899 )
4900 }
4901}
4902
4903impl Clone for AnyModelHandle {
4904 fn clone(&self) -> Self {
4905 Self::new(self.model_id, self.model_type, self.ref_counts.clone())
4906 }
4907}
4908
4909impl Drop for AnyModelHandle {
4910 fn drop(&mut self) {
4911 let mut ref_counts = self.ref_counts.lock();
4912 ref_counts.dec_model(self.model_id);
4913
4914 #[cfg(any(test, feature = "test-support"))]
4915 ref_counts
4916 .leak_detector
4917 .lock()
4918 .handle_dropped(self.model_id, self.handle_id);
4919 }
4920}
4921
4922#[derive(Hash, PartialEq, Eq, Debug)]
4923pub struct AnyWeakModelHandle {
4924 model_id: usize,
4925 model_type: TypeId,
4926}
4927
4928impl AnyWeakModelHandle {
4929 pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<AnyModelHandle> {
4930 cx.upgrade_any_model_handle(self)
4931 }
4932 pub fn model_type(&self) -> TypeId {
4933 self.model_type
4934 }
4935
4936 fn is<T: 'static>(&self) -> bool {
4937 TypeId::of::<T>() == self.model_type
4938 }
4939
4940 pub fn downcast<T: Entity>(&self) -> Option<WeakModelHandle<T>> {
4941 if self.is::<T>() {
4942 let result = Some(WeakModelHandle {
4943 model_id: self.model_id,
4944 model_type: PhantomData,
4945 });
4946
4947 result
4948 } else {
4949 None
4950 }
4951 }
4952}
4953
4954impl<T: Entity> From<WeakModelHandle<T>> for AnyWeakModelHandle {
4955 fn from(handle: WeakModelHandle<T>) -> Self {
4956 AnyWeakModelHandle {
4957 model_id: handle.model_id,
4958 model_type: TypeId::of::<T>(),
4959 }
4960 }
4961}
4962
4963#[derive(Debug)]
4964pub struct WeakViewHandle<T> {
4965 window_id: usize,
4966 view_id: usize,
4967 view_type: PhantomData<T>,
4968}
4969
4970impl<T> WeakHandle for WeakViewHandle<T> {
4971 fn id(&self) -> usize {
4972 self.view_id
4973 }
4974}
4975
4976impl<T: View> WeakViewHandle<T> {
4977 fn new(window_id: usize, view_id: usize) -> Self {
4978 Self {
4979 window_id,
4980 view_id,
4981 view_type: PhantomData,
4982 }
4983 }
4984
4985 pub fn id(&self) -> usize {
4986 self.view_id
4987 }
4988
4989 pub fn window_id(&self) -> usize {
4990 self.window_id
4991 }
4992
4993 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<ViewHandle<T>> {
4994 cx.upgrade_view_handle(self)
4995 }
4996}
4997
4998impl<T> Clone for WeakViewHandle<T> {
4999 fn clone(&self) -> Self {
5000 Self {
5001 window_id: self.window_id,
5002 view_id: self.view_id,
5003 view_type: PhantomData,
5004 }
5005 }
5006}
5007
5008impl<T> PartialEq for WeakViewHandle<T> {
5009 fn eq(&self, other: &Self) -> bool {
5010 self.window_id == other.window_id && self.view_id == other.view_id
5011 }
5012}
5013
5014impl<T> Eq for WeakViewHandle<T> {}
5015
5016impl<T> Hash for WeakViewHandle<T> {
5017 fn hash<H: Hasher>(&self, state: &mut H) {
5018 self.window_id.hash(state);
5019 self.view_id.hash(state);
5020 }
5021}
5022
5023pub struct AnyWeakViewHandle {
5024 window_id: usize,
5025 view_id: usize,
5026 view_type: TypeId,
5027}
5028
5029impl AnyWeakViewHandle {
5030 pub fn id(&self) -> usize {
5031 self.view_id
5032 }
5033
5034 pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<AnyViewHandle> {
5035 cx.upgrade_any_view_handle(self)
5036 }
5037}
5038
5039impl<T: View> From<WeakViewHandle<T>> for AnyWeakViewHandle {
5040 fn from(handle: WeakViewHandle<T>) -> Self {
5041 AnyWeakViewHandle {
5042 window_id: handle.window_id,
5043 view_id: handle.view_id,
5044 view_type: TypeId::of::<T>(),
5045 }
5046 }
5047}
5048
5049#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
5050pub struct ElementStateId {
5051 view_id: usize,
5052 element_id: usize,
5053 tag: TypeId,
5054}
5055
5056pub struct ElementStateHandle<T> {
5057 value_type: PhantomData<T>,
5058 id: ElementStateId,
5059 ref_counts: Weak<Mutex<RefCounts>>,
5060}
5061
5062impl<T: 'static> ElementStateHandle<T> {
5063 fn new(id: ElementStateId, frame_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
5064 ref_counts.lock().inc_element_state(id, frame_id);
5065 Self {
5066 value_type: PhantomData,
5067 id,
5068 ref_counts: Arc::downgrade(ref_counts),
5069 }
5070 }
5071
5072 pub fn id(&self) -> ElementStateId {
5073 self.id
5074 }
5075
5076 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
5077 cx.element_states
5078 .get(&self.id)
5079 .unwrap()
5080 .downcast_ref()
5081 .unwrap()
5082 }
5083
5084 pub fn update<C, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R
5085 where
5086 C: DerefMut<Target = MutableAppContext>,
5087 {
5088 let mut element_state = cx.deref_mut().cx.element_states.remove(&self.id).unwrap();
5089 let result = f(element_state.downcast_mut().unwrap(), cx);
5090 cx.deref_mut()
5091 .cx
5092 .element_states
5093 .insert(self.id, element_state);
5094 result
5095 }
5096}
5097
5098impl<T> Drop for ElementStateHandle<T> {
5099 fn drop(&mut self) {
5100 if let Some(ref_counts) = self.ref_counts.upgrade() {
5101 ref_counts.lock().dec_element_state(self.id);
5102 }
5103 }
5104}
5105
5106#[must_use]
5107pub enum Subscription {
5108 Subscription {
5109 id: usize,
5110 entity_id: usize,
5111 subscriptions: Option<Weak<Mapping<usize, SubscriptionCallback>>>,
5112 },
5113 GlobalSubscription {
5114 id: usize,
5115 type_id: TypeId,
5116 subscriptions: Option<Weak<Mapping<TypeId, GlobalSubscriptionCallback>>>,
5117 },
5118 Observation {
5119 id: usize,
5120 entity_id: usize,
5121 observations: Option<Weak<Mapping<usize, ObservationCallback>>>,
5122 },
5123 GlobalObservation {
5124 id: usize,
5125 type_id: TypeId,
5126 observations: Option<Weak<Mapping<TypeId, GlobalObservationCallback>>>,
5127 },
5128 FocusObservation {
5129 id: usize,
5130 view_id: usize,
5131 observations: Option<Weak<Mapping<usize, FocusObservationCallback>>>,
5132 },
5133 WindowActivationObservation {
5134 id: usize,
5135 window_id: usize,
5136 observations: Option<Weak<Mapping<usize, WindowActivationCallback>>>,
5137 },
5138 WindowFullscreenObservation {
5139 id: usize,
5140 window_id: usize,
5141 observations: Option<Weak<Mapping<usize, WindowFullscreenCallback>>>,
5142 },
5143 KeystrokeObservation {
5144 id: usize,
5145 window_id: usize,
5146 observations: Option<Weak<Mapping<usize, KeystrokeCallback>>>,
5147 },
5148
5149 ReleaseObservation {
5150 id: usize,
5151 entity_id: usize,
5152 #[allow(clippy::type_complexity)]
5153 observations:
5154 Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>>,
5155 },
5156 ActionObservation {
5157 id: usize,
5158 observations: Option<Weak<Mutex<BTreeMap<usize, ActionObservationCallback>>>>,
5159 },
5160}
5161
5162impl Subscription {
5163 pub fn detach(&mut self) {
5164 match self {
5165 Subscription::Subscription { subscriptions, .. } => {
5166 subscriptions.take();
5167 }
5168 Subscription::GlobalSubscription { subscriptions, .. } => {
5169 subscriptions.take();
5170 }
5171 Subscription::Observation { observations, .. } => {
5172 observations.take();
5173 }
5174 Subscription::GlobalObservation { observations, .. } => {
5175 observations.take();
5176 }
5177 Subscription::ReleaseObservation { observations, .. } => {
5178 observations.take();
5179 }
5180 Subscription::FocusObservation { observations, .. } => {
5181 observations.take();
5182 }
5183 Subscription::ActionObservation { observations, .. } => {
5184 observations.take();
5185 }
5186 Subscription::KeystrokeObservation { observations, .. } => {
5187 observations.take();
5188 }
5189 Subscription::WindowActivationObservation { observations, .. } => {
5190 observations.take();
5191 }
5192 Subscription::WindowFullscreenObservation { observations, .. } => {
5193 observations.take();
5194 }
5195 }
5196 }
5197}
5198
5199impl Drop for Subscription {
5200 fn drop(&mut self) {
5201 match self {
5202 Subscription::Subscription {
5203 id,
5204 entity_id,
5205 subscriptions,
5206 } => {
5207 if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
5208 match subscriptions
5209 .lock()
5210 .entry(*entity_id)
5211 .or_default()
5212 .entry(*id)
5213 {
5214 btree_map::Entry::Vacant(entry) => {
5215 entry.insert(None);
5216 }
5217 btree_map::Entry::Occupied(entry) => {
5218 entry.remove();
5219 }
5220 }
5221 }
5222 }
5223 Subscription::GlobalSubscription {
5224 id,
5225 type_id,
5226 subscriptions,
5227 } => {
5228 if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
5229 match subscriptions.lock().entry(*type_id).or_default().entry(*id) {
5230 btree_map::Entry::Vacant(entry) => {
5231 entry.insert(None);
5232 }
5233 btree_map::Entry::Occupied(entry) => {
5234 entry.remove();
5235 }
5236 }
5237 }
5238 }
5239 Subscription::Observation {
5240 id,
5241 entity_id,
5242 observations,
5243 } => {
5244 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5245 match observations
5246 .lock()
5247 .entry(*entity_id)
5248 .or_default()
5249 .entry(*id)
5250 {
5251 btree_map::Entry::Vacant(entry) => {
5252 entry.insert(None);
5253 }
5254 btree_map::Entry::Occupied(entry) => {
5255 entry.remove();
5256 }
5257 }
5258 }
5259 }
5260 Subscription::GlobalObservation {
5261 id,
5262 type_id,
5263 observations,
5264 } => {
5265 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5266 match observations.lock().entry(*type_id).or_default().entry(*id) {
5267 collections::btree_map::Entry::Vacant(entry) => {
5268 entry.insert(None);
5269 }
5270 collections::btree_map::Entry::Occupied(entry) => {
5271 entry.remove();
5272 }
5273 }
5274 }
5275 }
5276 Subscription::ReleaseObservation {
5277 id,
5278 entity_id,
5279 observations,
5280 } => {
5281 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5282 if let Some(observations) = observations.lock().get_mut(entity_id) {
5283 observations.remove(id);
5284 }
5285 }
5286 }
5287 Subscription::FocusObservation {
5288 id,
5289 view_id,
5290 observations,
5291 } => {
5292 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5293 match observations.lock().entry(*view_id).or_default().entry(*id) {
5294 btree_map::Entry::Vacant(entry) => {
5295 entry.insert(None);
5296 }
5297 btree_map::Entry::Occupied(entry) => {
5298 entry.remove();
5299 }
5300 }
5301 }
5302 }
5303 Subscription::ActionObservation { id, observations } => {
5304 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5305 observations.lock().remove(id);
5306 }
5307 }
5308 Subscription::KeystrokeObservation {
5309 id,
5310 window_id,
5311 observations,
5312 } => {
5313 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5314 match observations
5315 .lock()
5316 .entry(*window_id)
5317 .or_default()
5318 .entry(*id)
5319 {
5320 btree_map::Entry::Vacant(entry) => {
5321 entry.insert(None);
5322 }
5323 btree_map::Entry::Occupied(entry) => {
5324 entry.remove();
5325 }
5326 }
5327 }
5328 }
5329 Subscription::WindowActivationObservation {
5330 id,
5331 window_id,
5332 observations,
5333 } => {
5334 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5335 match observations
5336 .lock()
5337 .entry(*window_id)
5338 .or_default()
5339 .entry(*id)
5340 {
5341 btree_map::Entry::Vacant(entry) => {
5342 entry.insert(None);
5343 }
5344 btree_map::Entry::Occupied(entry) => {
5345 entry.remove();
5346 }
5347 }
5348 }
5349 }
5350 Subscription::WindowFullscreenObservation {
5351 id,
5352 window_id,
5353 observations,
5354 } => {
5355 if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) {
5356 match observations
5357 .lock()
5358 .entry(*window_id)
5359 .or_default()
5360 .entry(*id)
5361 {
5362 btree_map::Entry::Vacant(entry) => {
5363 entry.insert(None);
5364 }
5365 btree_map::Entry::Occupied(entry) => {
5366 entry.remove();
5367 }
5368 }
5369 }
5370 }
5371 }
5372 }
5373}
5374
5375lazy_static! {
5376 static ref LEAK_BACKTRACE: bool =
5377 std::env::var("LEAK_BACKTRACE").map_or(false, |b| !b.is_empty());
5378}
5379
5380#[cfg(any(test, feature = "test-support"))]
5381#[derive(Default)]
5382pub struct LeakDetector {
5383 next_handle_id: usize,
5384 #[allow(clippy::type_complexity)]
5385 handle_backtraces: HashMap<
5386 usize,
5387 (
5388 Option<&'static str>,
5389 HashMap<usize, Option<backtrace::Backtrace>>,
5390 ),
5391 >,
5392}
5393
5394#[cfg(any(test, feature = "test-support"))]
5395impl LeakDetector {
5396 fn handle_created(&mut self, type_name: Option<&'static str>, entity_id: usize) -> usize {
5397 let handle_id = post_inc(&mut self.next_handle_id);
5398 let entry = self.handle_backtraces.entry(entity_id).or_default();
5399 let backtrace = if *LEAK_BACKTRACE {
5400 Some(backtrace::Backtrace::new_unresolved())
5401 } else {
5402 None
5403 };
5404 if let Some(type_name) = type_name {
5405 entry.0.get_or_insert(type_name);
5406 }
5407 entry.1.insert(handle_id, backtrace);
5408 handle_id
5409 }
5410
5411 fn handle_dropped(&mut self, entity_id: usize, handle_id: usize) {
5412 if let Some((_, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
5413 assert!(backtraces.remove(&handle_id).is_some());
5414 if backtraces.is_empty() {
5415 self.handle_backtraces.remove(&entity_id);
5416 }
5417 }
5418 }
5419
5420 pub fn assert_dropped(&mut self, entity_id: usize) {
5421 if let Some((type_name, backtraces)) = self.handle_backtraces.get_mut(&entity_id) {
5422 for trace in backtraces.values_mut().flatten() {
5423 trace.resolve();
5424 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
5425 }
5426
5427 let hint = if *LEAK_BACKTRACE {
5428 ""
5429 } else {
5430 " – set LEAK_BACKTRACE=1 for more information"
5431 };
5432
5433 panic!(
5434 "{} handles to {} {} still exist{}",
5435 backtraces.len(),
5436 type_name.unwrap_or("entity"),
5437 entity_id,
5438 hint
5439 );
5440 }
5441 }
5442
5443 pub fn detect(&mut self) {
5444 let mut found_leaks = false;
5445 for (id, (type_name, backtraces)) in self.handle_backtraces.iter_mut() {
5446 eprintln!(
5447 "leaked {} handles to {} {}",
5448 backtraces.len(),
5449 type_name.unwrap_or("entity"),
5450 id
5451 );
5452 for trace in backtraces.values_mut().flatten() {
5453 trace.resolve();
5454 eprintln!("{:?}", crate::util::CwdBacktrace(trace));
5455 }
5456 found_leaks = true;
5457 }
5458
5459 let hint = if *LEAK_BACKTRACE {
5460 ""
5461 } else {
5462 " – set LEAK_BACKTRACE=1 for more information"
5463 };
5464 assert!(!found_leaks, "detected leaked handles{}", hint);
5465 }
5466}
5467
5468#[derive(Default)]
5469struct RefCounts {
5470 entity_counts: HashMap<usize, usize>,
5471 element_state_counts: HashMap<ElementStateId, ElementStateRefCount>,
5472 dropped_models: HashSet<usize>,
5473 dropped_views: HashSet<(usize, usize)>,
5474 dropped_element_states: HashSet<ElementStateId>,
5475
5476 #[cfg(any(test, feature = "test-support"))]
5477 leak_detector: Arc<Mutex<LeakDetector>>,
5478}
5479
5480struct ElementStateRefCount {
5481 ref_count: usize,
5482 frame_id: usize,
5483}
5484
5485impl RefCounts {
5486 fn inc_model(&mut self, model_id: usize) {
5487 match self.entity_counts.entry(model_id) {
5488 Entry::Occupied(mut entry) => {
5489 *entry.get_mut() += 1;
5490 }
5491 Entry::Vacant(entry) => {
5492 entry.insert(1);
5493 self.dropped_models.remove(&model_id);
5494 }
5495 }
5496 }
5497
5498 fn inc_view(&mut self, window_id: usize, view_id: usize) {
5499 match self.entity_counts.entry(view_id) {
5500 Entry::Occupied(mut entry) => *entry.get_mut() += 1,
5501 Entry::Vacant(entry) => {
5502 entry.insert(1);
5503 self.dropped_views.remove(&(window_id, view_id));
5504 }
5505 }
5506 }
5507
5508 fn inc_element_state(&mut self, id: ElementStateId, frame_id: usize) {
5509 match self.element_state_counts.entry(id) {
5510 Entry::Occupied(mut entry) => {
5511 let entry = entry.get_mut();
5512 if entry.frame_id == frame_id || entry.ref_count >= 2 {
5513 panic!("used the same element state more than once in the same frame");
5514 }
5515 entry.ref_count += 1;
5516 entry.frame_id = frame_id;
5517 }
5518 Entry::Vacant(entry) => {
5519 entry.insert(ElementStateRefCount {
5520 ref_count: 1,
5521 frame_id,
5522 });
5523 self.dropped_element_states.remove(&id);
5524 }
5525 }
5526 }
5527
5528 fn dec_model(&mut self, model_id: usize) {
5529 let count = self.entity_counts.get_mut(&model_id).unwrap();
5530 *count -= 1;
5531 if *count == 0 {
5532 self.entity_counts.remove(&model_id);
5533 self.dropped_models.insert(model_id);
5534 }
5535 }
5536
5537 fn dec_view(&mut self, window_id: usize, view_id: usize) {
5538 let count = self.entity_counts.get_mut(&view_id).unwrap();
5539 *count -= 1;
5540 if *count == 0 {
5541 self.entity_counts.remove(&view_id);
5542 self.dropped_views.insert((window_id, view_id));
5543 }
5544 }
5545
5546 fn dec_element_state(&mut self, id: ElementStateId) {
5547 let entry = self.element_state_counts.get_mut(&id).unwrap();
5548 entry.ref_count -= 1;
5549 if entry.ref_count == 0 {
5550 self.element_state_counts.remove(&id);
5551 self.dropped_element_states.insert(id);
5552 }
5553 }
5554
5555 fn is_entity_alive(&self, entity_id: usize) -> bool {
5556 self.entity_counts.contains_key(&entity_id)
5557 }
5558
5559 fn take_dropped(
5560 &mut self,
5561 ) -> (
5562 HashSet<usize>,
5563 HashSet<(usize, usize)>,
5564 HashSet<ElementStateId>,
5565 ) {
5566 (
5567 std::mem::take(&mut self.dropped_models),
5568 std::mem::take(&mut self.dropped_views),
5569 std::mem::take(&mut self.dropped_element_states),
5570 )
5571 }
5572}
5573
5574#[cfg(test)]
5575mod tests {
5576 use super::*;
5577 use crate::{actions, elements::*, impl_actions, MouseButton, MouseButtonEvent};
5578 use serde::Deserialize;
5579 use smol::future::poll_once;
5580 use std::{
5581 cell::Cell,
5582 sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
5583 };
5584
5585 #[crate::test(self)]
5586 fn test_model_handles(cx: &mut MutableAppContext) {
5587 struct Model {
5588 other: Option<ModelHandle<Model>>,
5589 events: Vec<String>,
5590 }
5591
5592 impl Entity for Model {
5593 type Event = usize;
5594 }
5595
5596 impl Model {
5597 fn new(other: Option<ModelHandle<Self>>, cx: &mut ModelContext<Self>) -> Self {
5598 if let Some(other) = other.as_ref() {
5599 cx.observe(other, |me, _, _| {
5600 me.events.push("notified".into());
5601 })
5602 .detach();
5603 cx.subscribe(other, |me, _, event, _| {
5604 me.events.push(format!("observed event {}", event));
5605 })
5606 .detach();
5607 }
5608
5609 Self {
5610 other,
5611 events: Vec::new(),
5612 }
5613 }
5614 }
5615
5616 let handle_1 = cx.add_model(|cx| Model::new(None, cx));
5617 let handle_2 = cx.add_model(|cx| Model::new(Some(handle_1.clone()), cx));
5618 assert_eq!(cx.cx.models.len(), 2);
5619
5620 handle_1.update(cx, |model, cx| {
5621 model.events.push("updated".into());
5622 cx.emit(1);
5623 cx.notify();
5624 cx.emit(2);
5625 });
5626 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5627 assert_eq!(
5628 handle_2.read(cx).events,
5629 vec![
5630 "observed event 1".to_string(),
5631 "notified".to_string(),
5632 "observed event 2".to_string(),
5633 ]
5634 );
5635
5636 handle_2.update(cx, |model, _| {
5637 drop(handle_1);
5638 model.other.take();
5639 });
5640
5641 assert_eq!(cx.cx.models.len(), 1);
5642 assert!(cx.subscriptions.is_empty());
5643 assert!(cx.observations.is_empty());
5644 }
5645
5646 #[crate::test(self)]
5647 fn test_model_events(cx: &mut MutableAppContext) {
5648 #[derive(Default)]
5649 struct Model {
5650 events: Vec<usize>,
5651 }
5652
5653 impl Entity for Model {
5654 type Event = usize;
5655 }
5656
5657 let handle_1 = cx.add_model(|_| Model::default());
5658 let handle_2 = cx.add_model(|_| Model::default());
5659
5660 handle_1.update(cx, |_, cx| {
5661 cx.subscribe(&handle_2, move |model: &mut Model, emitter, event, cx| {
5662 model.events.push(*event);
5663
5664 cx.subscribe(&emitter, |model, _, event, _| {
5665 model.events.push(*event * 2);
5666 })
5667 .detach();
5668 })
5669 .detach();
5670 });
5671
5672 handle_2.update(cx, |_, c| c.emit(7));
5673 assert_eq!(handle_1.read(cx).events, vec![7]);
5674
5675 handle_2.update(cx, |_, c| c.emit(5));
5676 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
5677 }
5678
5679 #[crate::test(self)]
5680 fn test_model_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
5681 #[derive(Default)]
5682 struct Model;
5683
5684 impl Entity for Model {
5685 type Event = ();
5686 }
5687
5688 let events = Rc::new(RefCell::new(Vec::new()));
5689 cx.add_model(|cx| {
5690 drop(cx.subscribe(&cx.handle(), {
5691 let events = events.clone();
5692 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
5693 }));
5694 cx.subscribe(&cx.handle(), {
5695 let events = events.clone();
5696 move |_, _, _, _| events.borrow_mut().push("before emit")
5697 })
5698 .detach();
5699 cx.emit(());
5700 cx.subscribe(&cx.handle(), {
5701 let events = events.clone();
5702 move |_, _, _, _| events.borrow_mut().push("after emit")
5703 })
5704 .detach();
5705 Model
5706 });
5707 assert_eq!(*events.borrow(), ["before emit"]);
5708 }
5709
5710 #[crate::test(self)]
5711 fn test_observe_and_notify_from_model(cx: &mut MutableAppContext) {
5712 #[derive(Default)]
5713 struct Model {
5714 count: usize,
5715 events: Vec<usize>,
5716 }
5717
5718 impl Entity for Model {
5719 type Event = ();
5720 }
5721
5722 let handle_1 = cx.add_model(|_| Model::default());
5723 let handle_2 = cx.add_model(|_| Model::default());
5724
5725 handle_1.update(cx, |_, c| {
5726 c.observe(&handle_2, move |model, observed, c| {
5727 model.events.push(observed.read(c).count);
5728 c.observe(&observed, |model, observed, c| {
5729 model.events.push(observed.read(c).count * 2);
5730 })
5731 .detach();
5732 })
5733 .detach();
5734 });
5735
5736 handle_2.update(cx, |model, c| {
5737 model.count = 7;
5738 c.notify()
5739 });
5740 assert_eq!(handle_1.read(cx).events, vec![7]);
5741
5742 handle_2.update(cx, |model, c| {
5743 model.count = 5;
5744 c.notify()
5745 });
5746 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10])
5747 }
5748
5749 #[crate::test(self)]
5750 fn test_model_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
5751 #[derive(Default)]
5752 struct Model;
5753
5754 impl Entity for Model {
5755 type Event = ();
5756 }
5757
5758 let events = Rc::new(RefCell::new(Vec::new()));
5759 cx.add_model(|cx| {
5760 drop(cx.observe(&cx.handle(), {
5761 let events = events.clone();
5762 move |_, _, _| events.borrow_mut().push("dropped before flush")
5763 }));
5764 cx.observe(&cx.handle(), {
5765 let events = events.clone();
5766 move |_, _, _| events.borrow_mut().push("before notify")
5767 })
5768 .detach();
5769 cx.notify();
5770 cx.observe(&cx.handle(), {
5771 let events = events.clone();
5772 move |_, _, _| events.borrow_mut().push("after notify")
5773 })
5774 .detach();
5775 Model
5776 });
5777 assert_eq!(*events.borrow(), ["before notify"]);
5778 }
5779
5780 #[crate::test(self)]
5781 fn test_defer_and_after_window_update(cx: &mut MutableAppContext) {
5782 struct View {
5783 render_count: usize,
5784 }
5785
5786 impl Entity for View {
5787 type Event = usize;
5788 }
5789
5790 impl super::View for View {
5791 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5792 post_inc(&mut self.render_count);
5793 Empty::new().boxed()
5794 }
5795
5796 fn ui_name() -> &'static str {
5797 "View"
5798 }
5799 }
5800
5801 let (_, view) = cx.add_window(Default::default(), |_| View { render_count: 0 });
5802 let called_defer = Rc::new(AtomicBool::new(false));
5803 let called_after_window_update = Rc::new(AtomicBool::new(false));
5804
5805 view.update(cx, |this, cx| {
5806 assert_eq!(this.render_count, 1);
5807 cx.defer({
5808 let called_defer = called_defer.clone();
5809 move |this, _| {
5810 assert_eq!(this.render_count, 1);
5811 called_defer.store(true, SeqCst);
5812 }
5813 });
5814 cx.after_window_update({
5815 let called_after_window_update = called_after_window_update.clone();
5816 move |this, cx| {
5817 assert_eq!(this.render_count, 2);
5818 called_after_window_update.store(true, SeqCst);
5819 cx.notify();
5820 }
5821 });
5822 assert!(!called_defer.load(SeqCst));
5823 assert!(!called_after_window_update.load(SeqCst));
5824 cx.notify();
5825 });
5826
5827 assert!(called_defer.load(SeqCst));
5828 assert!(called_after_window_update.load(SeqCst));
5829 assert_eq!(view.read(cx).render_count, 3);
5830 }
5831
5832 #[crate::test(self)]
5833 fn test_view_handles(cx: &mut MutableAppContext) {
5834 struct View {
5835 other: Option<ViewHandle<View>>,
5836 events: Vec<String>,
5837 }
5838
5839 impl Entity for View {
5840 type Event = usize;
5841 }
5842
5843 impl super::View for View {
5844 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5845 Empty::new().boxed()
5846 }
5847
5848 fn ui_name() -> &'static str {
5849 "View"
5850 }
5851 }
5852
5853 impl View {
5854 fn new(other: Option<ViewHandle<View>>, cx: &mut ViewContext<Self>) -> Self {
5855 if let Some(other) = other.as_ref() {
5856 cx.subscribe(other, |me, _, event, _| {
5857 me.events.push(format!("observed event {}", event));
5858 })
5859 .detach();
5860 }
5861 Self {
5862 other,
5863 events: Vec::new(),
5864 }
5865 }
5866 }
5867
5868 let (_, root_view) = cx.add_window(Default::default(), |cx| View::new(None, cx));
5869 let handle_1 = cx.add_view(&root_view, |cx| View::new(None, cx));
5870 let handle_2 = cx.add_view(&root_view, |cx| View::new(Some(handle_1.clone()), cx));
5871 assert_eq!(cx.cx.views.len(), 3);
5872
5873 handle_1.update(cx, |view, cx| {
5874 view.events.push("updated".into());
5875 cx.emit(1);
5876 cx.emit(2);
5877 });
5878 assert_eq!(handle_1.read(cx).events, vec!["updated".to_string()]);
5879 assert_eq!(
5880 handle_2.read(cx).events,
5881 vec![
5882 "observed event 1".to_string(),
5883 "observed event 2".to_string(),
5884 ]
5885 );
5886
5887 handle_2.update(cx, |view, _| {
5888 drop(handle_1);
5889 view.other.take();
5890 });
5891
5892 assert_eq!(cx.cx.views.len(), 2);
5893 assert!(cx.subscriptions.is_empty());
5894 assert!(cx.observations.is_empty());
5895 }
5896
5897 #[crate::test(self)]
5898 fn test_add_window(cx: &mut MutableAppContext) {
5899 struct View {
5900 mouse_down_count: Arc<AtomicUsize>,
5901 }
5902
5903 impl Entity for View {
5904 type Event = ();
5905 }
5906
5907 impl super::View for View {
5908 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
5909 enum Handler {}
5910 let mouse_down_count = self.mouse_down_count.clone();
5911 MouseEventHandler::<Handler>::new(0, cx, |_, _| Empty::new().boxed())
5912 .on_down(MouseButton::Left, move |_, _| {
5913 mouse_down_count.fetch_add(1, SeqCst);
5914 })
5915 .boxed()
5916 }
5917
5918 fn ui_name() -> &'static str {
5919 "View"
5920 }
5921 }
5922
5923 let mouse_down_count = Arc::new(AtomicUsize::new(0));
5924 let (window_id, _) = cx.add_window(Default::default(), |_| View {
5925 mouse_down_count: mouse_down_count.clone(),
5926 });
5927 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
5928 // Ensure window's root element is in a valid lifecycle state.
5929 presenter.borrow_mut().dispatch_event(
5930 Event::MouseDown(MouseButtonEvent {
5931 position: Default::default(),
5932 button: MouseButton::Left,
5933 modifiers: Default::default(),
5934 click_count: 1,
5935 }),
5936 false,
5937 cx,
5938 );
5939 assert_eq!(mouse_down_count.load(SeqCst), 1);
5940 }
5941
5942 #[crate::test(self)]
5943 fn test_entity_release_hooks(cx: &mut MutableAppContext) {
5944 struct Model {
5945 released: Rc<Cell<bool>>,
5946 }
5947
5948 struct View {
5949 released: Rc<Cell<bool>>,
5950 }
5951
5952 impl Entity for Model {
5953 type Event = ();
5954
5955 fn release(&mut self, _: &mut MutableAppContext) {
5956 self.released.set(true);
5957 }
5958 }
5959
5960 impl Entity for View {
5961 type Event = ();
5962
5963 fn release(&mut self, _: &mut MutableAppContext) {
5964 self.released.set(true);
5965 }
5966 }
5967
5968 impl super::View for View {
5969 fn ui_name() -> &'static str {
5970 "View"
5971 }
5972
5973 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
5974 Empty::new().boxed()
5975 }
5976 }
5977
5978 let model_released = Rc::new(Cell::new(false));
5979 let model_release_observed = Rc::new(Cell::new(false));
5980 let view_released = Rc::new(Cell::new(false));
5981 let view_release_observed = Rc::new(Cell::new(false));
5982
5983 let model = cx.add_model(|_| Model {
5984 released: model_released.clone(),
5985 });
5986 let (window_id, view) = cx.add_window(Default::default(), |_| View {
5987 released: view_released.clone(),
5988 });
5989 assert!(!model_released.get());
5990 assert!(!view_released.get());
5991
5992 cx.observe_release(&model, {
5993 let model_release_observed = model_release_observed.clone();
5994 move |_, _| model_release_observed.set(true)
5995 })
5996 .detach();
5997 cx.observe_release(&view, {
5998 let view_release_observed = view_release_observed.clone();
5999 move |_, _| view_release_observed.set(true)
6000 })
6001 .detach();
6002
6003 cx.update(move |_| {
6004 drop(model);
6005 });
6006 assert!(model_released.get());
6007 assert!(model_release_observed.get());
6008
6009 drop(view);
6010 cx.remove_window(window_id);
6011 assert!(view_released.get());
6012 assert!(view_release_observed.get());
6013 }
6014
6015 #[crate::test(self)]
6016 fn test_view_events(cx: &mut MutableAppContext) {
6017 #[derive(Default)]
6018 struct View {
6019 events: Vec<usize>,
6020 }
6021
6022 impl Entity for View {
6023 type Event = usize;
6024 }
6025
6026 impl super::View for View {
6027 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6028 Empty::new().boxed()
6029 }
6030
6031 fn ui_name() -> &'static str {
6032 "View"
6033 }
6034 }
6035
6036 struct Model;
6037
6038 impl Entity for Model {
6039 type Event = usize;
6040 }
6041
6042 let (_, handle_1) = cx.add_window(Default::default(), |_| View::default());
6043 let handle_2 = cx.add_view(&handle_1, |_| View::default());
6044 let handle_3 = cx.add_model(|_| Model);
6045
6046 handle_1.update(cx, |_, cx| {
6047 cx.subscribe(&handle_2, move |me, emitter, event, cx| {
6048 me.events.push(*event);
6049
6050 cx.subscribe(&emitter, |me, _, event, _| {
6051 me.events.push(*event * 2);
6052 })
6053 .detach();
6054 })
6055 .detach();
6056
6057 cx.subscribe(&handle_3, |me, _, event, _| {
6058 me.events.push(*event);
6059 })
6060 .detach();
6061 });
6062
6063 handle_2.update(cx, |_, c| c.emit(7));
6064 assert_eq!(handle_1.read(cx).events, vec![7]);
6065
6066 handle_2.update(cx, |_, c| c.emit(5));
6067 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10]);
6068
6069 handle_3.update(cx, |_, c| c.emit(9));
6070 assert_eq!(handle_1.read(cx).events, vec![7, 5, 10, 9]);
6071 }
6072
6073 #[crate::test(self)]
6074 fn test_global_events(cx: &mut MutableAppContext) {
6075 #[derive(Clone, Debug, Eq, PartialEq)]
6076 struct GlobalEvent(u64);
6077
6078 let events = Rc::new(RefCell::new(Vec::new()));
6079 let first_subscription;
6080 let second_subscription;
6081
6082 {
6083 let events = events.clone();
6084 first_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
6085 events.borrow_mut().push(("First", e.clone()));
6086 });
6087 }
6088
6089 {
6090 let events = events.clone();
6091 second_subscription = cx.subscribe_global(move |e: &GlobalEvent, _| {
6092 events.borrow_mut().push(("Second", e.clone()));
6093 });
6094 }
6095
6096 cx.update(|cx| {
6097 cx.emit_global(GlobalEvent(1));
6098 cx.emit_global(GlobalEvent(2));
6099 });
6100
6101 drop(first_subscription);
6102
6103 cx.update(|cx| {
6104 cx.emit_global(GlobalEvent(3));
6105 });
6106
6107 drop(second_subscription);
6108
6109 cx.update(|cx| {
6110 cx.emit_global(GlobalEvent(4));
6111 });
6112
6113 assert_eq!(
6114 &*events.borrow(),
6115 &[
6116 ("First", GlobalEvent(1)),
6117 ("Second", GlobalEvent(1)),
6118 ("First", GlobalEvent(2)),
6119 ("Second", GlobalEvent(2)),
6120 ("Second", GlobalEvent(3)),
6121 ]
6122 );
6123 }
6124
6125 #[crate::test(self)]
6126 fn test_global_events_emitted_before_subscription_in_same_update_cycle(
6127 cx: &mut MutableAppContext,
6128 ) {
6129 let events = Rc::new(RefCell::new(Vec::new()));
6130 cx.update(|cx| {
6131 {
6132 let events = events.clone();
6133 drop(cx.subscribe_global(move |_: &(), _| {
6134 events.borrow_mut().push("dropped before emit");
6135 }));
6136 }
6137
6138 {
6139 let events = events.clone();
6140 cx.subscribe_global(move |_: &(), _| {
6141 events.borrow_mut().push("before emit");
6142 })
6143 .detach();
6144 }
6145
6146 cx.emit_global(());
6147
6148 {
6149 let events = events.clone();
6150 cx.subscribe_global(move |_: &(), _| {
6151 events.borrow_mut().push("after emit");
6152 })
6153 .detach();
6154 }
6155 });
6156
6157 assert_eq!(*events.borrow(), ["before emit"]);
6158 }
6159
6160 #[crate::test(self)]
6161 fn test_global_nested_events(cx: &mut MutableAppContext) {
6162 #[derive(Clone, Debug, Eq, PartialEq)]
6163 struct GlobalEvent(u64);
6164
6165 let events = Rc::new(RefCell::new(Vec::new()));
6166
6167 {
6168 let events = events.clone();
6169 cx.subscribe_global(move |e: &GlobalEvent, cx| {
6170 events.borrow_mut().push(("Outer", e.clone()));
6171
6172 if e.0 == 1 {
6173 let events = events.clone();
6174 cx.subscribe_global(move |e: &GlobalEvent, _| {
6175 events.borrow_mut().push(("Inner", e.clone()));
6176 })
6177 .detach();
6178 }
6179 })
6180 .detach();
6181 }
6182
6183 cx.update(|cx| {
6184 cx.emit_global(GlobalEvent(1));
6185 cx.emit_global(GlobalEvent(2));
6186 cx.emit_global(GlobalEvent(3));
6187 });
6188 cx.update(|cx| {
6189 cx.emit_global(GlobalEvent(4));
6190 });
6191
6192 assert_eq!(
6193 &*events.borrow(),
6194 &[
6195 ("Outer", GlobalEvent(1)),
6196 ("Outer", GlobalEvent(2)),
6197 ("Outer", GlobalEvent(3)),
6198 ("Outer", GlobalEvent(4)),
6199 ("Inner", GlobalEvent(4)),
6200 ]
6201 );
6202 }
6203
6204 #[crate::test(self)]
6205 fn test_global(cx: &mut MutableAppContext) {
6206 type Global = usize;
6207
6208 let observation_count = Rc::new(RefCell::new(0));
6209 let subscription = cx.observe_global::<Global, _>({
6210 let observation_count = observation_count.clone();
6211 move |_| {
6212 *observation_count.borrow_mut() += 1;
6213 }
6214 });
6215
6216 assert!(!cx.has_global::<Global>());
6217 assert_eq!(cx.default_global::<Global>(), &0);
6218 assert_eq!(*observation_count.borrow(), 1);
6219 assert!(cx.has_global::<Global>());
6220 assert_eq!(
6221 cx.update_global::<Global, _, _>(|global, _| {
6222 *global = 1;
6223 "Update Result"
6224 }),
6225 "Update Result"
6226 );
6227 assert_eq!(*observation_count.borrow(), 2);
6228 assert_eq!(cx.global::<Global>(), &1);
6229
6230 drop(subscription);
6231 cx.update_global::<Global, _, _>(|global, _| {
6232 *global = 2;
6233 });
6234 assert_eq!(*observation_count.borrow(), 2);
6235
6236 type OtherGlobal = f32;
6237
6238 let observation_count = Rc::new(RefCell::new(0));
6239 cx.observe_global::<OtherGlobal, _>({
6240 let observation_count = observation_count.clone();
6241 move |_| {
6242 *observation_count.borrow_mut() += 1;
6243 }
6244 })
6245 .detach();
6246
6247 assert_eq!(
6248 cx.update_default_global::<OtherGlobal, _, _>(|global, _| {
6249 assert_eq!(global, &0.0);
6250 *global = 2.0;
6251 "Default update result"
6252 }),
6253 "Default update result"
6254 );
6255 assert_eq!(cx.global::<OtherGlobal>(), &2.0);
6256 assert_eq!(*observation_count.borrow(), 1);
6257 }
6258
6259 #[crate::test(self)]
6260 fn test_dropping_subscribers(cx: &mut MutableAppContext) {
6261 struct View;
6262
6263 impl Entity for View {
6264 type Event = ();
6265 }
6266
6267 impl super::View for View {
6268 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6269 Empty::new().boxed()
6270 }
6271
6272 fn ui_name() -> &'static str {
6273 "View"
6274 }
6275 }
6276
6277 struct Model;
6278
6279 impl Entity for Model {
6280 type Event = ();
6281 }
6282
6283 let (_, root_view) = cx.add_window(Default::default(), |_| View);
6284 let observing_view = cx.add_view(&root_view, |_| View);
6285 let emitting_view = cx.add_view(&root_view, |_| View);
6286 let observing_model = cx.add_model(|_| Model);
6287 let observed_model = cx.add_model(|_| Model);
6288
6289 observing_view.update(cx, |_, cx| {
6290 cx.subscribe(&emitting_view, |_, _, _, _| {}).detach();
6291 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
6292 });
6293 observing_model.update(cx, |_, cx| {
6294 cx.subscribe(&observed_model, |_, _, _, _| {}).detach();
6295 });
6296
6297 cx.update(|_| {
6298 drop(observing_view);
6299 drop(observing_model);
6300 });
6301
6302 emitting_view.update(cx, |_, cx| cx.emit(()));
6303 observed_model.update(cx, |_, cx| cx.emit(()));
6304 }
6305
6306 #[crate::test(self)]
6307 fn test_view_emit_before_subscribe_in_same_update_cycle(cx: &mut MutableAppContext) {
6308 #[derive(Default)]
6309 struct TestView;
6310
6311 impl Entity for TestView {
6312 type Event = ();
6313 }
6314
6315 impl View for TestView {
6316 fn ui_name() -> &'static str {
6317 "TestView"
6318 }
6319
6320 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6321 Empty::new().boxed()
6322 }
6323 }
6324
6325 let events = Rc::new(RefCell::new(Vec::new()));
6326 cx.add_window(Default::default(), |cx| {
6327 drop(cx.subscribe(&cx.handle(), {
6328 let events = events.clone();
6329 move |_, _, _, _| events.borrow_mut().push("dropped before flush")
6330 }));
6331 cx.subscribe(&cx.handle(), {
6332 let events = events.clone();
6333 move |_, _, _, _| events.borrow_mut().push("before emit")
6334 })
6335 .detach();
6336 cx.emit(());
6337 cx.subscribe(&cx.handle(), {
6338 let events = events.clone();
6339 move |_, _, _, _| events.borrow_mut().push("after emit")
6340 })
6341 .detach();
6342 TestView
6343 });
6344 assert_eq!(*events.borrow(), ["before emit"]);
6345 }
6346
6347 #[crate::test(self)]
6348 fn test_observe_and_notify_from_view(cx: &mut MutableAppContext) {
6349 #[derive(Default)]
6350 struct View {
6351 events: Vec<usize>,
6352 }
6353
6354 impl Entity for View {
6355 type Event = usize;
6356 }
6357
6358 impl super::View for View {
6359 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6360 Empty::new().boxed()
6361 }
6362
6363 fn ui_name() -> &'static str {
6364 "View"
6365 }
6366 }
6367
6368 #[derive(Default)]
6369 struct Model {
6370 count: usize,
6371 }
6372
6373 impl Entity for Model {
6374 type Event = ();
6375 }
6376
6377 let (_, view) = cx.add_window(Default::default(), |_| View::default());
6378 let model = cx.add_model(|_| Model::default());
6379
6380 view.update(cx, |_, c| {
6381 c.observe(&model, |me, observed, c| {
6382 me.events.push(observed.read(c).count)
6383 })
6384 .detach();
6385 });
6386
6387 model.update(cx, |model, c| {
6388 model.count = 11;
6389 c.notify();
6390 });
6391 assert_eq!(view.read(cx).events, vec![11]);
6392 }
6393
6394 #[crate::test(self)]
6395 fn test_view_notify_before_observe_in_same_update_cycle(cx: &mut MutableAppContext) {
6396 #[derive(Default)]
6397 struct TestView;
6398
6399 impl Entity for TestView {
6400 type Event = ();
6401 }
6402
6403 impl View for TestView {
6404 fn ui_name() -> &'static str {
6405 "TestView"
6406 }
6407
6408 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6409 Empty::new().boxed()
6410 }
6411 }
6412
6413 let events = Rc::new(RefCell::new(Vec::new()));
6414 cx.add_window(Default::default(), |cx| {
6415 drop(cx.observe(&cx.handle(), {
6416 let events = events.clone();
6417 move |_, _, _| events.borrow_mut().push("dropped before flush")
6418 }));
6419 cx.observe(&cx.handle(), {
6420 let events = events.clone();
6421 move |_, _, _| events.borrow_mut().push("before notify")
6422 })
6423 .detach();
6424 cx.notify();
6425 cx.observe(&cx.handle(), {
6426 let events = events.clone();
6427 move |_, _, _| events.borrow_mut().push("after notify")
6428 })
6429 .detach();
6430 TestView
6431 });
6432 assert_eq!(*events.borrow(), ["before notify"]);
6433 }
6434
6435 #[crate::test(self)]
6436 fn test_dropping_observers(cx: &mut MutableAppContext) {
6437 struct View;
6438
6439 impl Entity for View {
6440 type Event = ();
6441 }
6442
6443 impl super::View for View {
6444 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6445 Empty::new().boxed()
6446 }
6447
6448 fn ui_name() -> &'static str {
6449 "View"
6450 }
6451 }
6452
6453 struct Model;
6454
6455 impl Entity for Model {
6456 type Event = ();
6457 }
6458
6459 let (_, root_view) = cx.add_window(Default::default(), |_| View);
6460 let observing_view = cx.add_view(root_view, |_| View);
6461 let observing_model = cx.add_model(|_| Model);
6462 let observed_model = cx.add_model(|_| Model);
6463
6464 observing_view.update(cx, |_, cx| {
6465 cx.observe(&observed_model, |_, _, _| {}).detach();
6466 });
6467 observing_model.update(cx, |_, cx| {
6468 cx.observe(&observed_model, |_, _, _| {}).detach();
6469 });
6470
6471 cx.update(|_| {
6472 drop(observing_view);
6473 drop(observing_model);
6474 });
6475
6476 observed_model.update(cx, |_, cx| cx.notify());
6477 }
6478
6479 #[crate::test(self)]
6480 fn test_dropping_subscriptions_during_callback(cx: &mut MutableAppContext) {
6481 struct Model;
6482
6483 impl Entity for Model {
6484 type Event = u64;
6485 }
6486
6487 // Events
6488 let observing_model = cx.add_model(|_| Model);
6489 let observed_model = cx.add_model(|_| Model);
6490
6491 let events = Rc::new(RefCell::new(Vec::new()));
6492
6493 observing_model.update(cx, |_, cx| {
6494 let events = events.clone();
6495 let subscription = Rc::new(RefCell::new(None));
6496 *subscription.borrow_mut() = Some(cx.subscribe(&observed_model, {
6497 let subscription = subscription.clone();
6498 move |_, _, e, _| {
6499 subscription.borrow_mut().take();
6500 events.borrow_mut().push(*e);
6501 }
6502 }));
6503 });
6504
6505 observed_model.update(cx, |_, cx| {
6506 cx.emit(1);
6507 cx.emit(2);
6508 });
6509
6510 assert_eq!(*events.borrow(), [1]);
6511
6512 // Global Events
6513 #[derive(Clone, Debug, Eq, PartialEq)]
6514 struct GlobalEvent(u64);
6515
6516 let events = Rc::new(RefCell::new(Vec::new()));
6517
6518 {
6519 let events = events.clone();
6520 let subscription = Rc::new(RefCell::new(None));
6521 *subscription.borrow_mut() = Some(cx.subscribe_global({
6522 let subscription = subscription.clone();
6523 move |e: &GlobalEvent, _| {
6524 subscription.borrow_mut().take();
6525 events.borrow_mut().push(e.clone());
6526 }
6527 }));
6528 }
6529
6530 cx.update(|cx| {
6531 cx.emit_global(GlobalEvent(1));
6532 cx.emit_global(GlobalEvent(2));
6533 });
6534
6535 assert_eq!(*events.borrow(), [GlobalEvent(1)]);
6536
6537 // Model Observation
6538 let observing_model = cx.add_model(|_| Model);
6539 let observed_model = cx.add_model(|_| Model);
6540
6541 let observation_count = Rc::new(RefCell::new(0));
6542
6543 observing_model.update(cx, |_, cx| {
6544 let observation_count = observation_count.clone();
6545 let subscription = Rc::new(RefCell::new(None));
6546 *subscription.borrow_mut() = Some(cx.observe(&observed_model, {
6547 let subscription = subscription.clone();
6548 move |_, _, _| {
6549 subscription.borrow_mut().take();
6550 *observation_count.borrow_mut() += 1;
6551 }
6552 }));
6553 });
6554
6555 observed_model.update(cx, |_, cx| {
6556 cx.notify();
6557 });
6558
6559 observed_model.update(cx, |_, cx| {
6560 cx.notify();
6561 });
6562
6563 assert_eq!(*observation_count.borrow(), 1);
6564
6565 // View Observation
6566 struct View;
6567
6568 impl Entity for View {
6569 type Event = ();
6570 }
6571
6572 impl super::View for View {
6573 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6574 Empty::new().boxed()
6575 }
6576
6577 fn ui_name() -> &'static str {
6578 "View"
6579 }
6580 }
6581
6582 let (_, root_view) = cx.add_window(Default::default(), |_| View);
6583 let observing_view = cx.add_view(&root_view, |_| View);
6584 let observed_view = cx.add_view(&root_view, |_| View);
6585
6586 let observation_count = Rc::new(RefCell::new(0));
6587 observing_view.update(cx, |_, cx| {
6588 let observation_count = observation_count.clone();
6589 let subscription = Rc::new(RefCell::new(None));
6590 *subscription.borrow_mut() = Some(cx.observe(&observed_view, {
6591 let subscription = subscription.clone();
6592 move |_, _, _| {
6593 subscription.borrow_mut().take();
6594 *observation_count.borrow_mut() += 1;
6595 }
6596 }));
6597 });
6598
6599 observed_view.update(cx, |_, cx| {
6600 cx.notify();
6601 });
6602
6603 observed_view.update(cx, |_, cx| {
6604 cx.notify();
6605 });
6606
6607 assert_eq!(*observation_count.borrow(), 1);
6608
6609 // Global Observation
6610 let observation_count = Rc::new(RefCell::new(0));
6611 let subscription = Rc::new(RefCell::new(None));
6612 *subscription.borrow_mut() = Some(cx.observe_global::<(), _>({
6613 let observation_count = observation_count.clone();
6614 let subscription = subscription.clone();
6615 move |_| {
6616 subscription.borrow_mut().take();
6617 *observation_count.borrow_mut() += 1;
6618 }
6619 }));
6620
6621 cx.default_global::<()>();
6622 cx.set_global(());
6623 assert_eq!(*observation_count.borrow(), 1);
6624 }
6625
6626 #[crate::test(self)]
6627 fn test_focus(cx: &mut MutableAppContext) {
6628 struct View {
6629 name: String,
6630 events: Arc<Mutex<Vec<String>>>,
6631 }
6632
6633 impl Entity for View {
6634 type Event = ();
6635 }
6636
6637 impl super::View for View {
6638 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6639 Empty::new().boxed()
6640 }
6641
6642 fn ui_name() -> &'static str {
6643 "View"
6644 }
6645
6646 fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
6647 if cx.handle().id() == focused.id() {
6648 self.events.lock().push(format!("{} focused", &self.name));
6649 }
6650 }
6651
6652 fn focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
6653 if cx.handle().id() == blurred.id() {
6654 self.events.lock().push(format!("{} blurred", &self.name));
6655 }
6656 }
6657 }
6658
6659 let view_events: Arc<Mutex<Vec<String>>> = Default::default();
6660 let (_, view_1) = cx.add_window(Default::default(), |_| View {
6661 events: view_events.clone(),
6662 name: "view 1".to_string(),
6663 });
6664 let view_2 = cx.add_view(&view_1, |_| View {
6665 events: view_events.clone(),
6666 name: "view 2".to_string(),
6667 });
6668
6669 let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
6670 view_1.update(cx, |_, cx| {
6671 cx.observe_focus(&view_2, {
6672 let observed_events = observed_events.clone();
6673 move |this, view, focused, cx| {
6674 let label = if focused { "focus" } else { "blur" };
6675 observed_events.lock().push(format!(
6676 "{} observed {}'s {}",
6677 this.name,
6678 view.read(cx).name,
6679 label
6680 ))
6681 }
6682 })
6683 .detach();
6684 });
6685 view_2.update(cx, |_, cx| {
6686 cx.observe_focus(&view_1, {
6687 let observed_events = observed_events.clone();
6688 move |this, view, focused, cx| {
6689 let label = if focused { "focus" } else { "blur" };
6690 observed_events.lock().push(format!(
6691 "{} observed {}'s {}",
6692 this.name,
6693 view.read(cx).name,
6694 label
6695 ))
6696 }
6697 })
6698 .detach();
6699 });
6700 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
6701 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
6702
6703 view_1.update(cx, |_, cx| {
6704 // Ensure focus events are sent for all intermediate focuses
6705 cx.focus(&view_2);
6706 cx.focus(&view_1);
6707 cx.focus(&view_2);
6708 });
6709 assert_eq!(
6710 mem::take(&mut *view_events.lock()),
6711 [
6712 "view 1 blurred",
6713 "view 2 focused",
6714 "view 2 blurred",
6715 "view 1 focused",
6716 "view 1 blurred",
6717 "view 2 focused"
6718 ],
6719 );
6720 assert_eq!(
6721 mem::take(&mut *observed_events.lock()),
6722 [
6723 "view 2 observed view 1's blur",
6724 "view 1 observed view 2's focus",
6725 "view 1 observed view 2's blur",
6726 "view 2 observed view 1's focus",
6727 "view 2 observed view 1's blur",
6728 "view 1 observed view 2's focus"
6729 ]
6730 );
6731
6732 view_1.update(cx, |_, cx| cx.focus(&view_1));
6733 assert_eq!(
6734 mem::take(&mut *view_events.lock()),
6735 ["view 2 blurred", "view 1 focused"],
6736 );
6737 assert_eq!(
6738 mem::take(&mut *observed_events.lock()),
6739 [
6740 "view 1 observed view 2's blur",
6741 "view 2 observed view 1's focus"
6742 ]
6743 );
6744
6745 view_1.update(cx, |_, cx| cx.focus(&view_2));
6746 assert_eq!(
6747 mem::take(&mut *view_events.lock()),
6748 ["view 1 blurred", "view 2 focused"],
6749 );
6750 assert_eq!(
6751 mem::take(&mut *observed_events.lock()),
6752 [
6753 "view 2 observed view 1's blur",
6754 "view 1 observed view 2's focus"
6755 ]
6756 );
6757
6758 view_1.update(cx, |_, _| drop(view_2));
6759 assert_eq!(mem::take(&mut *view_events.lock()), ["view 1 focused"]);
6760 assert_eq!(mem::take(&mut *observed_events.lock()), Vec::<&str>::new());
6761 }
6762
6763 #[crate::test(self)]
6764 fn test_deserialize_actions(cx: &mut MutableAppContext) {
6765 #[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
6766 pub struct ComplexAction {
6767 arg: String,
6768 count: usize,
6769 }
6770
6771 actions!(test::something, [SimpleAction]);
6772 impl_actions!(test::something, [ComplexAction]);
6773
6774 cx.add_global_action(move |_: &SimpleAction, _: &mut MutableAppContext| {});
6775 cx.add_global_action(move |_: &ComplexAction, _: &mut MutableAppContext| {});
6776
6777 let action1 = cx
6778 .deserialize_action(
6779 "test::something::ComplexAction",
6780 Some(r#"{"arg": "a", "count": 5}"#),
6781 )
6782 .unwrap();
6783 let action2 = cx
6784 .deserialize_action("test::something::SimpleAction", None)
6785 .unwrap();
6786 assert_eq!(
6787 action1.as_any().downcast_ref::<ComplexAction>().unwrap(),
6788 &ComplexAction {
6789 arg: "a".to_string(),
6790 count: 5,
6791 }
6792 );
6793 assert_eq!(
6794 action2.as_any().downcast_ref::<SimpleAction>().unwrap(),
6795 &SimpleAction
6796 );
6797 }
6798
6799 #[crate::test(self)]
6800 fn test_dispatch_action(cx: &mut MutableAppContext) {
6801 struct ViewA {
6802 id: usize,
6803 }
6804
6805 impl Entity for ViewA {
6806 type Event = ();
6807 }
6808
6809 impl View for ViewA {
6810 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6811 Empty::new().boxed()
6812 }
6813
6814 fn ui_name() -> &'static str {
6815 "View"
6816 }
6817 }
6818
6819 struct ViewB {
6820 id: usize,
6821 }
6822
6823 impl Entity for ViewB {
6824 type Event = ();
6825 }
6826
6827 impl View for ViewB {
6828 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6829 Empty::new().boxed()
6830 }
6831
6832 fn ui_name() -> &'static str {
6833 "View"
6834 }
6835 }
6836
6837 #[derive(Clone, Default, Deserialize, PartialEq)]
6838 pub struct Action(pub String);
6839
6840 impl_actions!(test, [Action]);
6841
6842 let actions = Rc::new(RefCell::new(Vec::new()));
6843
6844 cx.add_global_action({
6845 let actions = actions.clone();
6846 move |_: &Action, _: &mut MutableAppContext| {
6847 actions.borrow_mut().push("global".to_string());
6848 }
6849 });
6850
6851 cx.add_action({
6852 let actions = actions.clone();
6853 move |view: &mut ViewA, action: &Action, cx| {
6854 assert_eq!(action.0, "bar");
6855 cx.propagate_action();
6856 actions.borrow_mut().push(format!("{} a", view.id));
6857 }
6858 });
6859
6860 cx.add_action({
6861 let actions = actions.clone();
6862 move |view: &mut ViewA, _: &Action, cx| {
6863 if view.id != 1 {
6864 cx.add_view(|cx| {
6865 cx.propagate_action(); // Still works on a nested ViewContext
6866 ViewB { id: 5 }
6867 });
6868 }
6869 actions.borrow_mut().push(format!("{} b", view.id));
6870 }
6871 });
6872
6873 cx.add_action({
6874 let actions = actions.clone();
6875 move |view: &mut ViewB, _: &Action, cx| {
6876 cx.propagate_action();
6877 actions.borrow_mut().push(format!("{} c", view.id));
6878 }
6879 });
6880
6881 cx.add_action({
6882 let actions = actions.clone();
6883 move |view: &mut ViewB, _: &Action, cx| {
6884 cx.propagate_action();
6885 actions.borrow_mut().push(format!("{} d", view.id));
6886 }
6887 });
6888
6889 cx.capture_action({
6890 let actions = actions.clone();
6891 move |view: &mut ViewA, _: &Action, cx| {
6892 cx.propagate_action();
6893 actions.borrow_mut().push(format!("{} capture", view.id));
6894 }
6895 });
6896
6897 let observed_actions = Rc::new(RefCell::new(Vec::new()));
6898 cx.observe_actions({
6899 let observed_actions = observed_actions.clone();
6900 move |action_id, _| observed_actions.borrow_mut().push(action_id)
6901 })
6902 .detach();
6903
6904 let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 });
6905 let view_2 = cx.add_view(&view_1, |_| ViewB { id: 2 });
6906 let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 });
6907 let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 });
6908
6909 cx.handle_dispatch_action_from_effect(
6910 window_id,
6911 Some(view_4.id()),
6912 &Action("bar".to_string()),
6913 );
6914
6915 assert_eq!(
6916 *actions.borrow(),
6917 vec![
6918 "1 capture",
6919 "3 capture",
6920 "4 d",
6921 "4 c",
6922 "3 b",
6923 "3 a",
6924 "2 d",
6925 "2 c",
6926 "1 b"
6927 ]
6928 );
6929 assert_eq!(*observed_actions.borrow(), [Action::default().id()]);
6930
6931 // Remove view_1, which doesn't propagate the action
6932
6933 let (window_id, view_2) = cx.add_window(Default::default(), |_| ViewB { id: 2 });
6934 let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 });
6935 let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 });
6936
6937 actions.borrow_mut().clear();
6938 cx.handle_dispatch_action_from_effect(
6939 window_id,
6940 Some(view_4.id()),
6941 &Action("bar".to_string()),
6942 );
6943
6944 assert_eq!(
6945 *actions.borrow(),
6946 vec![
6947 "3 capture",
6948 "4 d",
6949 "4 c",
6950 "3 b",
6951 "3 a",
6952 "2 d",
6953 "2 c",
6954 "global"
6955 ]
6956 );
6957 assert_eq!(
6958 *observed_actions.borrow(),
6959 [Action::default().id(), Action::default().id()]
6960 );
6961 }
6962
6963 #[crate::test(self)]
6964 fn test_dispatch_keystroke(cx: &mut MutableAppContext) {
6965 #[derive(Clone, Deserialize, PartialEq)]
6966 pub struct Action(String);
6967
6968 impl_actions!(test, [Action]);
6969
6970 struct View {
6971 id: usize,
6972 keymap_context: keymap::Context,
6973 }
6974
6975 impl Entity for View {
6976 type Event = ();
6977 }
6978
6979 impl super::View for View {
6980 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
6981 Empty::new().boxed()
6982 }
6983
6984 fn ui_name() -> &'static str {
6985 "View"
6986 }
6987
6988 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
6989 self.keymap_context.clone()
6990 }
6991 }
6992
6993 impl View {
6994 fn new(id: usize) -> Self {
6995 View {
6996 id,
6997 keymap_context: keymap::Context::default(),
6998 }
6999 }
7000 }
7001
7002 let mut view_1 = View::new(1);
7003 let mut view_2 = View::new(2);
7004 let mut view_3 = View::new(3);
7005 view_1.keymap_context.set.insert("a".into());
7006 view_2.keymap_context.set.insert("a".into());
7007 view_2.keymap_context.set.insert("b".into());
7008 view_3.keymap_context.set.insert("a".into());
7009 view_3.keymap_context.set.insert("b".into());
7010 view_3.keymap_context.set.insert("c".into());
7011
7012 let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1);
7013 let view_2 = cx.add_view(&view_1, |_| view_2);
7014 let _view_3 = cx.add_view(&view_2, |cx| {
7015 cx.focus_self();
7016 view_3
7017 });
7018
7019 // This keymap's only binding dispatches an action on view 2 because that view will have
7020 // "a" and "b" in its context, but not "c".
7021 cx.add_bindings(vec![keymap::Binding::new(
7022 "a",
7023 Action("a".to_string()),
7024 Some("a && b && !c"),
7025 )]);
7026
7027 cx.add_bindings(vec![keymap::Binding::new(
7028 "b",
7029 Action("b".to_string()),
7030 None,
7031 )]);
7032
7033 let actions = Rc::new(RefCell::new(Vec::new()));
7034 cx.add_action({
7035 let actions = actions.clone();
7036 move |view: &mut View, action: &Action, cx| {
7037 if action.0 == "a" {
7038 actions.borrow_mut().push(format!("{} a", view.id));
7039 } else {
7040 actions
7041 .borrow_mut()
7042 .push(format!("{} {}", view.id, action.0));
7043 cx.propagate_action();
7044 }
7045 }
7046 });
7047
7048 cx.add_global_action({
7049 let actions = actions.clone();
7050 move |action: &Action, _| {
7051 actions.borrow_mut().push(format!("global {}", action.0));
7052 }
7053 });
7054
7055 cx.dispatch_keystroke(window_id, &Keystroke::parse("a").unwrap());
7056
7057 assert_eq!(&*actions.borrow(), &["2 a"]);
7058
7059 actions.borrow_mut().clear();
7060
7061 cx.dispatch_keystroke(window_id, &Keystroke::parse("b").unwrap());
7062
7063 assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
7064 }
7065
7066 #[crate::test(self)]
7067 async fn test_model_condition(cx: &mut TestAppContext) {
7068 struct Counter(usize);
7069
7070 impl super::Entity for Counter {
7071 type Event = ();
7072 }
7073
7074 impl Counter {
7075 fn inc(&mut self, cx: &mut ModelContext<Self>) {
7076 self.0 += 1;
7077 cx.notify();
7078 }
7079 }
7080
7081 let model = cx.add_model(|_| Counter(0));
7082
7083 let condition1 = model.condition(cx, |model, _| model.0 == 2);
7084 let condition2 = model.condition(cx, |model, _| model.0 == 3);
7085 smol::pin!(condition1, condition2);
7086
7087 model.update(cx, |model, cx| model.inc(cx));
7088 assert_eq!(poll_once(&mut condition1).await, None);
7089 assert_eq!(poll_once(&mut condition2).await, None);
7090
7091 model.update(cx, |model, cx| model.inc(cx));
7092 assert_eq!(poll_once(&mut condition1).await, Some(()));
7093 assert_eq!(poll_once(&mut condition2).await, None);
7094
7095 model.update(cx, |model, cx| model.inc(cx));
7096 assert_eq!(poll_once(&mut condition2).await, Some(()));
7097
7098 model.update(cx, |_, cx| cx.notify());
7099 }
7100
7101 #[crate::test(self)]
7102 #[should_panic]
7103 async fn test_model_condition_timeout(cx: &mut TestAppContext) {
7104 struct Model;
7105
7106 impl super::Entity for Model {
7107 type Event = ();
7108 }
7109
7110 let model = cx.add_model(|_| Model);
7111 model.condition(cx, |_, _| false).await;
7112 }
7113
7114 #[crate::test(self)]
7115 #[should_panic(expected = "model dropped with pending condition")]
7116 async fn test_model_condition_panic_on_drop(cx: &mut TestAppContext) {
7117 struct Model;
7118
7119 impl super::Entity for Model {
7120 type Event = ();
7121 }
7122
7123 let model = cx.add_model(|_| Model);
7124 let condition = model.condition(cx, |_, _| false);
7125 cx.update(|_| drop(model));
7126 condition.await;
7127 }
7128
7129 #[crate::test(self)]
7130 async fn test_view_condition(cx: &mut TestAppContext) {
7131 struct Counter(usize);
7132
7133 impl super::Entity for Counter {
7134 type Event = ();
7135 }
7136
7137 impl super::View for Counter {
7138 fn ui_name() -> &'static str {
7139 "test view"
7140 }
7141
7142 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7143 Empty::new().boxed()
7144 }
7145 }
7146
7147 impl Counter {
7148 fn inc(&mut self, cx: &mut ViewContext<Self>) {
7149 self.0 += 1;
7150 cx.notify();
7151 }
7152 }
7153
7154 let (_, view) = cx.add_window(|_| Counter(0));
7155
7156 let condition1 = view.condition(cx, |view, _| view.0 == 2);
7157 let condition2 = view.condition(cx, |view, _| view.0 == 3);
7158 smol::pin!(condition1, condition2);
7159
7160 view.update(cx, |view, cx| view.inc(cx));
7161 assert_eq!(poll_once(&mut condition1).await, None);
7162 assert_eq!(poll_once(&mut condition2).await, None);
7163
7164 view.update(cx, |view, cx| view.inc(cx));
7165 assert_eq!(poll_once(&mut condition1).await, Some(()));
7166 assert_eq!(poll_once(&mut condition2).await, None);
7167
7168 view.update(cx, |view, cx| view.inc(cx));
7169 assert_eq!(poll_once(&mut condition2).await, Some(()));
7170 view.update(cx, |_, cx| cx.notify());
7171 }
7172
7173 #[crate::test(self)]
7174 #[should_panic]
7175 async fn test_view_condition_timeout(cx: &mut TestAppContext) {
7176 struct View;
7177
7178 impl super::Entity for View {
7179 type Event = ();
7180 }
7181
7182 impl super::View for View {
7183 fn ui_name() -> &'static str {
7184 "test view"
7185 }
7186
7187 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7188 Empty::new().boxed()
7189 }
7190 }
7191
7192 let (_, view) = cx.add_window(|_| View);
7193 view.condition(cx, |_, _| false).await;
7194 }
7195
7196 #[crate::test(self)]
7197 #[should_panic(expected = "view dropped with pending condition")]
7198 async fn test_view_condition_panic_on_drop(cx: &mut TestAppContext) {
7199 struct View;
7200
7201 impl super::Entity for View {
7202 type Event = ();
7203 }
7204
7205 impl super::View for View {
7206 fn ui_name() -> &'static str {
7207 "test view"
7208 }
7209
7210 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7211 Empty::new().boxed()
7212 }
7213 }
7214
7215 let (_, root_view) = cx.add_window(|_| View);
7216 let view = cx.add_view(&root_view, |_| View);
7217
7218 let condition = view.condition(cx, |_, _| false);
7219 cx.update(|_| drop(view));
7220 condition.await;
7221 }
7222
7223 #[crate::test(self)]
7224 fn test_refresh_windows(cx: &mut MutableAppContext) {
7225 struct View(usize);
7226
7227 impl super::Entity for View {
7228 type Event = ();
7229 }
7230
7231 impl super::View for View {
7232 fn ui_name() -> &'static str {
7233 "test view"
7234 }
7235
7236 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7237 Empty::new().named(format!("render count: {}", post_inc(&mut self.0)))
7238 }
7239 }
7240
7241 let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0));
7242 let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
7243
7244 assert_eq!(
7245 presenter.borrow().rendered_views[&root_view.id()].name(),
7246 Some("render count: 0")
7247 );
7248
7249 let view = cx.add_view(&root_view, |cx| {
7250 cx.refresh_windows();
7251 View(0)
7252 });
7253
7254 assert_eq!(
7255 presenter.borrow().rendered_views[&root_view.id()].name(),
7256 Some("render count: 1")
7257 );
7258 assert_eq!(
7259 presenter.borrow().rendered_views[&view.id()].name(),
7260 Some("render count: 0")
7261 );
7262
7263 cx.update(|cx| cx.refresh_windows());
7264 assert_eq!(
7265 presenter.borrow().rendered_views[&root_view.id()].name(),
7266 Some("render count: 2")
7267 );
7268 assert_eq!(
7269 presenter.borrow().rendered_views[&view.id()].name(),
7270 Some("render count: 1")
7271 );
7272
7273 cx.update(|cx| {
7274 cx.refresh_windows();
7275 drop(view);
7276 });
7277 assert_eq!(
7278 presenter.borrow().rendered_views[&root_view.id()].name(),
7279 Some("render count: 3")
7280 );
7281 assert_eq!(presenter.borrow().rendered_views.len(), 1);
7282 }
7283
7284 #[crate::test(self)]
7285 async fn test_window_activation(cx: &mut TestAppContext) {
7286 struct View(&'static str);
7287
7288 impl super::Entity for View {
7289 type Event = ();
7290 }
7291
7292 impl super::View for View {
7293 fn ui_name() -> &'static str {
7294 "test view"
7295 }
7296
7297 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7298 Empty::new().boxed()
7299 }
7300 }
7301
7302 let events = Rc::new(RefCell::new(Vec::new()));
7303 let (window_1, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7304 cx.observe_window_activation({
7305 let events = events.clone();
7306 move |this, active, _| events.borrow_mut().push((this.0, active))
7307 })
7308 .detach();
7309 View("window 1")
7310 });
7311 assert_eq!(mem::take(&mut *events.borrow_mut()), [("window 1", true)]);
7312
7313 let (window_2, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7314 cx.observe_window_activation({
7315 let events = events.clone();
7316 move |this, active, _| events.borrow_mut().push((this.0, active))
7317 })
7318 .detach();
7319 View("window 2")
7320 });
7321 assert_eq!(
7322 mem::take(&mut *events.borrow_mut()),
7323 [("window 1", false), ("window 2", true)]
7324 );
7325
7326 let (window_3, _) = cx.add_window(|cx: &mut ViewContext<View>| {
7327 cx.observe_window_activation({
7328 let events = events.clone();
7329 move |this, active, _| events.borrow_mut().push((this.0, active))
7330 })
7331 .detach();
7332 View("window 3")
7333 });
7334 assert_eq!(
7335 mem::take(&mut *events.borrow_mut()),
7336 [("window 2", false), ("window 3", true)]
7337 );
7338
7339 cx.simulate_window_activation(Some(window_2));
7340 assert_eq!(
7341 mem::take(&mut *events.borrow_mut()),
7342 [("window 3", false), ("window 2", true)]
7343 );
7344
7345 cx.simulate_window_activation(Some(window_1));
7346 assert_eq!(
7347 mem::take(&mut *events.borrow_mut()),
7348 [("window 2", false), ("window 1", true)]
7349 );
7350
7351 cx.simulate_window_activation(Some(window_3));
7352 assert_eq!(
7353 mem::take(&mut *events.borrow_mut()),
7354 [("window 1", false), ("window 3", true)]
7355 );
7356
7357 cx.simulate_window_activation(Some(window_3));
7358 assert_eq!(mem::take(&mut *events.borrow_mut()), []);
7359 }
7360
7361 #[crate::test(self)]
7362 fn test_child_view(cx: &mut MutableAppContext) {
7363 struct Child {
7364 rendered: Rc<Cell<bool>>,
7365 dropped: Rc<Cell<bool>>,
7366 }
7367
7368 impl super::Entity for Child {
7369 type Event = ();
7370 }
7371
7372 impl super::View for Child {
7373 fn ui_name() -> &'static str {
7374 "child view"
7375 }
7376
7377 fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
7378 self.rendered.set(true);
7379 Empty::new().boxed()
7380 }
7381 }
7382
7383 impl Drop for Child {
7384 fn drop(&mut self) {
7385 self.dropped.set(true);
7386 }
7387 }
7388
7389 struct Parent {
7390 child: Option<ViewHandle<Child>>,
7391 }
7392
7393 impl super::Entity for Parent {
7394 type Event = ();
7395 }
7396
7397 impl super::View for Parent {
7398 fn ui_name() -> &'static str {
7399 "parent view"
7400 }
7401
7402 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
7403 if let Some(child) = self.child.as_ref() {
7404 ChildView::new(child, cx).boxed()
7405 } else {
7406 Empty::new().boxed()
7407 }
7408 }
7409 }
7410
7411 let child_rendered = Rc::new(Cell::new(false));
7412 let child_dropped = Rc::new(Cell::new(false));
7413 let (_, root_view) = cx.add_window(Default::default(), |cx| Parent {
7414 child: Some(cx.add_view(|_| Child {
7415 rendered: child_rendered.clone(),
7416 dropped: child_dropped.clone(),
7417 })),
7418 });
7419 assert!(child_rendered.take());
7420 assert!(!child_dropped.take());
7421
7422 root_view.update(cx, |view, cx| {
7423 view.child.take();
7424 cx.notify();
7425 });
7426 assert!(!child_rendered.take());
7427 assert!(child_dropped.take());
7428 }
7429}