This commit is contained in:
Nathan Sobo 2023-08-02 08:25:40 -06:00
parent b695c42e11
commit 300ce61bd0
4 changed files with 47 additions and 38 deletions

View file

@ -498,8 +498,8 @@ pub struct AppContext {
// Action Types -> Action Handlers // Action Types -> Action Handlers
global_actions: HashMap<TypeId, Box<GlobalActionCallback>>, global_actions: HashMap<TypeId, Box<GlobalActionCallback>>,
keystroke_matcher: KeymapMatcher, keystroke_matcher: KeymapMatcher,
next_entity_id: usize, next_id: usize,
next_window_id: usize, // next_window_id: usize,
next_subscription_id: usize, next_subscription_id: usize,
frame_count: usize, frame_count: usize,
@ -558,8 +558,7 @@ impl AppContext {
actions: Default::default(), actions: Default::default(),
global_actions: Default::default(), global_actions: Default::default(),
keystroke_matcher: KeymapMatcher::default(), keystroke_matcher: KeymapMatcher::default(),
next_entity_id: 0, next_id: 0,
next_window_id: 0,
next_subscription_id: 0, next_subscription_id: 0,
frame_count: 0, frame_count: 0,
subscriptions: Default::default(), subscriptions: Default::default(),
@ -1230,7 +1229,7 @@ impl AppContext {
F: FnOnce(&mut ModelContext<T>) -> T, F: FnOnce(&mut ModelContext<T>) -> T,
{ {
self.update(|this| { self.update(|this| {
let model_id = post_inc(&mut this.next_entity_id); let model_id = post_inc(&mut this.next_id);
let handle = ModelHandle::new(model_id, &this.ref_counts); let handle = ModelHandle::new(model_id, &this.ref_counts);
let mut cx = ModelContext::new(this, model_id); let mut cx = ModelContext::new(this, model_id);
let model = build_model(&mut cx); let model = build_model(&mut cx);
@ -1310,7 +1309,7 @@ impl AppContext {
F: FnOnce(&mut ViewContext<V>) -> V, F: FnOnce(&mut ViewContext<V>) -> V,
{ {
self.update(|this| { self.update(|this| {
let window_id = post_inc(&mut this.next_window_id); let window_id = post_inc(&mut this.next_id);
let platform_window = let platform_window =
this.platform this.platform
.open_window(window_id, window_options, this.foreground.clone()); .open_window(window_id, window_options, this.foreground.clone());
@ -1326,7 +1325,7 @@ impl AppContext {
F: FnOnce(&mut ViewContext<V>) -> V, F: FnOnce(&mut ViewContext<V>) -> V,
{ {
self.update(|this| { self.update(|this| {
let window_id = post_inc(&mut this.next_window_id); let window_id = post_inc(&mut this.next_id);
let platform_window = this.platform.add_status_item(window_id); let platform_window = this.platform.add_status_item(window_id);
let window = this.build_window(window_id, platform_window, build_root_view); let window = this.build_window(window_id, platform_window, build_root_view);
let root_view = window.root_view().clone().downcast::<V>().unwrap(); let root_view = window.root_view().clone().downcast::<V>().unwrap();
@ -3810,6 +3809,7 @@ pub struct WindowHandle<T> {
view_type: PhantomData<T>, view_type: PhantomData<T>,
} }
#[allow(dead_code)]
impl<V: View> WindowHandle<V> { impl<V: View> WindowHandle<V> {
fn id(&self) -> usize { fn id(&self) -> usize {
self.any_handle.id() self.any_handle.id()
@ -3922,6 +3922,17 @@ impl AnyWindowHandle {
pub fn id(&self) -> usize { pub fn id(&self) -> usize {
self.window_id self.window_id
} }
pub fn downcast<V: View>(self) -> Option<WindowHandle<V>> {
if TypeId::of::<V>() == self.root_view_type {
Some(WindowHandle {
any_handle: self,
view_type: PhantomData,
})
} else {
None
}
}
} }
impl Drop for AnyWindowHandle { impl Drop for AnyWindowHandle {
@ -5613,20 +5624,18 @@ mod tests {
child: None, child: None,
}); });
let view_1 = window.root(cx); let view_1 = window.root(cx);
let view_2 = window let view_2 = window.update(cx, |cx| {
.update(cx, |cx| { let view_2 = cx.add_view(|_| View {
let view_2 = cx.add_view(|_| View { events: view_events.clone(),
events: view_events.clone(), name: "view 2".to_string(),
name: "view 2".to_string(), child: None,
child: None, });
}); view_1.update(cx, |view_1, cx| {
view_1.update(cx, |view_1, cx| { view_1.child = Some(view_2.clone().into_any());
view_1.child = Some(view_2.clone().into_any()); cx.notify();
cx.notify(); });
}); view_2
view_2 });
})
.unwrap();
let observed_events: Arc<Mutex<Vec<String>>> = Default::default(); let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
view_1.update(cx, |_, cx| { view_1.update(cx, |_, cx| {
@ -6071,26 +6080,26 @@ mod tests {
} }
}); });
cx.update_window(window_id, |cx| { window.update(cx, |cx| {
cx.dispatch_keystroke(&Keystroke::parse("a").unwrap()) cx.dispatch_keystroke(&Keystroke::parse("a").unwrap())
}); });
assert_eq!(&*actions.borrow(), &["2 a"]); assert_eq!(&*actions.borrow(), &["2 a"]);
actions.borrow_mut().clear(); actions.borrow_mut().clear();
cx.update_window(window_id, |cx| { window.update(cx, |cx| {
cx.dispatch_keystroke(&Keystroke::parse("b").unwrap()); cx.dispatch_keystroke(&Keystroke::parse("b").unwrap());
}); });
assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]); assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
actions.borrow_mut().clear(); actions.borrow_mut().clear();
cx.update_window(window_id, |cx| { window.update(cx, |cx| {
cx.dispatch_keystroke(&Keystroke::parse("c").unwrap()); cx.dispatch_keystroke(&Keystroke::parse("c").unwrap());
}); });
assert_eq!(&*actions.borrow(), &["3 c"]); assert_eq!(&*actions.borrow(), &["3 c"]);
actions.borrow_mut().clear(); actions.borrow_mut().clear();
cx.update_window(window_id, |cx| { window.update(cx, |cx| {
cx.dispatch_keystroke(&Keystroke::parse("d").unwrap()); cx.dispatch_keystroke(&Keystroke::parse("d").unwrap());
}); });
assert_eq!(&*actions.borrow(), &["2 d"]); assert_eq!(&*actions.borrow(), &["2 d"]);
@ -6201,7 +6210,7 @@ mod tests {
// Check that global actions do not have a binding, even if a binding does exist in another view // Check that global actions do not have a binding, even if a binding does exist in another view
assert_eq!( assert_eq!(
&available_actions(window_id, view_1.id(), cx), &available_actions(window.id(), view_1.id(), cx),
&[ &[
("test::Action1", vec![Keystroke::parse("a").unwrap()]), ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
("test::GlobalAction", vec![]) ("test::GlobalAction", vec![])
@ -6210,7 +6219,7 @@ mod tests {
// Check that view 1 actions and bindings are available even when called from view 2 // Check that view 1 actions and bindings are available even when called from view 2
assert_eq!( assert_eq!(
&available_actions(window_id, view_2.id(), cx), &available_actions(window.id(), view_2.id(), cx),
&[ &[
("test::Action1", vec![Keystroke::parse("a").unwrap()]), ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
("test::Action2", vec![Keystroke::parse("b").unwrap()]), ("test::Action2", vec![Keystroke::parse("b").unwrap()]),
@ -6273,7 +6282,7 @@ mod tests {
]); ]);
}); });
let actions = cx.available_actions(window_id, view.id()); let actions = cx.available_actions(window.id(), view.id());
assert_eq!( assert_eq!(
actions[0].1.as_any().downcast_ref::<ActionWithArg>(), actions[0].1.as_any().downcast_ref::<ActionWithArg>(),
Some(&ActionWithArg { arg: false }) Some(&ActionWithArg { arg: false })
@ -6559,25 +6568,25 @@ mod tests {
[("window 2", false), ("window 3", true)] [("window 2", false), ("window 3", true)]
); );
cx.simulate_window_activation(Some(window_2)); cx.simulate_window_activation(Some(window_2.id()));
assert_eq!( assert_eq!(
mem::take(&mut *events.borrow_mut()), mem::take(&mut *events.borrow_mut()),
[("window 3", false), ("window 2", true)] [("window 3", false), ("window 2", true)]
); );
cx.simulate_window_activation(Some(window_1)); cx.simulate_window_activation(Some(window_1.id()));
assert_eq!( assert_eq!(
mem::take(&mut *events.borrow_mut()), mem::take(&mut *events.borrow_mut()),
[("window 2", false), ("window 1", true)] [("window 2", false), ("window 1", true)]
); );
cx.simulate_window_activation(Some(window_3)); cx.simulate_window_activation(Some(window_3.id()));
assert_eq!( assert_eq!(
mem::take(&mut *events.borrow_mut()), mem::take(&mut *events.borrow_mut()),
[("window 1", false), ("window 3", true)] [("window 1", false), ("window 3", true)]
); );
cx.simulate_window_activation(Some(window_3)); cx.simulate_window_activation(Some(window_3.id()));
assert_eq!(mem::take(&mut *events.borrow_mut()), []); assert_eq!(mem::take(&mut *events.borrow_mut()), []);
} }
@ -6633,12 +6642,13 @@ mod tests {
let child_rendered = Rc::new(Cell::new(false)); let child_rendered = Rc::new(Cell::new(false));
let child_dropped = Rc::new(Cell::new(false)); let child_dropped = Rc::new(Cell::new(false));
let (_, root_view) = cx.add_window(|cx| Parent { let window = cx.add_window(|cx| Parent {
child: Some(cx.add_view(|_| Child { child: Some(cx.add_view(|_| Child {
rendered: child_rendered.clone(), rendered: child_rendered.clone(),
dropped: child_dropped.clone(), dropped: child_dropped.clone(),
})), })),
}); });
let root_view = window.root(cx);
assert!(child_rendered.take()); assert!(child_rendered.take());
assert!(!child_dropped.take()); assert!(!child_dropped.take());

View file

@ -23,7 +23,6 @@ struct ElementStateRefCount {
#[derive(Default)] #[derive(Default)]
pub struct RefCounts { pub struct RefCounts {
window_counts: HashMap<usize, usize>,
entity_counts: HashMap<usize, usize>, entity_counts: HashMap<usize, usize>,
element_state_counts: HashMap<ElementStateId, ElementStateRefCount>, element_state_counts: HashMap<ElementStateId, ElementStateRefCount>,
dropped_windows: HashSet<usize>, dropped_windows: HashSet<usize>,
@ -46,7 +45,7 @@ impl RefCounts {
} }
pub fn inc_window(&mut self, window_id: usize) { pub fn inc_window(&mut self, window_id: usize) {
match self.window_counts.entry(window_id) { match self.entity_counts.entry(window_id) {
Entry::Occupied(mut entry) => { Entry::Occupied(mut entry) => {
*entry.get_mut() += 1; *entry.get_mut() += 1;
} }
@ -100,7 +99,7 @@ impl RefCounts {
} }
pub fn dec_window(&mut self, window_id: usize) { pub fn dec_window(&mut self, window_id: usize) {
let count = self.window_counts.get_mut(&window_id).unwrap(); let count = self.entity_counts.get_mut(&window_id).unwrap();
*count -= 1; *count -= 1;
if *count == 0 { if *count == 0 {
self.entity_counts.remove(&window_id); self.entity_counts.remove(&window_id);

View file

@ -60,7 +60,7 @@ impl TestAppContext {
RefCounts::new(leak_detector), RefCounts::new(leak_detector),
(), (),
); );
cx.next_entity_id = first_entity_id; cx.next_id = first_entity_id;
let cx = TestAppContext { let cx = TestAppContext {
cx: Rc::new(RefCell::new(cx)), cx: Rc::new(RefCell::new(cx)),
foreground_platform, foreground_platform,

View file

@ -1176,7 +1176,7 @@ impl<'a> WindowContext<'a> {
F: FnOnce(&mut ViewContext<T>) -> Option<T>, F: FnOnce(&mut ViewContext<T>) -> Option<T>,
{ {
let window_id = self.window_id; let window_id = self.window_id;
let view_id = post_inc(&mut self.next_entity_id); let view_id = post_inc(&mut self.next_id);
let mut cx = ViewContext::mutable(self, view_id); let mut cx = ViewContext::mutable(self, view_id);
let handle = if let Some(view) = build_view(&mut cx) { let handle = if let Some(view) = build_view(&mut cx) {
let mut keymap_context = KeymapContext::default(); let mut keymap_context = KeymapContext::default();