-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gpui: Add linear gradient support to fill background (#20812)
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.
- Loading branch information
Showing
9 changed files
with
899 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
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); | ||
}); | ||
} |
Oops, something went wrong.