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