use rust_format::{Config, Edition, Formatter, RustFmt}; use crate::{ types::{ project::Project, rendered_element::{container, row, svg, text, RenderedElement}, ElementName, }, Error, }; impl RenderedElement { fn props_codegen(&self) -> String { let mut props_string = String::new(); for (k, v) in self.props.clone() { if let Some(v) = v { props_string = format!("{props_string}.{k}({v})"); } } props_string } fn codegen(&self) -> (String, String) { let mut imports = String::new(); let mut view = String::new(); let props = self.props_codegen(); let mut elements = String::new(); if let Some(els) = &self.child_elements { for element in els { let (c_imports, children) = element.codegen(); imports = format!("{imports}{c_imports}"); elements = format!("{elements}{},", children); } } match &self.name { ElementName::Container => { imports = format!("{imports}container,"); view = format!("{view}\ncontainer({elements}){props}"); } ElementName::Row => { imports = format!("{imports}row,"); view = format!("{view}\nrow![{elements}]{props}"); } ElementName::Column => { imports = format!("{imports}column,"); view = format!("{view}\ncolumn![{elements}]{props}"); } ElementName::Text(string) => { imports = format!("{imports}text,"); view = format!( "{view}\ntext(\"{}\"){props}", if *string == String::new() { "New Text" } else { string } ); } ElementName::Button(string) => { imports = format!("{imports}button,"); view = format!( "{view}\nbutton(\"{}\"){props}", if *string == String::new() { "New Button" } else { string } ); } ElementName::Image(path) => { imports = format!("{imports}image,"); view = format!("{view}\nimage(\"{path}\"){props}"); } ElementName::SVG(path) => { imports = format!("{imports}svg,"); view = format!("{view}\nsvg(\"{path}\"){props}"); } } (imports, view) } pub fn test() -> RenderedElement { let mut text1 = text("wow"); text1.option("height", "120.5"); text1.option("width", "230"); let element = container(Some(row(Some(vec![ text1, text("heh"), svg("/mnt/drive_d/git/obs-website/src/lib/assets/bars-solid.svg"), ])))); element } } impl Project { pub fn app_code(self) -> Result { match &self.content { Some(el) => { let (imports, view) = el.codegen(); let mut app_code = format!("use iced::{{widget::{{{imports}}},Element}};"); app_code = format!( r#"// Automatically generated by iced Builder {app_code} fn main() -> iced::Result {{ iced::run("{}", State::update, State::view) }} #[derive(Default)] struct State; #[derive(Debug, Clone)] enum Message {{}} impl State {{ fn update(&mut self, _message: Message) {{}} fn view(&self) -> Element {{ {view}.into() }} }}"#, match &self.title { Some(t) => t, None => "New app", } ); let config = Config::new_str() .edition(Edition::Rust2021) .option("trailing_comma", "Never") .option("imports_granularity", "Crate"); let rustfmt = RustFmt::from_config(config); Ok(rustfmt.format_str(app_code)?) } None => Err("No element tree present".into()), } } }