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::{ use gpui::{
div, fill, outline, overlay, point, px, quad, relative, size, transparent_black, Action, div, fill, outline, overlay, point, px, quad, relative, size, transparent_black, Action,
AnchorCorner, AnyElement, AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners, AnchorCorner, AnyElement, AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners,
CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Hsla, InteractiveBounds, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity, Hsla,
InteractiveElement, IntoElement, ModifiersChangedEvent, MouseButton, MouseDownEvent, InteractiveBounds, InteractiveElement, IntoElement, ModifiersChangedEvent, MouseButton,
MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, ScrollDelta,
SharedString, Size, StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun, ScrollWheelEvent, ShapedLine, SharedString, Size, StackingOrder, StatefulInteractiveElement,
TextStyle, View, ViewContext, WindowContext, Style, Styled, TextRun, TextStyle, View, ViewContext, WindowContext,
}; };
use itertools::Itertools; use itertools::Itertools;
use language::language_settings::ShowWhitespaceSetting; use language::language_settings::ShowWhitespaceSetting;
@ -2801,6 +2801,7 @@ impl Element for EditorElement {
_element_state: Option<Self::State>, _element_state: Option<Self::State>,
cx: &mut gpui::WindowContext, cx: &mut gpui::WindowContext,
) -> (gpui::LayoutId, Self::State) { ) -> (gpui::LayoutId, Self::State) {
cx.with_view_id(self.editor.entity_id(), |cx| {
self.editor.update(cx, |editor, cx| { self.editor.update(cx, |editor, cx| {
editor.set_style(self.style.clone(), cx); editor.set_style(self.style.clone(), cx);
@ -2816,7 +2817,9 @@ impl Element for EditorElement {
let editor_handle = cx.view().clone(); let editor_handle = cx.view().clone();
let max_line_number_width = let max_line_number_width =
self.max_line_number_width(&editor.snapshot(cx), cx); 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 editor_handle
.update(cx, |editor, cx| { .update(cx, |editor, cx| {
compute_auto_height_layout( compute_auto_height_layout(
@ -2828,7 +2831,8 @@ impl Element for EditorElement {
) )
}) })
.unwrap_or_default() .unwrap_or_default()
}) },
)
} }
EditorMode::Full => { EditorMode::Full => {
let mut style = Style::default(); let mut style = Style::default();
@ -2840,6 +2844,7 @@ impl Element for EditorElement {
(layout_id, ()) (layout_id, ())
}) })
})
} }
fn paint( fn paint(
@ -2850,6 +2855,7 @@ impl Element for EditorElement {
) { ) {
let editor = self.editor.clone(); let editor = self.editor.clone();
cx.paint_view(self.editor.entity_id(), |cx| {
cx.with_text_style( cx.with_text_style(
Some(gpui::TextStyleRefinement { Some(gpui::TextStyleRefinement {
font_size: Some(self.style.text.font_size), 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. // Don't panic.
let bounds = Bounds::<Pixels>::new(Default::default(), size); let bounds = Bounds::<Pixels>::new(Default::default(), size);
cx.update_window(window.into(), |view, cx| { cx.update_window(window.into(), |view, cx| element.paint(bounds, &mut (), cx))
cx.paint_view(view.entity_id(), |cx| element.paint(bounds, &mut (), cx))
})
.unwrap() .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 { 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(); let text_system = self.text_system().clone();
text_system.with_view(view_id, || { 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.view_stack.push(view_id);
let result = f(self); let result = f(self);
self.window.next_frame.view_stack.pop(); self.window.next_frame.view_stack.pop();
result result
}
}) })
} }
/// Invoke the given function with the given view id present on the view stack. /// 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. /// 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 { pub fn paint_view<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
self.with_view_id(view_id, |cx| { let text_system = self.text_system().clone();
cx.window 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 .next_frame
.dispatch_tree .dispatch_tree
.push_node(None, None, Some(view_id)); .push_node(None, None, Some(view_id));
let result = f(cx); let result = f(self);
cx.window.next_frame.dispatch_tree.pop_node(); self.window.next_frame.view_stack.pop();
result result
}
}) })
} }