summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpml68 <contact@pml68.me>2024-09-22 23:53:02 +0200
committerpml68 <contact@pml68.me>2024-09-23 00:00:45 +0200
commitf5c35e48c480355036778d26aacde498e5c15e68 (patch)
treebf949b406bd8f0719f06095bb14bf9872a7493e5 /src
parentMerge pull request #1 from pml68/feat/codegen (diff)
downloadiced-builder-f5c35e48c480355036778d26aacde498e5c15e68.tar.gz
feat: restructure project, start drag and drop
Diffstat (limited to 'src')
-rw-r--r--src/codegen/mod.rs160
-rw-r--r--src/lib.rs0
-rw-r--r--src/main.rs301
-rw-r--r--src/types/mod.rs25
-rw-r--r--src/types/rendered_element.rs47
5 files changed, 0 insertions, 533 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
deleted file mode 100644
index 2dd9cff..0000000
--- a/src/codegen/mod.rs
+++ /dev/null
@@ -1,160 +0,0 @@
-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()
- }
-}
diff --git a/src/lib.rs b/src/lib.rs
deleted file mode 100644
index e69de29..0000000
--- a/src/lib.rs
+++ /dev/null
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index d3fafc6..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,301 +0,0 @@
-mod codegen;
-mod types;
-
-use iced::{
- clipboard, executor,
- highlighter::{self, Highlighter},
- theme,
- widget::{
- button, column, container,
- pane_grid::{self, Pane, PaneGrid},
- row, text, text_editor, tooltip, Column, Space,
- },
- Alignment, Application, Color, Command, Element, Font, Length, Settings,
-};
-use types::{rendered_element::RenderedElement, DesignerPage, DesignerState};
-
-fn main() -> iced::Result {
- App::run(Settings {
- fonts: vec![include_bytes!("../fonts/icons.ttf").as_slice().into()],
- ..Settings::default()
- })
-}
-
-struct App {
- is_saved: bool,
- current_project: Option<String>,
- dark_theme: bool,
- pane_state: pane_grid::State<Panes>,
- focus: Option<Pane>,
- designer_state: DesignerState,
- element_list: Vec<String>,
- editor_content: text_editor::Content,
-}
-
-#[derive(Debug, Clone)]
-enum Message {
- ToggleTheme,
- CopyCode,
- Resized(pane_grid::ResizeEvent),
- Clicked(pane_grid::Pane),
-}
-
-#[derive(Clone, Debug)]
-enum Panes {
- Designer,
- ElementList,
-}
-
-impl Application for App {
- type Message = Message;
- type Theme = theme::Theme;
- type Executor = executor::Default;
- type Flags = ();
-
- fn new(_flags: ()) -> (Self, Command<Message>) {
- let state = pane_grid::State::with_configuration(pane_grid::Configuration::Split {
- axis: pane_grid::Axis::Vertical,
- ratio: 0.8,
- a: Box::new(pane_grid::Configuration::Pane(Panes::Designer)),
- b: Box::new(pane_grid::Configuration::Pane(Panes::ElementList)),
- });
- (
- Self {
- is_saved: true,
- current_project: None,
- dark_theme: true,
- pane_state: state,
- focus: None,
- designer_state: DesignerState {
- designer_content: vec![],
- designer_page: DesignerPage::CodeView,
- },
- element_list: vec!["Column", "Row", "PickList", "PaneGrid", "Button", "Text"]
- .into_iter()
- .map(|c| c.to_owned())
- .collect(),
- editor_content: text_editor::Content::with_text(&RenderedElement::test()),
- },
- Command::none(),
- )
- }
-
- fn title(&self) -> String {
- let saved_state = if self.is_saved { "" } else { " *" };
-
- let project_name = match &self.current_project {
- Some(n) => format!(" - {n}"),
- None => "".to_owned(),
- };
-
- format!("iced Builder{project_name}{saved_state}")
- }
-
- fn theme(&self) -> iced::Theme {
- if self.dark_theme {
- theme::Theme::CatppuccinMocha
- } else {
- theme::Theme::CatppuccinLatte
- }
- }
-
- fn update(&mut self, message: Message) -> Command<Message> {
- match message {
- Message::ToggleTheme => self.dark_theme = !self.dark_theme,
- Message::CopyCode => return clipboard::write(self.editor_content.text()),
- Message::Resized(pane_grid::ResizeEvent { split, ratio }) => {
- self.pane_state.resize(split, ratio);
- }
- Message::Clicked(pane) => {
- self.focus = Some(pane);
- }
- }
-
- Command::none()
- }
-
- fn view(&self) -> Element<Message> {
- let header = row![button("Toggle Theme")
- .on_press(Message::ToggleTheme)
- .padding(5)]
- .width(200);
- let pane_grid = PaneGrid::new(&self.pane_state, |id, pane, _is_maximized| {
- let is_focused = Some(id) == self.focus;
- match pane {
- Panes::Designer => match self.designer_state.designer_page {
- DesignerPage::Designer => {
- let content = column![text("Designer"),]
- .align_items(Alignment::Center)
- .height(Length::Fill)
- .width(Length::Fill);
- let title = text("Designer").style(if is_focused {
- PANE_ID_COLOR_FOCUSED
- } else {
- PANE_ID_COLOR_UNFOCUSED
- });
- let title_bar = pane_grid::TitleBar::new(title)
- .padding(10)
- .style(style::title_bar);
- pane_grid::Content::new(content)
- .title_bar(title_bar)
- .style(if is_focused {
- style::pane_focused
- } else {
- style::pane_active
- })
- }
- DesignerPage::CodeView => {
- let title = row![
- text("Generated Code").style(if is_focused {
- PANE_ID_COLOR_FOCUSED
- } else {
- PANE_ID_COLOR_UNFOCUSED
- }),
- Space::with_width(Length::Fill),
- tooltip(
- button(
- container(
- text('\u{0e801}').font(Font::with_name("editor-icons"))
- )
- .width(30)
- .center_x()
- )
- .on_press(Message::CopyCode),
- "Copy code to clipboard",
- tooltip::Position::Left
- )
- ];
- let title_bar = pane_grid::TitleBar::new(title)
- .padding(10)
- .style(style::title_bar);
- pane_grid::Content::new(
- text_editor(&self.editor_content)
- .highlight::<Highlighter>(
- highlighter::Settings {
- theme: highlighter::Theme::Base16Mocha,
- extension: "rs".to_string(),
- },
- |highlight, _theme| highlight.to_format(),
- )
- .height(Length::Fill)
- .padding(20),
- )
- .title_bar(title_bar)
- .style(if is_focused {
- style::pane_focused
- } else {
- style::pane_active
- })
- }
- },
- Panes::ElementList => {
- let items_list = items_list_view(&self.element_list);
- let content = column![items_list]
- .align_items(Alignment::Center)
- .height(Length::Fill)
- .width(Length::Fill);
- let title = text("Element List").style(if is_focused {
- PANE_ID_COLOR_FOCUSED
- } else {
- PANE_ID_COLOR_UNFOCUSED
- });
- let title_bar = pane_grid::TitleBar::new(title)
- .padding(10)
- .style(style::title_bar);
- pane_grid::Content::new(content)
- .title_bar(title_bar)
- .style(if is_focused {
- style::pane_focused
- } else {
- style::pane_active
- })
- }
- }
- })
- .width(Length::Fill)
- .height(Length::Fill)
- .spacing(10)
- .on_resize(10, Message::Resized)
- .on_click(Message::Clicked);
-
- let content = Column::new()
- .push(header)
- .push(pane_grid)
- .spacing(5)
- .align_items(Alignment::Center)
- .width(Length::Fill);
-
- container(content).height(Length::Fill).into()
- }
-}
-
-const fn from_grayscale(grayscale: f32) -> Color {
- Color {
- r: grayscale,
- g: grayscale,
- b: grayscale,
- a: 1.0,
- }
-}
-
-// #ffffff
-const PANE_ID_COLOR_FOCUSED: Color = from_grayscale(1.0);
-
-// #e8e8e8
-const PANE_ID_COLOR_UNFOCUSED: Color = from_grayscale(0xE8 as f32 / 255.0);
-
-fn items_list_view(items: &Vec<String>) -> Element<'static, Message> {
- let mut column = Column::new()
- .spacing(20)
- .align_items(Alignment::Center)
- .width(Length::Fill);
-
- for value in items {
- column = column.push(text(value));
- }
-
- container(column).height(250.0).width(300).into()
-}
-
-mod style {
- use iced::widget::container;
- use iced::{Border, Theme};
-
- pub fn title_bar(theme: &Theme) -> container::Appearance {
- let palette = theme.extended_palette();
-
- container::Appearance {
- text_color: Some(palette.background.strong.text),
- background: Some(palette.background.strong.color.into()),
- ..Default::default()
- }
- }
-
- pub fn pane_active(theme: &Theme) -> container::Appearance {
- let palette = theme.extended_palette();
-
- container::Appearance {
- background: Some(palette.background.weak.color.into()),
- border: Border {
- width: 1.0,
- color: palette.background.strong.color,
- ..Border::default()
- },
- ..Default::default()
- }
- }
-
- pub fn pane_focused(theme: &Theme) -> container::Appearance {
- let palette = theme.extended_palette();
-
- container::Appearance {
- background: Some(palette.background.weak.color.into()),
- border: Border {
- width: 4.0,
- color: palette.background.strong.color,
- ..Border::default()
- },
- ..Default::default()
- }
- }
-}
diff --git a/src/types/mod.rs b/src/types/mod.rs
deleted file mode 100644
index 7a04d79..0000000
--- a/src/types/mod.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-pub mod rendered_element;
-
-use rendered_element::RenderedElement;
-use std::path::PathBuf;
-
-pub struct DesignerState {
- pub designer_content: Vec<RenderedElement>,
- pub designer_page: DesignerPage,
-}
-
-#[derive(Debug)]
-pub enum ElementName {
- Text(&'static str),
- Button(&'static str),
- SVG(PathBuf),
- Image(PathBuf),
- Container,
- Row,
- Column,
-}
-
-pub enum DesignerPage {
- Designer,
- CodeView,
-}
diff --git a/src/types/rendered_element.rs b/src/types/rendered_element.rs
deleted file mode 100644
index f05594d..0000000
--- a/src/types/rendered_element.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use std::collections::HashMap;
-
-use unique_id::{string::StringGenerator, Generator};
-
-use iced::advanced::widget::Id;
-
-use super::ElementName;
-
-#[derive(Debug)]
-pub struct RenderedElement {
- pub id: Id,
- pub child_elements: Vec<RenderedElement>,
- pub name: ElementName,
- pub props: HashMap<&'static str, &'static str>,
-}
-
-impl RenderedElement {
- pub fn new(name: ElementName) -> Self {
- let gen = StringGenerator::default();
- Self {
- id: Id::new(gen.next_id()),
- child_elements: vec![],
- name,
- props: HashMap::new(),
- }
- }
-
- pub fn from_vec(name: ElementName, child_elements: Vec<RenderedElement>) -> Self {
- let gen = StringGenerator::default();
- Self {
- id: Id::new(gen.next_id()),
- child_elements,
- name,
- props: HashMap::new(),
- }
- }
-
- pub fn push(mut self, element: RenderedElement) -> Self {
- self.child_elements.push(element);
- self
- }
-
- pub fn set_property(&mut self, prop: &'static str, value: &'static str) {
- let prop_ref = self.props.entry(prop).or_insert(value);
- *prop_ref = value;
- }
-}