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