1use gpui::{
2 App, Application, Bounds, ColorSpace, Context, Half, Render, Window, WindowOptions, canvas,
3 div, linear_color_stop, linear_gradient, point, prelude::*, px, size,
4};
5
6struct GradientViewer {
7 color_space: ColorSpace,
8}
9
10impl GradientViewer {
11 fn new() -> Self {
12 Self {
13 color_space: ColorSpace::default(),
14 }
15 }
16}
17
18impl Render for GradientViewer {
19 fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
20 let color_space = self.color_space;
21
22 div()
23 .font_family(".SystemUIFont")
24 .bg(gpui::white())
25 .size_full()
26 .p_4()
27 .flex()
28 .flex_col()
29 .gap_3()
30 .child(
31 div()
32 .flex()
33 .gap_2()
34 .justify_between()
35 .items_center()
36 .child("Gradient Examples")
37 .child(
38 div().flex().gap_2().items_center().child(
39 div()
40 .id("method")
41 .flex()
42 .px_3()
43 .py_1()
44 .text_sm()
45 .bg(gpui::black())
46 .text_color(gpui::white())
47 .child(format!("{}", color_space))
48 .active(|this| this.opacity(0.8))
49 .on_click(cx.listener(move |this, _, _, cx| {
50 this.color_space = match this.color_space {
51 ColorSpace::Oklab => ColorSpace::Srgb,
52 ColorSpace::Srgb => ColorSpace::Oklab,
53 };
54 cx.notify();
55 })),
56 ),
57 ),
58 )
59 .child(
60 div()
61 .flex()
62 .flex_1()
63 .gap_3()
64 .child(
65 div()
66 .size_full()
67 .rounded_xl()
68 .flex()
69 .items_center()
70 .justify_center()
71 .bg(gpui::red())
72 .text_color(gpui::white())
73 .child("Solid Color"),
74 )
75 .child(
76 div()
77 .size_full()
78 .rounded_xl()
79 .flex()
80 .items_center()
81 .justify_center()
82 .bg(gpui::blue())
83 .text_color(gpui::white())
84 .child("Solid Color"),
85 ),
86 )
87 .child(
88 div()
89 .flex()
90 .flex_1()
91 .gap_3()
92 .h_24()
93 .text_color(gpui::white())
94 .child(
95 div().flex_1().rounded_xl().bg(linear_gradient(
96 45.,
97 linear_color_stop(gpui::red(), 0.),
98 linear_color_stop(gpui::blue(), 1.),
99 )
100 .color_space(color_space)),
101 )
102 .child(
103 div().flex_1().rounded_xl().bg(linear_gradient(
104 135.,
105 linear_color_stop(gpui::red(), 0.),
106 linear_color_stop(gpui::green(), 1.),
107 )
108 .color_space(color_space)),
109 )
110 .child(
111 div().flex_1().rounded_xl().bg(linear_gradient(
112 225.,
113 linear_color_stop(gpui::green(), 0.),
114 linear_color_stop(gpui::blue(), 1.),
115 )
116 .color_space(color_space)),
117 )
118 .child(
119 div().flex_1().rounded_xl().bg(linear_gradient(
120 315.,
121 linear_color_stop(gpui::green(), 0.),
122 linear_color_stop(gpui::yellow(), 1.),
123 )
124 .color_space(color_space)),
125 ),
126 )
127 .child(
128 div()
129 .flex()
130 .flex_1()
131 .gap_3()
132 .h_24()
133 .text_color(gpui::white())
134 .child(
135 div().flex_1().rounded_xl().bg(linear_gradient(
136 0.,
137 linear_color_stop(gpui::red(), 0.),
138 linear_color_stop(gpui::white(), 1.),
139 )
140 .color_space(color_space)),
141 )
142 .child(
143 div().flex_1().rounded_xl().bg(linear_gradient(
144 90.,
145 linear_color_stop(gpui::blue(), 0.),
146 linear_color_stop(gpui::white(), 1.),
147 )
148 .color_space(color_space)),
149 )
150 .child(
151 div().flex_1().rounded_xl().bg(linear_gradient(
152 180.,
153 linear_color_stop(gpui::green(), 0.),
154 linear_color_stop(gpui::white(), 1.),
155 )
156 .color_space(color_space)),
157 )
158 .child(
159 div().flex_1().rounded_xl().bg(linear_gradient(
160 360.,
161 linear_color_stop(gpui::yellow(), 0.),
162 linear_color_stop(gpui::white(), 1.),
163 )
164 .color_space(color_space)),
165 ),
166 )
167 .child(
168 div().flex_1().rounded_xl().bg(linear_gradient(
169 0.,
170 linear_color_stop(gpui::green(), 0.05),
171 linear_color_stop(gpui::yellow(), 0.95),
172 )
173 .color_space(color_space)),
174 )
175 .child(
176 div().flex_1().rounded_xl().bg(linear_gradient(
177 90.,
178 linear_color_stop(gpui::blue(), 0.05),
179 linear_color_stop(gpui::red(), 0.95),
180 )
181 .color_space(color_space)),
182 )
183 .child(
184 div()
185 .flex()
186 .flex_1()
187 .gap_3()
188 .child(
189 div().flex().flex_1().gap_3().child(
190 div().flex_1().rounded_xl().bg(linear_gradient(
191 90.,
192 linear_color_stop(gpui::blue(), 0.5),
193 linear_color_stop(gpui::red(), 0.5),
194 )
195 .color_space(color_space)),
196 ),
197 )
198 .child(
199 div().flex_1().rounded_xl().bg(linear_gradient(
200 180.,
201 linear_color_stop(gpui::green(), 0.),
202 linear_color_stop(gpui::blue(), 0.5),
203 )
204 .color_space(color_space)),
205 ),
206 )
207 .child(div().h_24().child(canvas(
208 move |_, _, _| {},
209 move |bounds, _, window, _| {
210 let size = size(bounds.size.width * 0.8, px(80.));
211 let square_bounds = Bounds {
212 origin: point(
213 bounds.size.width.half() - size.width.half(),
214 bounds.origin.y,
215 ),
216 size,
217 };
218 let height = square_bounds.size.height;
219 let horizontal_offset = height;
220 let vertical_offset = px(30.);
221 let mut builder = gpui::PathBuilder::fill();
222 builder.move_to(square_bounds.bottom_left());
223 builder
224 .line_to(square_bounds.origin + point(horizontal_offset, vertical_offset));
225 builder.line_to(
226 square_bounds.top_right() + point(-horizontal_offset, vertical_offset),
227 );
228
229 builder.line_to(square_bounds.bottom_right());
230 builder.line_to(square_bounds.bottom_left());
231 let path = builder.build().unwrap();
232 window.paint_path(
233 path,
234 linear_gradient(
235 180.,
236 linear_color_stop(gpui::red(), 0.),
237 linear_color_stop(gpui::blue(), 1.),
238 )
239 .color_space(color_space),
240 );
241 },
242 )))
243 }
244}
245
246fn main() {
247 Application::new().run(|cx: &mut App| {
248 cx.open_window(
249 WindowOptions {
250 focus: true,
251 ..Default::default()
252 },
253 |_, cx| cx.new(|_| GradientViewer::new()),
254 )
255 .unwrap();
256 cx.activate(true);
257 });
258}