1use crate::{components::Component, style::Style};
6
7pub struct Renderer {
9 backend: Box<dyn RenderBackend>,
11}
12
13pub trait RenderBackend {
15 fn initialize(&mut self) -> Result<(), Box<dyn std::error::Error>>;
17
18 fn cleanup(&mut self);
20
21 fn begin_frame(&mut self);
23
24 fn end_frame(&mut self);
26
27 fn render_component(&mut self, component: &Component, x: f32, y: f32, width: f32, height: f32);
29
30 fn draw_rect(&mut self, x: f32, y: f32, width: f32, height: f32, style: &Style);
32
33 fn draw_text(&mut self, text: &str, x: f32, y: f32, style: &Style);
35
36 fn measure_text(&mut self, text: &str, style: &Style) -> (f32, f32);
38}
39
40impl Renderer {
41 pub fn new(backend: Box<dyn RenderBackend>) -> Self {
49 Self { backend }
50 }
51
52 pub fn initialize(&mut self) -> Result<(), Box<dyn std::error::Error>> {
57 self.backend.initialize()
58 }
59
60 pub fn cleanup(&mut self) {
62 self.backend.cleanup();
63 }
64
65 pub fn begin_frame(&mut self) {
67 self.backend.begin_frame();
68 }
69
70 pub fn end_frame(&mut self) {
72 self.backend.end_frame();
73 }
74
75 pub fn render(&mut self, root: &Component, width: f32, height: f32) {
82 self.begin_frame();
83 self.render_component_recursive(root, 0.0, 0.0, width, height);
84 self.end_frame();
85 }
86
87 fn render_component_recursive(&mut self, component: &Component, x: f32, y: f32, width: f32, height: f32) {
96 if !component.properties().visible {
97 return;
98 }
99
100 self.backend.render_component(component, x, y, width, height);
102
103 for child in component.children() {
105 let child_y = y + 50.0; self.render_component_recursive(child, x + 20.0, child_y, width - 40.0, 40.0);
109 }
110 }
111}
112
113#[derive(Debug)]
115pub struct ExampleRenderBackend {
116 initialized: bool,
118}
119
120impl ExampleRenderBackend {
121 pub fn new() -> Self {
126 Self { initialized: false }
127 }
128}
129
130impl RenderBackend for ExampleRenderBackend {
131 fn initialize(&mut self) -> Result<(), Box<dyn std::error::Error>> {
132 println!("Initializing example render backend");
133 self.initialized = true;
134 Ok(())
135 }
136
137 fn cleanup(&mut self) {
138 println!("Cleaning up example render backend");
139 self.initialized = false;
140 }
141
142 fn begin_frame(&mut self) {
143 println!("Beginning render frame");
144 }
145
146 fn end_frame(&mut self) {
147 println!("Ending render frame");
148 }
149
150 fn render_component(&mut self, component: &Component, x: f32, y: f32, width: f32, height: f32) {
151 println!("Rendering component {} at ({}, {}, {}, {})", component.id(), x, y, width, height);
152 }
154
155 fn draw_rect(&mut self, x: f32, y: f32, width: f32, height: f32, _style: &Style) {
156 println!("Drawing rect at ({}, {}, {}, {})", x, y, width, height);
157 }
159
160 fn draw_text(&mut self, text: &str, x: f32, y: f32, _style: &Style) {
161 println!("Drawing text '{}' at ({}, {})", text, x, y);
162 }
164
165 fn measure_text(&mut self, text: &str, _style: &Style) -> (f32, f32) {
166 (text.len() as f32 * 8.0, 16.0)
168 }
169}