chart: Draw dashed lines using gpui PathBuilder (#927)
https://github.com/zed-industries/zed/pull/31678
This commit is contained in:
parent
01197769df
commit
44ec74f1fb
10 changed files with 36 additions and 83 deletions
31
Cargo.lock
generated
31
Cargo.lock
generated
|
|
@ -623,7 +623,7 @@ dependencies = [
|
|||
"bitflags 2.9.1",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools 0.12.1",
|
||||
"itertools 0.10.5",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"log",
|
||||
|
|
@ -646,7 +646,7 @@ dependencies = [
|
|||
"bitflags 2.9.1",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools 0.13.0",
|
||||
"itertools 0.10.5",
|
||||
"log",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
|
|
@ -1226,7 +1226,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "collections"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"indexmap 2.7.1",
|
||||
"rustc-hash 2.1.0",
|
||||
|
|
@ -1739,7 +1739,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "derive_refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -2777,7 +2777,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "gpui"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"as-raw-xcb-connection",
|
||||
|
|
@ -2881,7 +2881,6 @@ dependencies = [
|
|||
"image",
|
||||
"indoc",
|
||||
"itertools 0.13.0",
|
||||
"lyon",
|
||||
"markdown",
|
||||
"markup5ever_rcdom",
|
||||
"minify-html",
|
||||
|
|
@ -2946,7 +2945,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "gpui_macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
|
|
@ -3216,7 +3215,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "http_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
|
@ -3233,7 +3232,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "http_client_tls"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"rustls-platform-verifier",
|
||||
|
|
@ -4003,7 +4002,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "media"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bindgen 0.71.1",
|
||||
|
|
@ -4396,7 +4395,7 @@ version = "0.7.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
|
||||
dependencies = [
|
||||
"proc-macro-crate 3.2.0",
|
||||
"proc-macro-crate 1.3.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
|
|
@ -5720,7 +5719,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"derive_refineable",
|
||||
"workspace-hack",
|
||||
|
|
@ -5830,7 +5829,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "reqwest_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
|
@ -6379,7 +6378,7 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a"
|
|||
[[package]]
|
||||
name = "semantic_version"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
|
|
@ -6876,7 +6875,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||
[[package]]
|
||||
name = "sum_tree"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"log",
|
||||
|
|
@ -8043,7 +8042,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||
[[package]]
|
||||
name = "util"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed.git#06a199da4d8a147c7867f4c82ffafed4974bea24"
|
||||
source = "git+https://github.com/zed-industries/zed.git#b15aef4310e86aa31c2ceab74184ec7e5627a2c5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-fs 2.1.2",
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ UI components for building fantastic desktop applications using [GPUI](https://g
|
|||
|
||||
Here is the first application: [Longbridge Pro](https://longbridge.com/desktop), built using GPUI Component.
|
||||
|
||||
<img width="1763" alt="Image" src="https://i.postimg.cc/qBh6GCvp/Longbridge-Pro.png" />
|
||||
<img width="1763" alt="Image" src="https://wp-cdn.4ce.cn/v2/hZRGaJm.png" />
|
||||
|
||||
We built multi-theme support in the application. This feature is not included in GPUI Component itself, but is based on the `Theme` feature, so it's easy to implement.
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ enum-iterator = "2.1.0"
|
|||
futures-util = "0.3.31"
|
||||
image = "0.25.1"
|
||||
itertools = "0.13.0"
|
||||
lyon = "1.0"
|
||||
once_cell = "1.19.0"
|
||||
paste = "1"
|
||||
regex = "1"
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ where
|
|||
Grid::new()
|
||||
.y((0..=3).map(|i| height * i as f64 / 4.0).collect())
|
||||
.stroke(cx.theme().border)
|
||||
.dash_array([px(4.), px(2.)])
|
||||
.dash_array(&[px(4.), px(2.)])
|
||||
.paint(&bounds, window);
|
||||
|
||||
// Draw area
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ where
|
|||
Grid::new()
|
||||
.y((0..=3).map(|i| height * i as f64 / 4.0).collect())
|
||||
.stroke(cx.theme().border)
|
||||
.dash_array([px(4.), px(2.)])
|
||||
.dash_array(&[px(4.), px(2.)])
|
||||
.paint(&bounds, window);
|
||||
|
||||
// Draw bars
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ where
|
|||
Grid::new()
|
||||
.y((0..=3).map(|i| height * i as f64 / 4.0).collect())
|
||||
.stroke(cx.theme().border)
|
||||
.dash_array([px(4.), px(2.)])
|
||||
.dash_array(&[px(4.), px(2.)])
|
||||
.paint(&bounds, window);
|
||||
|
||||
// Draw line
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use gpui::{px, Bounds, Hsla, PathBuilder, Pixels, Point, Window};
|
||||
|
||||
use super::{dash_line, origin_point};
|
||||
use super::origin_point;
|
||||
|
||||
pub struct Grid {
|
||||
x: Vec<Pixels>,
|
||||
y: Vec<Pixels>,
|
||||
stroke: Hsla,
|
||||
dash_array: Option<[Pixels; 2]>,
|
||||
dash_array: Option<Vec<Pixels>>,
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
|
|
@ -39,8 +39,8 @@ impl Grid {
|
|||
}
|
||||
|
||||
/// Set the dash array of the Grid.
|
||||
pub fn dash_array(mut self, dash_array: [Pixels; 2]) -> Self {
|
||||
self.dash_array = Some(dash_array);
|
||||
pub fn dash_array(mut self, dash_array: &[Pixels]) -> Self {
|
||||
self.dash_array = Some(dash_array.to_vec());
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -78,20 +78,17 @@ impl Grid {
|
|||
pub fn paint(&self, bounds: &Bounds<Pixels>, window: &mut Window) {
|
||||
let points = self.points(bounds);
|
||||
|
||||
if let Some(dash_array) = self.dash_array {
|
||||
for (start, end) in points {
|
||||
if let Some(line) = dash_line(start, end, dash_array) {
|
||||
window.paint_path(line, self.stroke);
|
||||
}
|
||||
for (start, end) in points {
|
||||
let mut builder = PathBuilder::stroke(px(1.));
|
||||
|
||||
if let Some(dash_array) = &self.dash_array {
|
||||
builder = builder.dash_array(&dash_array);
|
||||
}
|
||||
} else {
|
||||
for (start, end) in points {
|
||||
let mut builder = PathBuilder::stroke(px(1.));
|
||||
builder.move_to(start);
|
||||
builder.line_to(end);
|
||||
if let Ok(line) = builder.build() {
|
||||
window.paint_path(line, self.stroke);
|
||||
}
|
||||
|
||||
builder.move_to(start);
|
||||
builder.line_to(end);
|
||||
if let Ok(line) = builder.build() {
|
||||
window.paint_path(line, self.stroke);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@ pub use gpui_component_macros::IntoPlot;
|
|||
|
||||
use std::{fmt::Debug, ops::Add};
|
||||
|
||||
use gpui::{
|
||||
point, px, App, Bounds, IntoElement, Path, PathBuilder, PathStyle, Pixels, Point,
|
||||
StrokeOptions, Window,
|
||||
};
|
||||
use gpui::{point, px, App, Bounds, IntoElement, Path, PathBuilder, Pixels, Point, Window};
|
||||
|
||||
pub use axis::{Axis, AxisText, AXIS_GAP};
|
||||
pub use grid::Grid;
|
||||
|
|
@ -36,45 +33,6 @@ where
|
|||
point(x, y) + origin
|
||||
}
|
||||
|
||||
// TODO: Move into gpui
|
||||
//
|
||||
// https://github.com/zed-industries/zed/pull/31678
|
||||
pub fn dash_line<T>(start: Point<T>, end: Point<T>, dash_array: [T; 2]) -> Option<Path<Pixels>>
|
||||
where
|
||||
T: Default + Clone + Copy + Debug + PartialEq + Add<Output = T> + Into<f64>,
|
||||
{
|
||||
let mut path = lyon::path::Path::builder();
|
||||
path.begin(lyon::geom::point(
|
||||
start.x.into() as f32,
|
||||
start.y.into() as f32,
|
||||
));
|
||||
path.line_to(lyon::geom::point(end.x.into() as f32, end.y.into() as f32));
|
||||
path.end(false);
|
||||
let path = path.build();
|
||||
|
||||
// Make path dashable.
|
||||
let measure = lyon::algorithms::measure::PathMeasurements::from_path(&path, 0.01);
|
||||
let mut sampler =
|
||||
measure.create_sampler(&path, lyon::algorithms::measure::SampleType::Normalized);
|
||||
let mut dashes = lyon::path::Path::builder();
|
||||
let length = sampler.length();
|
||||
let dash_length = dash_array[0].into() as f32;
|
||||
let gap_length = dash_array[1].into() as f32;
|
||||
let pattern_length = dash_length + gap_length;
|
||||
let num_patterns = (length / pattern_length).ceil() as usize;
|
||||
for i in 0..num_patterns {
|
||||
let start = i as f32 * pattern_length / length;
|
||||
let end = (i as f32 * pattern_length + dash_length) / length;
|
||||
sampler.split_range(start..end.min(1.), &mut dashes);
|
||||
}
|
||||
|
||||
let mut path: PathBuilder = dashes.into();
|
||||
path = path.with_style(PathStyle::Stroke(
|
||||
StrokeOptions::default().with_line_width(1.),
|
||||
));
|
||||
path.build().ok()
|
||||
}
|
||||
|
||||
pub fn polygon<T>(points: &[Point<T>], bounds: &Bounds<Pixels>) -> Option<Path<Pixels>>
|
||||
where
|
||||
T: Default + Clone + Copy + Debug + Into<f64> + PartialEq,
|
||||
|
|
|
|||
|
|
@ -676,7 +676,7 @@ impl Element for Scrollbar {
|
|||
let margin_end = state.margin_end;
|
||||
let is_vertical = axis.is_vertical();
|
||||
|
||||
window.set_cursor_style(CursorStyle::default(), Some(&state.bar_hitbox));
|
||||
window.set_cursor_style(CursorStyle::default(), &state.bar_hitbox);
|
||||
|
||||
window.paint_layer(hitbox_bounds, |cx| {
|
||||
cx.paint_quad(fill(state.bounds, state.bg));
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ impl RenderOnce for WindowBorder {
|
|||
CursorStyle::ResizeUpRightDownLeft
|
||||
}
|
||||
},
|
||||
Some(&hitbox),
|
||||
&hitbox,
|
||||
);
|
||||
},
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue