Ensure editor elements invalidate their parent views on notify

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
Co-Authored-By: Conrad Irwin <conrad@zed.dev>
This commit is contained in:
Antonio Scandurra 2024-01-12 17:36:11 +01:00
parent a32ad3f907
commit 817b641c17
2 changed files with 124 additions and 109 deletions

View file

@ -26,11 +26,11 @@ use git::diff::DiffHunkStatus;
use gpui::{
div, fill, outline, overlay, point, px, quad, relative, size, transparent_black, Action,
AnchorCorner, AnyElement, AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners,
CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Hsla, InteractiveBounds,
InteractiveElement, IntoElement, ModifiersChangedEvent, MouseButton, MouseDownEvent,
MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine,
SharedString, Size, StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun,
TextStyle, View, ViewContext, WindowContext,
CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity, Hsla,
InteractiveBounds, InteractiveElement, IntoElement, ModifiersChangedEvent, MouseButton,
MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, ScrollDelta,
ScrollWheelEvent, ShapedLine, SharedString, Size, StackingOrder, StatefulInteractiveElement,
Style, Styled, TextRun, TextStyle, View, ViewContext, WindowContext,
};
use itertools::Itertools;
use language::language_settings::ShowWhitespaceSetting;
@ -2801,6 +2801,7 @@ impl Element for EditorElement {
_element_state: Option<Self::State>,
cx: &mut gpui::WindowContext,
) -> (gpui::LayoutId, Self::State) {
cx.with_view_id(self.editor.entity_id(), |cx| {
self.editor.update(cx, |editor, cx| {
editor.set_style(self.style.clone(), cx);
@ -2816,7 +2817,9 @@ impl Element for EditorElement {
let editor_handle = cx.view().clone();
let max_line_number_width =
self.max_line_number_width(&editor.snapshot(cx), cx);
cx.request_measured_layout(Style::default(), move |known_dimensions, _, cx| {
cx.request_measured_layout(
Style::default(),
move |known_dimensions, _, cx| {
editor_handle
.update(cx, |editor, cx| {
compute_auto_height_layout(
@ -2828,7 +2831,8 @@ impl Element for EditorElement {
)
})
.unwrap_or_default()
})
},
)
}
EditorMode::Full => {
let mut style = Style::default();
@ -2840,6 +2844,7 @@ impl Element for EditorElement {
(layout_id, ())
})
})
}
fn paint(
@ -2850,6 +2855,7 @@ impl Element for EditorElement {
) {
let editor = self.editor.clone();
cx.paint_view(self.editor.entity_id(), |cx| {
cx.with_text_style(
Some(gpui::TextStyleRefinement {
font_size: Some(self.style.text.font_size),
@ -2908,7 +2914,8 @@ impl Element for EditorElement {
});
})
},
);
)
})
}
}
@ -3588,9 +3595,7 @@ mod tests {
// Don't panic.
let bounds = Bounds::<Pixels>::new(Default::default(), size);
cx.update_window(window.into(), |view, cx| {
cx.paint_view(view.entity_id(), |cx| element.paint(bounds, &mut (), cx))
})
cx.update_window(window.into(), |view, cx| element.paint(bounds, &mut (), cx))
.unwrap()
}

View file

@ -2009,24 +2009,34 @@ impl<'a> WindowContext<'a> {
pub fn with_view_id<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
let text_system = self.text_system().clone();
text_system.with_view(view_id, || {
if self.window.next_frame.view_stack.last() == Some(&view_id) {
return f(self);
} else {
self.window.next_frame.view_stack.push(view_id);
let result = f(self);
self.window.next_frame.view_stack.pop();
result
}
})
}
/// Invoke the given function with the given view id present on the view stack.
/// This is a fairly low-level method used to paint views.
pub fn paint_view<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
self.with_view_id(view_id, |cx| {
cx.window
let text_system = self.text_system().clone();
text_system.with_view(view_id, || {
if self.window.next_frame.view_stack.last() == Some(&view_id) {
return f(self);
} else {
self.window.next_frame.view_stack.push(view_id);
self.window
.next_frame
.dispatch_tree
.push_node(None, None, Some(view_id));
let result = f(cx);
cx.window.next_frame.dispatch_tree.pop_node();
let result = f(self);
self.window.next_frame.view_stack.pop();
result
}
})
}