Incorporate ElementId as part of the Element::id trait method and expose GlobalId (#11101)

We're planning to associate "selection sources" with global element ids
to allow arbitrary UI text to be selected in GPUI. Previously, global
ids were not exposed outside the framework and we entangled management
of the element id stack with element state access. This was more
acceptable when element state was the only place we used global element
ids, but now that we're planning to use them more places, it makes sense
to deal with element identity as a first-class part of the element
system. We now ensure that the stack of element ids which forms the
current global element id is correctly managed in every phase of element
layout and paint and make the global id available to each element
method. In a subsequent PR, we'll use the global element id as part of
implementing arbitrary selection for UI text.

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Nathan Sobo
2024-04-28 13:59:21 -06:00
committed by GitHub
co-authored by Antonio Scandurra
parent 8b55494351
commit 39fb1d567d
21 changed files with 825 additions and 497 deletions
+38 -24
View File
@@ -25,10 +25,11 @@ use gpui::{
anchored, deferred, div, fill, outline, point, px, quad, relative, size, svg,
transparent_black, Action, AnchorCorner, AnyElement, AvailableSpace, Bounds, ClipboardItem,
ContentMask, Corners, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity,
Hitbox, Hsla, InteractiveElement, IntoElement, ModifiersChangedEvent, MouseButton,
MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad, ParentElement, Pixels, ScrollDelta,
ScrollWheelEvent, ShapedLine, SharedString, Size, Stateful, StatefulInteractiveElement, Style,
Styled, TextRun, TextStyle, TextStyleRefinement, View, ViewContext, WeakView, WindowContext,
GlobalElementId, Hitbox, Hsla, InteractiveElement, IntoElement, ModifiersChangedEvent,
MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad, ParentElement, Pixels,
ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString, Size, Stateful,
StatefulInteractiveElement, Style, Styled, TextRun, TextStyle, TextStyleRefinement, View,
ViewContext, WeakView, WindowContext,
};
use itertools::Itertools;
use language::language_settings::ShowWhitespaceSetting;
@@ -2270,7 +2271,7 @@ impl EditorElement {
}
cx.paint_layer(layout.gutter_hitbox.bounds, |cx| {
cx.with_element_id(Some("gutter_fold_indicators"), |cx| {
cx.with_element_namespace("gutter_fold_indicators", |cx| {
for fold_indicator in layout.fold_indicators.iter_mut().flatten() {
fold_indicator.paint(cx);
}
@@ -2419,7 +2420,7 @@ impl EditorElement {
};
cx.set_cursor_style(cursor_style, &layout.text_hitbox);
cx.with_element_id(Some("folds"), |cx| self.paint_folds(layout, cx));
cx.with_element_namespace("folds", |cx| self.paint_folds(layout, cx));
let invisible_display_ranges = self.paint_highlights(layout, cx);
self.paint_lines(&invisible_display_ranges, layout, cx);
self.paint_redactions(layout, cx);
@@ -3446,7 +3447,15 @@ impl Element for EditorElement {
type RequestLayoutState = ();
type PrepaintState = EditorLayout;
fn request_layout(&mut self, cx: &mut WindowContext) -> (gpui::LayoutId, ()) {
fn id(&self) -> Option<ElementId> {
None
}
fn request_layout(
&mut self,
_: Option<&GlobalElementId>,
cx: &mut WindowContext,
) -> (gpui::LayoutId, ()) {
self.editor.update(cx, |editor, cx| {
editor.set_style(self.style.clone(), cx);
@@ -3490,6 +3499,7 @@ impl Element for EditorElement {
fn prepaint(
&mut self,
_: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
cx: &mut WindowContext,
@@ -3666,19 +3676,22 @@ impl Element for EditorElement {
.width;
let mut scroll_width =
longest_line_width.max(max_visible_line_width) + overscroll.width;
let mut blocks = self.build_blocks(
start_row..end_row,
&snapshot,
&hitbox,
&text_hitbox,
&mut scroll_width,
&gutter_dimensions,
em_width,
gutter_dimensions.width + gutter_dimensions.margin,
line_height,
&line_layouts,
cx,
);
let mut blocks = cx.with_element_namespace("blocks", |cx| {
self.build_blocks(
start_row..end_row,
&snapshot,
&hitbox,
&text_hitbox,
&mut scroll_width,
&gutter_dimensions,
em_width,
gutter_dimensions.width + gutter_dimensions.margin,
line_height,
&line_layouts,
cx,
)
});
let scroll_pixel_position = point(
scroll_position.x * em_width,
@@ -3740,7 +3753,7 @@ impl Element for EditorElement {
}
});
cx.with_element_id(Some("blocks"), |cx| {
cx.with_element_namespace("blocks", |cx| {
self.layout_blocks(
&mut blocks,
&hitbox,
@@ -3776,7 +3789,7 @@ impl Element for EditorElement {
cx,
);
let folds = cx.with_element_id(Some("folds"), |cx| {
let folds = cx.with_element_namespace("folds", |cx| {
self.layout_folds(
&snapshot,
content_origin,
@@ -3837,7 +3850,7 @@ impl Element for EditorElement {
let mouse_context_menu = self.layout_mouse_context_menu(cx);
let fold_indicators = if gutter_settings.folds {
cx.with_element_id(Some("gutter_fold_indicators"), |cx| {
cx.with_element_namespace("gutter_fold_indicators", |cx| {
self.layout_gutter_fold_indicators(
fold_statuses,
line_height,
@@ -3930,6 +3943,7 @@ impl Element for EditorElement {
fn paint(
&mut self,
_: Option<&GlobalElementId>,
bounds: Bounds<gpui::Pixels>,
_: &mut Self::RequestLayoutState,
layout: &mut Self::PrepaintState,
@@ -3962,7 +3976,7 @@ impl Element for EditorElement {
self.paint_text(layout, cx);
if !layout.blocks.is_empty() {
cx.with_element_id(Some("blocks"), |cx| {
cx.with_element_namespace("blocks", |cx| {
self.paint_blocks(layout, cx);
});
}