diff options
| author | Polesznyák Márk László <116908301+pml68@users.noreply.github.com> | 2024-09-22 21:32:38 +0200 |
|---|---|---|
| committer | pml68 <contact@pml68.me> | 2024-09-22 23:55:11 +0200 |
| commit | 0e1e21ad18dcf48e64422f7f45af44ac5ea4a7be (patch) | |
| tree | 2fe99dcb6380deb067e3bc3005fb5275f33b48d5 /src/codegen/mod.rs | |
| parent | feat: add usable state logic (diff) | |
| parent | feat: add "Copy to clipboard" button for code view (diff) | |
| download | iced-builder-0e1e21ad18dcf48e64422f7f45af44ac5ea4a7be.tar.gz | |
Merge pull request #1 from pml68/feat/codegen
Codegen done
Diffstat (limited to 'src/codegen/mod.rs')
| -rw-r--r-- | src/codegen/mod.rs | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs new file mode 100644 index 0000000..2dd9cff --- /dev/null +++ b/src/codegen/mod.rs @@ -0,0 +1,160 @@ +use std::path::PathBuf; + +use rust_format::{Config, Edition, Formatter, RustFmt}; + +use crate::types::{rendered_element::RenderedElement, ElementName}; + +impl RenderedElement { + fn props_codegen(&self) -> String { + let mut props_string = String::new(); + + for (k, v) in self.props.clone() { + 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(); + + match self.name { + ElementName::Column | ElementName::Row | ElementName::Container => { + for element in &self.child_elements { + 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 = if self.child_elements.len() < 2 { + format!("{view}\ncontainer({elements}){props}") + } else { + format!("{view}\ncontainer(){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(\"{}\"){props}", path.display().to_string()); + } + ElementName::SVG(path) => { + imports = format!("{imports}svg,"); + view = format!("{view}\nsvg(\"{}\"){props}", path.display().to_string()); + } + } + + (imports, view) + } + + pub fn app_code( + &self, + title: &str, + theme: Option<iced::Theme>, + ) -> Result<String, Box<dyn std::error::Error>> { + let (imports, view) = self.codegen(); + let mut app_code = format!("use iced::{{widget::{{{imports}}},Sandbox,Settings,Element}};"); + + app_code = format!( + r#"{app_code} + + fn main() -> iced::Result {{ + App::run(Settings::default()) + }} + + struct App; + + impl Sandbox for App {{ + type Message = (); + + fn new() -> Self {{ + Self {{}} + }} + + fn title(&self) -> String {{ + "{title}".into() + }} + + fn theme(&self) -> iced::Theme {{ + iced::Theme::{} + }} + + fn update(&mut self, message: Self::Message) {{ + + }} + + fn view(&self) -> Element<Self::Message> {{ + {view}.into() + }} + }}"#, + if let Some(c) = theme { + c.to_string().replace(' ', "") + } else { + "default()".to_owned() + } + ); + 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)?) + } + + pub fn test() -> String { + let mut text1 = RenderedElement::new(ElementName::Text("wow")); + text1.set_property("height", "120.5"); + text1.set_property("width", "230"); + + let element = RenderedElement::new(ElementName::Container).push(RenderedElement::from_vec( + ElementName::Row, + vec![ + text1, + RenderedElement::new(ElementName::Text("heh")), + RenderedElement::new(ElementName::SVG(PathBuf::from( + "/mnt/drive_d/git/obs-website/src/lib/assets/bars-solid.svg", + ))), + ], + )); + + element.app_code("new app", None).unwrap() + } +} |
