mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-07 00:06:24 +03:00
Cache view's type id and keymap context into a separate map
During `layout`, we now pass a mutable reference to the element's parent view. This is a recursive process that causes the view to be removed from `AppContext` and then re-inserted back into it once the layout is complete. As such, querying parent views during `layout` does not work as such views will have been removed from `AppContext` and not yet re-inserted into it. This caused a bug in `KeystrokeLabel`, which used the `keystrokes_for_action` method to query its ancestors to determine their type id and keymap context. Now, any time a view notifies, we will cache its keymap context so that we don't need to query the parent view during `layout`.
This commit is contained in:
parent
053b34875b
commit
18e39ef2fa
@ -440,6 +440,7 @@ type WindowShouldCloseSubscriptionCallback = Box<dyn FnMut(&mut AppContext) -> b
|
||||
pub struct AppContext {
|
||||
models: HashMap<usize, Box<dyn AnyModel>>,
|
||||
views: HashMap<(usize, usize), Box<dyn AnyView>>,
|
||||
views_metadata: HashMap<(usize, usize), ViewMetadata>,
|
||||
pub(crate) parents: HashMap<(usize, usize), ParentId>,
|
||||
windows: HashMap<usize, Window>,
|
||||
globals: HashMap<TypeId, Box<dyn Any>>,
|
||||
@ -502,6 +503,7 @@ impl AppContext {
|
||||
Self {
|
||||
models: Default::default(),
|
||||
views: Default::default(),
|
||||
views_metadata: Default::default(),
|
||||
parents: Default::default(),
|
||||
windows: Default::default(),
|
||||
globals: Default::default(),
|
||||
@ -727,9 +729,9 @@ impl AppContext {
|
||||
}
|
||||
|
||||
pub fn view_type_id(&self, window_id: usize, view_id: usize) -> Option<TypeId> {
|
||||
self.views
|
||||
self.views_metadata
|
||||
.get(&(window_id, view_id))
|
||||
.map(|view| view.as_any().type_id())
|
||||
.map(|metadata| metadata.type_id)
|
||||
}
|
||||
|
||||
pub fn active_labeled_tasks<'a>(
|
||||
@ -1045,9 +1047,10 @@ impl AppContext {
|
||||
.read_window(window_id, |cx| {
|
||||
if let Some(focused_view_id) = cx.focused_view_id() {
|
||||
for view_id in cx.ancestors(focused_view_id) {
|
||||
if let Some(view) = cx.views.get(&(window_id, view_id)) {
|
||||
let view_type = view.as_any().type_id();
|
||||
if let Some(actions) = cx.actions.get(&view_type) {
|
||||
if let Some(view_metadata) =
|
||||
cx.views_metadata.get(&(window_id, view_id))
|
||||
{
|
||||
if let Some(actions) = cx.actions.get(&view_metadata.type_id) {
|
||||
if actions.contains_key(&action_type) {
|
||||
return true;
|
||||
}
|
||||
@ -1448,6 +1451,7 @@ impl AppContext {
|
||||
for (window_id, view_id) in dropped_views {
|
||||
self.subscriptions.remove(view_id);
|
||||
self.observations.remove(view_id);
|
||||
self.views_metadata.remove(&(window_id, view_id));
|
||||
let mut view = self.views.remove(&(window_id, view_id)).unwrap();
|
||||
view.release(self);
|
||||
let change_focus_to = self.windows.get_mut(&window_id).and_then(|window| {
|
||||
@ -1779,9 +1783,11 @@ impl AppContext {
|
||||
observed_window_id: usize,
|
||||
observed_view_id: usize,
|
||||
) {
|
||||
if self
|
||||
let view_key = (observed_window_id, observed_view_id);
|
||||
if let Some((view, mut view_metadata)) = self
|
||||
.views
|
||||
.contains_key(&(observed_window_id, observed_view_id))
|
||||
.remove(&view_key)
|
||||
.zip(self.views_metadata.remove(&view_key))
|
||||
{
|
||||
if let Some(window) = self.windows.get_mut(&observed_window_id) {
|
||||
window
|
||||
@ -1791,6 +1797,10 @@ impl AppContext {
|
||||
.insert(observed_view_id);
|
||||
}
|
||||
|
||||
view_metadata.keymap_context = view.keymap_context(self);
|
||||
self.views.insert(view_key, view);
|
||||
self.views_metadata.insert(view_key, view_metadata);
|
||||
|
||||
let mut observations = self.observations.clone();
|
||||
observations.emit(observed_view_id, |callback| callback(self));
|
||||
}
|
||||
@ -2037,6 +2047,11 @@ pub enum ParentId {
|
||||
Root,
|
||||
}
|
||||
|
||||
struct ViewMetadata {
|
||||
type_id: TypeId,
|
||||
keymap_context: KeymapContext,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct WindowInvalidation {
|
||||
pub updated: HashSet<usize>,
|
||||
@ -2437,11 +2452,10 @@ where
|
||||
cx.handle().into_any()
|
||||
} else {
|
||||
let focused_type = cx
|
||||
.views
|
||||
.views_metadata
|
||||
.get(&(cx.window_id, focused_id))
|
||||
.unwrap()
|
||||
.as_any()
|
||||
.type_id();
|
||||
.type_id;
|
||||
AnyViewHandle::new(
|
||||
cx.window_id,
|
||||
focused_id,
|
||||
@ -2458,11 +2472,10 @@ where
|
||||
cx.handle().into_any()
|
||||
} else {
|
||||
let blurred_type = cx
|
||||
.views
|
||||
.views_metadata
|
||||
.get(&(cx.window_id, blurred_id))
|
||||
.unwrap()
|
||||
.as_any()
|
||||
.type_id();
|
||||
.type_id;
|
||||
AnyViewHandle::new(
|
||||
cx.window_id,
|
||||
blurred_id,
|
||||
|
@ -34,7 +34,7 @@ use std::{
|
||||
use util::ResultExt;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::Reference;
|
||||
use super::{Reference, ViewMetadata};
|
||||
|
||||
pub struct Window {
|
||||
pub(crate) root_view: Option<AnyViewHandle>,
|
||||
@ -369,13 +369,13 @@ impl<'a> WindowContext<'a> {
|
||||
let mut contexts = Vec::new();
|
||||
let mut handler_depth = None;
|
||||
for (i, view_id) in self.ancestors(view_id).enumerate() {
|
||||
if let Some(view) = self.views.get(&(window_id, view_id)) {
|
||||
if let Some(actions) = self.actions.get(&view.as_any().type_id()) {
|
||||
if let Some(view_metadata) = self.views_metadata.get(&(window_id, view_id)) {
|
||||
if let Some(actions) = self.actions.get(&view_metadata.type_id) {
|
||||
if actions.contains_key(&action.as_any().type_id()) {
|
||||
handler_depth = Some(i);
|
||||
}
|
||||
}
|
||||
contexts.push(view.keymap_context(self));
|
||||
contexts.push(view_metadata.keymap_context.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1177,6 +1177,14 @@ impl<'a> WindowContext<'a> {
|
||||
self.parents.insert((window_id, view_id), parent_id);
|
||||
let mut cx = ViewContext::mutable(self, view_id);
|
||||
let handle = if let Some(view) = build_view(&mut cx) {
|
||||
let keymap_context = view.keymap_context(cx.app_context());
|
||||
self.views_metadata.insert(
|
||||
(window_id, view_id),
|
||||
ViewMetadata {
|
||||
type_id: TypeId::of::<T>(),
|
||||
keymap_context,
|
||||
},
|
||||
);
|
||||
self.views.insert((window_id, view_id), Box::new(view));
|
||||
self.window
|
||||
.invalidation
|
||||
|
Loading…
Reference in New Issue
Block a user