
Release Notes: - gpui: Add linear gradient support to fill background Run example: ``` cargo run -p gpui --example gradient cargo run -p gpui --example gradient --features macos-blade ``` ## Demo In GPUI (sRGB): <img width="761" alt="image" src="https://github.com/user-attachments/assets/568c02e8-3065-43c2-b5c2-5618d553dd6e"> In GPUI (Oklab): <img width="761" alt="image" src="https://github.com/user-attachments/assets/b008b0de-2705-4f99-831d-998ce48eed42"> In CSS (sRGB): https://codepen.io/huacnlee/pen/rNXgxBY <img width="505" alt="image" src="https://github.com/user-attachments/assets/239f4b65-24b3-4797-9491-a13eea420158"> In CSS (Oklab): https://codepen.io/huacnlee/pen/wBwBKOp <img width="658" alt="image" src="https://github.com/user-attachments/assets/56fdd55f-d219-45de-922f-7227f535b210"> --- Currently only support 2 color stops with linear-gradient. I think this is we first introduce the gradient feature in GPUI, and the linear-gradient is most popular for use. So we can just add this first and then to add more other supports.
254 lines
9.6 KiB
Rust
254 lines
9.6 KiB
Rust
use gpui::{
|
|
canvas, div, linear_color_stop, linear_gradient, point, prelude::*, px, size, App, AppContext,
|
|
Bounds, ColorSpace, Half, Render, ViewContext, WindowOptions,
|
|
};
|
|
|
|
struct GradientViewer {
|
|
color_space: ColorSpace,
|
|
}
|
|
|
|
impl GradientViewer {
|
|
fn new() -> Self {
|
|
Self {
|
|
color_space: ColorSpace::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Render for GradientViewer {
|
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
|
let color_space = self.color_space;
|
|
|
|
div()
|
|
.font_family(".SystemUIFont")
|
|
.bg(gpui::white())
|
|
.size_full()
|
|
.p_4()
|
|
.flex()
|
|
.flex_col()
|
|
.gap_3()
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.gap_2()
|
|
.justify_between()
|
|
.items_center()
|
|
.child("Gradient Examples")
|
|
.child(
|
|
div().flex().gap_2().items_center().child(
|
|
div()
|
|
.id("method")
|
|
.flex()
|
|
.px_3()
|
|
.py_1()
|
|
.text_sm()
|
|
.bg(gpui::black())
|
|
.text_color(gpui::white())
|
|
.child(format!("{}", color_space))
|
|
.active(|this| this.opacity(0.8))
|
|
.on_click(cx.listener(move |this, _, cx| {
|
|
this.color_space = match this.color_space {
|
|
ColorSpace::Oklab => ColorSpace::Srgb,
|
|
ColorSpace::Srgb => ColorSpace::Oklab,
|
|
};
|
|
cx.notify();
|
|
})),
|
|
),
|
|
),
|
|
)
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.flex_1()
|
|
.gap_3()
|
|
.child(
|
|
div()
|
|
.size_full()
|
|
.rounded_xl()
|
|
.flex()
|
|
.items_center()
|
|
.justify_center()
|
|
.bg(gpui::red())
|
|
.text_color(gpui::white())
|
|
.child("Solid Color"),
|
|
)
|
|
.child(
|
|
div()
|
|
.size_full()
|
|
.rounded_xl()
|
|
.flex()
|
|
.items_center()
|
|
.justify_center()
|
|
.bg(gpui::blue())
|
|
.text_color(gpui::white())
|
|
.child("Solid Color"),
|
|
),
|
|
)
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.flex_1()
|
|
.gap_3()
|
|
.h_24()
|
|
.text_color(gpui::white())
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
45.,
|
|
linear_color_stop(gpui::red(), 0.),
|
|
linear_color_stop(gpui::blue(), 1.),
|
|
)
|
|
.color_space(color_space)),
|
|
)
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
135.,
|
|
linear_color_stop(gpui::red(), 0.),
|
|
linear_color_stop(gpui::green(), 1.),
|
|
)
|
|
.color_space(color_space)),
|
|
)
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
225.,
|
|
linear_color_stop(gpui::green(), 0.),
|
|
linear_color_stop(gpui::blue(), 1.),
|
|
)
|
|
.color_space(color_space)),
|
|
)
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
315.,
|
|
linear_color_stop(gpui::green(), 0.),
|
|
linear_color_stop(gpui::yellow(), 1.),
|
|
)
|
|
.color_space(color_space)),
|
|
),
|
|
)
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.flex_1()
|
|
.gap_3()
|
|
.h_24()
|
|
.text_color(gpui::white())
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
0.,
|
|
linear_color_stop(gpui::red(), 0.),
|
|
linear_color_stop(gpui::white(), 1.),
|
|
)
|
|
.color_space(color_space)),
|
|
)
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
90.,
|
|
linear_color_stop(gpui::blue(), 0.),
|
|
linear_color_stop(gpui::white(), 1.),
|
|
)
|
|
.color_space(color_space)),
|
|
)
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
180.,
|
|
linear_color_stop(gpui::green(), 0.),
|
|
linear_color_stop(gpui::white(), 1.),
|
|
)
|
|
.color_space(color_space)),
|
|
)
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
360.,
|
|
linear_color_stop(gpui::yellow(), 0.),
|
|
linear_color_stop(gpui::white(), 1.),
|
|
)
|
|
.color_space(color_space)),
|
|
),
|
|
)
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
0.,
|
|
linear_color_stop(gpui::green(), 0.05),
|
|
linear_color_stop(gpui::yellow(), 0.95),
|
|
)
|
|
.color_space(color_space)),
|
|
)
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
90.,
|
|
linear_color_stop(gpui::blue(), 0.05),
|
|
linear_color_stop(gpui::red(), 0.95),
|
|
)
|
|
.color_space(color_space)),
|
|
)
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.flex_1()
|
|
.gap_3()
|
|
.child(
|
|
div().flex().flex_1().gap_3().child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
90.,
|
|
linear_color_stop(gpui::blue(), 0.5),
|
|
linear_color_stop(gpui::red(), 0.5),
|
|
)
|
|
.color_space(color_space)),
|
|
),
|
|
)
|
|
.child(
|
|
div().flex_1().rounded_xl().bg(linear_gradient(
|
|
180.,
|
|
linear_color_stop(gpui::green(), 0.),
|
|
linear_color_stop(gpui::blue(), 0.5),
|
|
)
|
|
.color_space(color_space)),
|
|
),
|
|
)
|
|
.child(div().h_24().child(canvas(
|
|
move |_, _| {},
|
|
move |bounds, _, cx| {
|
|
let size = size(bounds.size.width * 0.8, px(80.));
|
|
let square_bounds = Bounds {
|
|
origin: point(
|
|
bounds.size.width.half() - size.width.half(),
|
|
bounds.origin.y,
|
|
),
|
|
size,
|
|
};
|
|
let height = square_bounds.size.height;
|
|
let horizontal_offset = height;
|
|
let vertical_offset = px(30.);
|
|
let mut path = gpui::Path::new(square_bounds.lower_left());
|
|
path.line_to(square_bounds.origin + point(horizontal_offset, vertical_offset));
|
|
path.line_to(
|
|
square_bounds.upper_right() + point(-horizontal_offset, vertical_offset),
|
|
);
|
|
path.line_to(square_bounds.lower_right());
|
|
path.line_to(square_bounds.lower_left());
|
|
cx.paint_path(
|
|
path,
|
|
linear_gradient(
|
|
180.,
|
|
linear_color_stop(gpui::red(), 0.),
|
|
linear_color_stop(gpui::blue(), 1.),
|
|
)
|
|
.color_space(color_space),
|
|
);
|
|
},
|
|
)))
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
App::new().run(|cx: &mut AppContext| {
|
|
cx.open_window(
|
|
WindowOptions {
|
|
focus: true,
|
|
..Default::default()
|
|
},
|
|
|cx| cx.new_view(|_| GradientViewer::new()),
|
|
)
|
|
.unwrap();
|
|
cx.activate(true);
|
|
});
|
|
}
|