Add support for dashed borders to GPUI (#27139)

Features:

* Scales dash spacing with border width.
* Laying out dashes around rounded corners.
* Varying border widths with rounded corners - now uses an ellipse for the inner edge of the border.
* When there are no rounded corners, each straight border is laid out separately, so that the dashes to meet at the corners.
* All sides of each dash are antialiased.

![image](https://github.com/user-attachments/assets/b3789a98-a5be-4f97-9736-c4e59615afe6)

![image](https://github.com/user-attachments/assets/739bdc57-4580-42c8-bfc3-6e287411a408)

Release Notes:

- N/A

---------

Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Ben <ben@zed.dev>
This commit is contained in:
Nathan Sobo 2025-03-25 11:11:04 -06:00 committed by GitHub
parent 2fe2028e20
commit cd1e56d6c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 869 additions and 159 deletions

View file

@ -35,9 +35,9 @@ use git::{blame::BlameEntry, status::FileStatus, Oid};
use gpui::{
anchored, deferred, div, fill, linear_color_stop, linear_gradient, outline, point, px, quad,
relative, size, solid_background, transparent_black, Action, AnyElement, App, AvailableSpace,
Axis, Bounds, ClickEvent, ClipboardItem, ContentMask, Context, Corner, Corners, CursorStyle,
DispatchPhase, Edges, Element, ElementInputHandler, Entity, Focusable as _, FontId,
GlobalElementId, Hitbox, Hsla, InteractiveElement, IntoElement, Keystroke, Length,
Axis, BorderStyle, Bounds, ClickEvent, ClipboardItem, ContentMask, Context, Corner, Corners,
CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity, Focusable as _,
FontId, GlobalElementId, Hitbox, Hsla, InteractiveElement, IntoElement, Keystroke, Length,
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad,
ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString, Size,
StatefulInteractiveElement, Style, Styled, Subscription, TextRun, TextStyleRefinement, Window,
@ -4549,6 +4549,7 @@ impl EditorElement {
flattened_background_color,
Edges::default(),
transparent_black(),
BorderStyle::default(),
));
} else {
let flattened_unstaged_background_color = cx
@ -4563,6 +4564,7 @@ impl EditorElement {
flattened_unstaged_background_color,
Edges::all(Pixels(1.0)),
flattened_background_color,
BorderStyle::Solid,
));
}
}
@ -4927,6 +4929,7 @@ impl EditorElement {
left: Pixels::ZERO,
},
cx.theme().colors().scrollbar_track_border,
BorderStyle::Solid,
));
window.paint_quad(quad(
@ -4940,6 +4943,7 @@ impl EditorElement {
left: ScrollbarLayout::BORDER_WIDTH,
},
cx.theme().colors().scrollbar_thumb_border,
BorderStyle::Solid,
));
})
}
@ -5075,6 +5079,7 @@ impl EditorElement {
left: ScrollbarLayout::BORDER_WIDTH,
},
cx.theme().colors().scrollbar_track_border,
BorderStyle::Solid,
));
let fast_markers =
@ -5100,6 +5105,7 @@ impl EditorElement {
left: ScrollbarLayout::BORDER_WIDTH,
},
cx.theme().colors().scrollbar_thumb_border,
BorderStyle::Solid,
));
});
}
@ -8063,6 +8069,7 @@ impl ScrollbarLayout {
pixel_range.color,
Edges::default(),
Hsla::transparent_black(),
BorderStyle::default(),
));
}
@ -8296,7 +8303,7 @@ impl CursorLayout {
//Draw background or border quad
let cursor = if matches!(self.shape, CursorShape::Hollow) {
outline(bounds, self.color)
outline(bounds, self.color, BorderStyle::Solid)
} else {
fill(bounds, self.color)
};