1use gpui::{
2 AbsoluteLength, App, Application, Context, CornersRefinement, DefiniteLength, Div, Fill,
3 Length, SharedString, SizeRefinement, StyleRefinement, WeakEntity, Window, WindowOptions, div,
4 prelude::*, px, rgb,
5};
6use gpui_qrcode::QrCode;
7
8struct SimpleExample {
9 inner: QrCode,
10 dot_style: StyleRefinement,
11}
12
13impl SimpleExample {
14 fn new(inner: QrCode) -> Self {
15 Self {
16 inner,
17 dot_style: StyleRefinement {
18 background: Some(Fill::from(gpui::black())),
19 ..Default::default()
20 },
21 }
22 }
23
24 fn render_dot_colors(me: WeakEntity<Self>) -> Div {
25 div()
26 .flex()
27 .gap_2()
28 .child(SharedString::new("Color: "))
29 .children(
30 [
31 gpui::red(),
32 gpui::green(),
33 gpui::blue(),
34 gpui::yellow(),
35 gpui::black(),
36 ]
37 .into_iter()
38 .enumerate()
39 .map(|(index, color)| {
40 let me = me.clone();
41 div()
42 .id(SharedString::new(format!("color-{index}")))
43 .size_8()
44 .bg(color.clone())
45 .on_click(move |_ev, _win, cx| {
46 let _ = me.update(cx, |this, cx| {
47 this.dot_style.background = Some(Fill::from(color));
48 cx.notify()
49 });
50 })
51 }),
52 )
53 }
54
55 fn render_dot_sizes(me: WeakEntity<Self>) -> Div {
56 div()
57 .flex()
58 .gap_2()
59 .child(SharedString::new("Dot Size: "))
60 .children([0.25f32, 0.5f32, 1f32, 2f32].into_iter().map(|size| {
61 let me = me.clone();
62 div()
63 .id(SharedString::new(format!("size-{size}")))
64 .child(SharedString::new(format!("{size}rem")))
65 .on_click(move |_ev, _win, cx| {
66 let _ = me.update(cx, |this, cx| {
67 this.dot_style.size = SizeRefinement {
68 width: Some(Length::Definite(DefiniteLength::Absolute(
69 AbsoluteLength::Rems(gpui::Rems(size)),
70 ))),
71 height: Some(Length::Definite(DefiniteLength::Absolute(
72 AbsoluteLength::Rems(gpui::Rems(size)),
73 ))),
74 };
75 cx.notify();
76 });
77 })
78 }))
79 }
80
81 fn render_pad_sizes(me: WeakEntity<Self>) -> Div {
82 div()
83 .flex()
84 .gap_2()
85 .child(SharedString::new("Padding: "))
86 .children([0.25f32, 0.5f32, 1f32, 2f32].into_iter().map(|size| {
87 let me = me.clone();
88 div()
89 .id(SharedString::new(format!("padding-size-{size}")))
90 .child(SharedString::new(format!("{size}rem")))
91 .on_click(move |_ev, _win, cx| {
92 let _ = me.update(cx, |this, cx| {
93 this.inner = this.inner.clone().p(DefiniteLength::Absolute(
94 AbsoluteLength::Rems(gpui::Rems(size)),
95 ));
96 cx.notify();
97 });
98 })
99 }))
100 }
101
102 fn render_dot_style(me: WeakEntity<Self>) -> Div {
103 div()
104 .flex()
105 .gap_2()
106 .child(SharedString::new("Dot Style: "))
107 .children(
108 [
109 StyleRefinement {
110 corner_radii: CornersRefinement {
111 top_left: Some(AbsoluteLength::Pixels(px(10.0))),
112 top_right: Some(AbsoluteLength::Pixels(px(10.0))),
113 bottom_left: Some(AbsoluteLength::Pixels(px(10.0))),
114 bottom_right: Some(AbsoluteLength::Pixels(px(10.0))),
115 },
116 ..Default::default()
117 },
118 StyleRefinement {
119 corner_radii: CornersRefinement {
120 top_left: Some(AbsoluteLength::Pixels(px(10.0))),
121 top_right: Some(AbsoluteLength::Pixels(px(10.0))),
122 bottom_left: Some(AbsoluteLength::Pixels(px(10.0))),
123 bottom_right: Some(AbsoluteLength::Pixels(px(0.0))),
124 },
125 ..Default::default()
126 },
127 StyleRefinement {
128 corner_radii: CornersRefinement {
129 top_left: Some(AbsoluteLength::Pixels(px(0.0))),
130 top_right: Some(AbsoluteLength::Pixels(px(10.0))),
131 bottom_left: Some(AbsoluteLength::Pixels(px(10.0))),
132 bottom_right: Some(AbsoluteLength::Pixels(px(10.0))),
133 },
134 ..Default::default()
135 },
136 ]
137 .into_iter()
138 .enumerate()
139 .map(|(index, style)| {
140 let me = me.clone();
141 let mut d = div()
142 .id(SharedString::new(format!("style-{index}")))
143 .bg(gpui::black())
144 .size_5();
145
146 d.style().refine(&style);
147 d.on_click(move |_ev, _win, cx| {
148 let _ = me.update(cx, |this, cx| {
149 this.dot_style.refine(&style);
150 cx.notify();
151 });
152 })
153 }),
154 )
155 }
156
157 fn render_actions(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
158 let me = cx.entity().downgrade();
159 div()
160 .flex()
161 .flex_col()
162 .items_center()
163 .child(SharedString::new("Configuration"))
164 .child(Self::render_dot_colors(me.clone()))
165 .child(Self::render_dot_sizes(me.clone()))
166 .child(Self::render_dot_style(me.clone()))
167 .child(Self::render_pad_sizes(me.clone()))
168 }
170}
171
172impl Render for SimpleExample {
173 fn render(&mut self, win: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
174 div()
175 .flex()
176 .flex_col()
177 .gap_3()
178 .bg(rgb(0x505050))
179 .size_full()
180 .content_stretch()
181 .justify_center()
182 .items_center()
183 .text_xl()
184 .text_color(rgb(0xffffff))
185 .child(self.inner.clone().refine_dot_style(&self.dot_style))
186 .child(self.render_actions(win, cx))
187 }
188}
189
190fn main() {
191 Application::new().run(|cx: &mut App| {
192 cx.open_window(
193 WindowOptions {
194 ..Default::default()
195 },
196 |_, cx| {
197 let q =
198 QrCode::try_from(qrcode::QrCode::new("https://hellozoe.app").unwrap()).unwrap();
199 cx.new(|_| SimpleExample::new(q))
200 },
201 )
202 .unwrap();
203 });
204}