1#![allow(non_snake_case)]
2use std::sync::Arc;
3
4use repose_core::*;
5use repose_ui::*;
6
7pub struct DrawScope {
8 pub commands: Vec<DrawCommand>,
9 pub size: Size,
10}
11
12#[derive(Clone)]
13pub enum DrawCommand {
14 Rect {
15 rect: Rect,
16 color: Color,
17 radius: f32,
18 stroke: Option<(f32, Color)>,
19 },
20 Ellipse {
21 center: Vec2,
22 rx: f32,
23 ry: f32,
24 color: Color,
25 stroke: Option<(f32, Color)>,
26 },
27 Text {
28 text: String,
29 pos: Vec2,
30 color: Color,
31 size: f32,
32 },
33}
34
35impl DrawScope {
36 pub fn draw_rect(&mut self, rect: Rect, color: Color, radius: f32) {
37 self.commands.push(DrawCommand::Rect {
38 rect,
39 color,
40 radius,
41 stroke: None,
42 });
43 }
44 pub fn draw_rect_stroke(&mut self, rect: Rect, color: Color, radius: f32, width: f32) {
45 self.commands.push(DrawCommand::Rect {
46 rect,
47 color,
48 radius,
49 stroke: Some((width, color)),
50 });
51 }
52 pub fn draw_ellipse(&mut self, center: Vec2, rx: f32, ry: f32, color: Color) {
53 self.commands.push(DrawCommand::Ellipse {
54 center,
55 rx: rx.max(0.0),
56 ry: ry.max(0.0),
57 color,
58 stroke: None,
59 });
60 }
61 pub fn draw_ellipse_stroke(
62 &mut self,
63 center: Vec2,
64 rx: f32,
65 ry: f32,
66 color: Color,
67 width: f32,
68 ) {
69 self.commands.push(DrawCommand::Ellipse {
70 center,
71 rx: rx.max(0.0),
72 ry: ry.max(0.0),
73 color,
74 stroke: Some((width.max(0.0), color)),
75 });
76 }
77 pub fn draw_circle(&mut self, center: Vec2, radius: f32, color: Color) {
78 self.draw_ellipse(center, radius, radius, color);
79 }
80 pub fn draw_circle_stroke(&mut self, center: Vec2, radius: f32, color: Color, width: f32) {
81 self.draw_ellipse_stroke(center, radius, radius, color, width);
82 }
83 pub fn draw_text(&mut self, text: impl Into<String>, pos: Vec2, color: Color, size: f32) {
84 self.commands.push(DrawCommand::Text {
85 text: text.into(),
86 pos,
87 color,
88 size,
89 });
90 }
91}
92
93pub fn Canvas(modifier: Modifier, on_draw: impl Fn(&mut DrawScope) + 'static) -> View {
94 let painter = move |scene: &mut Scene, rect: Rect| {
96 let mut scope = DrawScope {
97 commands: Vec::new(),
98 size: Size {
99 width: rect.w.max(0.0),
100 height: rect.h.max(0.0),
101 },
102 };
103 on_draw(&mut scope);
104
105 let to_global = |r: Rect| Rect {
107 x: rect.x + r.x,
108 y: rect.y + r.y,
109 w: r.w,
110 h: r.h,
111 };
112
113 for cmd in &scope.commands {
114 match cmd {
115 DrawCommand::Rect {
116 rect: r,
117 color,
118 radius,
119 stroke,
120 } => {
121 scene.nodes.push(SceneNode::Rect {
122 rect: to_global(*r),
123 brush: Brush::Solid(*color),
124 radius: *radius,
125 });
126 if let Some((w, c)) = stroke {
127 scene.nodes.push(SceneNode::Border {
128 rect: to_global(*r),
129 color: *c,
130 width: *w,
131 radius: *radius,
132 });
133 }
134 }
135 DrawCommand::Ellipse {
136 center,
137 rx,
138 ry,
139 color,
140 stroke,
141 } => {
142 let r = Rect {
143 x: center.x - *rx,
144 y: center.y - *ry,
145 w: 2.0 * *rx,
146 h: 2.0 * *ry,
147 };
148 scene.nodes.push(SceneNode::Ellipse {
149 rect: to_global(r),
150 brush: Brush::Solid(*color),
151 });
152 if let Some((w, c)) = stroke {
153 scene.nodes.push(SceneNode::EllipseBorder {
154 rect: to_global(r),
155 color: *c,
156 width: *w,
157 });
158 }
159 }
160 DrawCommand::Text {
161 text,
162 pos,
163 color,
164 size,
165 } => {
166 scene.nodes.push(SceneNode::Text {
167 rect: Rect {
168 x: rect.x + pos.x,
169 y: rect.y + pos.y,
170 w: 0.0,
171 h: *size,
172 },
173 text: Arc::<str>::from(text.clone()),
174 color: *color,
175 size: *size,
176 });
177 }
178 }
179 }
180 };
181
182 let mut m = modifier.painter(painter);
184 let has_size = m.size.is_some()
185 || m.width.is_some()
186 || m.height.is_some()
187 || m.fill_max
188 || m.fill_max_w
189 || m.fill_max_h;
190 if !has_size {
191 m = m.size(100.0, 100.0);
192 }
193
194 Box(m)
195}