1use crate::components::component::ComponentSpecification;
2use crate::components::Props;
3use crate::elements::element::Element;
4use crate::elements::element_data::ElementData;
5use crate::elements::element_styles::ElementStyles;
6use crate::layout::layout_context::LayoutContext;
7use crate::geometry::{Point, Rectangle};
8use crate::reactive::element_state_store::ElementStateStore;
9use crate::renderer::renderer::RenderList;
10use crate::renderer::RenderCommand;
11use crate::style::Style;
12use crate::Color;
13use crate::generate_component_methods_no_children;
14use std::any::Any;
15use std::sync::Arc;
16use taffy::{NodeId, TaffyTree};
17use winit::window::Window;
18use crate::text::text_context::TextContext;
19
20#[derive(Clone, Default, Debug)]
21pub struct Canvas {
22 pub element_data: ElementData,
23 pub render_list: Vec<RenderCommand>,
24}
25
26#[derive(Clone, Copy, Default)]
27pub struct CanvasState {}
28
29impl Element for Canvas {
30 fn element_data(&self) -> &ElementData {
31 &self.element_data
32 }
33
34 fn element_data_mut(&mut self) -> &mut ElementData {
35 &mut self.element_data
36 }
37
38 fn name(&self) -> &'static str {
39 "Canvas"
40 }
41
42 fn draw(
43 &mut self,
44 renderer: &mut RenderList,
45 _text_context: &mut TextContext,
46 _taffy_tree: &mut TaffyTree<LayoutContext>,
47 _root_node: NodeId,
48 element_state: &mut ElementStateStore,
49 _pointer: Option<Point>,
50 _window: Option<Arc<dyn Window>>,
51 ) {
52 if !self.element_data.style.visible() {
53 return;
54 }
55 let _border_color: Color = self.style().border_color().top;
56 let computed_box_transformed = self.element_data.computed_box_transformed;
57 let _border_rectangle = computed_box_transformed.border_rectangle();
58 let _content_rectangle = computed_box_transformed.content_rectangle();
59
60 let computed_x_transformed = self.element_data.computed_box_transformed.position.x;
62 let computed_y_transformed = self.element_data.computed_box_transformed.position.y;
63
64 let computed_width = self.element_data.computed_box_transformed.size.width;
65 let computed_height = self.element_data.computed_box_transformed.size.height;
66
67 let border_top = self.element_data.computed_box_transformed.border.top;
68 let border_right = self.element_data.computed_box_transformed.border.right;
69 let border_bottom = self.element_data.computed_box_transformed.border.bottom;
70 let border_left = self.element_data.computed_box_transformed.border.left;
71
72 self.draw_borders(renderer, element_state);
73
74 renderer.push_layer(Rectangle::new(
75 computed_x_transformed + border_left,
76 computed_y_transformed + border_top,
77 computed_width - (border_right + border_left),
78 computed_height - (border_top + border_bottom),
79 ));
80
81 for render_command in self.render_list.iter() {
82 match render_command {
83 RenderCommand::DrawRect(rectangle, color) => {
84 let translated_rectangle = Rectangle::new(
85 rectangle.x + computed_x_transformed,
86 rectangle.y + computed_y_transformed,
87 rectangle.width,
88 rectangle.height,
89 );
90 renderer.draw_rect(translated_rectangle, *color);
91 }
92 RenderCommand::DrawRectOutline(rectangle, color) => {
93 let translated_rectangle = Rectangle::new(
94 rectangle.x + computed_x_transformed,
95 rectangle.y + computed_y_transformed,
96 rectangle.width,
97 rectangle.height,
98 );
99 renderer.draw_rect_outline(translated_rectangle, *color);
100 }
101 RenderCommand::DrawImage(rectangle, resource_identifier) => {
102 let translated_rectangle = Rectangle::new(
103 rectangle.x + computed_x_transformed,
104 rectangle.y + computed_y_transformed,
105 rectangle.width,
106 rectangle.height,
107 );
108 renderer.draw_image(translated_rectangle, resource_identifier.clone());
109 }
110 RenderCommand::DrawText(text_renderer, rectangle, text_scroll, show_cursor,) => {
111 let translated_rectangle = Rectangle::new(
112 rectangle.x + computed_x_transformed,
113 rectangle.y + computed_y_transformed,
114 rectangle.width,
115 rectangle.height,
116 );
117 renderer.draw_text(text_renderer.clone(), translated_rectangle, *text_scroll, *show_cursor);
118 }
119 RenderCommand::PushLayer(rectangle) => {
120 let translated_rectangle = Rectangle::new(
121 rectangle.x + computed_x_transformed,
122 rectangle.y + computed_y_transformed,
123 rectangle.width,
124 rectangle.height,
125 );
126 renderer.push_layer(translated_rectangle);
127 }
128 RenderCommand::PopLayer => {
129 renderer.pop_layer();
130 }
131 RenderCommand::FillBezPath(path, brush) => {
132 renderer.fill_bez_path(path.clone(), brush.clone());
133 }
134 RenderCommand::DrawTinyVg(rectangle, resource_identifier, color) => {
135 renderer.draw_tiny_vg(*rectangle, resource_identifier.clone(), *color);
136 }
137 RenderCommand::StartOverlay => {
138 renderer.start_overlay();
139 }
140 RenderCommand::EndOverlay => {
141 renderer.end_overlay();
142 }
143 }
144 }
145
146 renderer.pop_layer();
147 }
148
149 fn compute_layout(
150 &mut self,
151 taffy_tree: &mut TaffyTree<LayoutContext>,
152 element_state: &mut ElementStateStore,
153 scale_factor: f64,
154 ) -> Option<NodeId> {
155 self.merge_default_style();
156 let mut child_nodes: Vec<NodeId> = Vec::with_capacity(self.children().len());
157
158 for child in self.element_data.children.iter_mut() {
159 let child_node = child.internal.compute_layout(taffy_tree, element_state, scale_factor);
160 if let Some(child_node) = child_node {
161 child_nodes.push(child_node);
162 }
163 }
164
165 let style: taffy::Style = self.element_data.style.to_taffy_style_with_scale_factor(scale_factor);
166
167 self.element_data_mut().taffy_node_id = Some(taffy_tree.new_with_children(style, &child_nodes).unwrap());
168 self.element_data().taffy_node_id
169 }
170
171 fn finalize_layout(
172 &mut self,
173 taffy_tree: &mut TaffyTree<LayoutContext>,
174 root_node: NodeId,
175 position: Point,
176 z_index: &mut u32,
177 transform: glam::Mat4,
178 element_state: &mut ElementStateStore,
179 pointer: Option<Point>,
180 text_context: &mut TextContext,
181 ) {
182 let result = taffy_tree.layout(root_node).unwrap();
183 self.resolve_box(position, transform, result, z_index);
184 self.finalize_borders(element_state);
185
186 for child in self.element_data.children.iter_mut() {
187 let taffy_child_node_id = child.internal.taffy_node_id();
188 if taffy_child_node_id.is_none() {
189 continue;
190 }
191
192 child.internal.finalize_layout(
193 taffy_tree,
194 taffy_child_node_id.unwrap(),
195 self.element_data.computed_box.position,
196 z_index,
197 transform,
198 element_state,
199 pointer,
200 text_context,
201 );
202 }
203 }
204
205 fn as_any(&self) -> &dyn Any {
206 self
207 }
208}
209
210impl Canvas {
211 #[allow(dead_code)]
212 fn get_state<'a>(&self, element_state: &'a ElementStateStore) -> &'a CanvasState {
213 element_state.storage.get(&self.element_data.component_id).unwrap().data.as_ref().downcast_ref().unwrap()
214 }
215
216 #[allow(dead_code)]
217 fn get_state_mut<'a>(&self, element_state: &'a mut ElementStateStore) -> &'a mut CanvasState {
218 element_state.storage.get_mut(&self.element_data.component_id).unwrap().data.as_mut().downcast_mut().unwrap()
219 }
220
221 pub fn new() -> Canvas {
222 Canvas {
223 element_data: Default::default(),
224 render_list: Vec::new(),
225 }
226 }
227
228 generate_component_methods_no_children!();
229}
230
231impl ElementStyles for Canvas {
232 fn styles_mut(&mut self) -> &mut Style {
233 self.element_data.current_style_mut()
234 }
235}