summaryrefslogtreecommitdiff
path: root/src/types
diff options
context:
space:
mode:
authorPolesznyák Márk László <116908301+pml68@users.noreply.github.com>2025-04-29 23:35:39 +0200
committerGitHub <noreply@github.com>2025-04-29 23:35:39 +0200
commitca50c308f0058af80e9125ba00a1349877169968 (patch)
tree38fbd5c78c90487e5b641f635d01c4a614ddfd44 /src/types
parentMerge pull request #14 from pml68/dependabot/cargo/windows_exe_info-0.5.1 (diff)
parentstyle: `theme` -> `appearance` (diff)
downloadiced-builder-ca50c308f0058af80e9125ba00a1349877169968.tar.gz
Merge pull request #20 from pml68/feat/custom-theme
Diffstat (limited to '')
-rw-r--r--src/types.rs8
-rw-r--r--src/types/project.rs70
-rwxr-xr-xsrc/types/rendered_element.rs158
3 files changed, 118 insertions, 118 deletions
diff --git a/src/types.rs b/src/types.rs
index a7fae1c..608f285 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -8,14 +8,20 @@ pub use element_name::ElementName;
use iced::advanced::widget::Id;
use iced::widget::{pane_grid, text_editor};
use iced_anim::Event;
+use material_theme::Theme;
pub use project::Project;
pub use rendered_element::*;
use crate::Error;
+use crate::config::Config;
+pub type Element<'a, Message> = iced::Element<'a, Message, Theme>;
+
+#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone)]
pub enum Message {
- SwitchTheme(Event<iced::Theme>),
+ ConfigLoad(Result<Config, Error>),
+ SwitchTheme(Event<Theme>),
CopyCode,
SwitchPage(DesignerPane),
EditorAction(text_editor::Action),
diff --git a/src/types/project.rs b/src/types/project.rs
index 721783e..11789ac 100644
--- a/src/types/project.rs
+++ b/src/types/project.rs
@@ -1,24 +1,19 @@
use std::path::{Path, PathBuf};
-use std::sync::Arc;
extern crate fxhash;
-use fxhash::FxHashMap;
use iced::Theme;
use rust_format::{Edition, Formatter, RustFmt};
use serde::{Deserialize, Serialize};
use super::rendered_element::RenderedElement;
use crate::Error;
-use crate::config::Config;
-use crate::theme::{theme_from_str, theme_index, theme_to_string};
+use crate::appearance::iced_theme_from_str;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Project {
pub title: Option<String>,
pub theme: Option<String>,
pub element_tree: Option<RenderedElement>,
- #[serde(skip)]
- theme_cache: FxHashMap<String, String>,
}
impl Default for Project {
@@ -33,45 +28,24 @@ impl Project {
title: None,
theme: None,
element_tree: None,
- theme_cache: FxHashMap::default(),
}
}
- pub fn get_theme(&self, config: &Config) -> Theme {
+ pub fn get_theme(&self) -> Theme {
match &self.theme {
- Some(theme) => theme_from_str(Some(config), theme),
- None => Theme::default(),
+ Some(theme) => iced_theme_from_str(theme),
+ None => iced::Theme::default(),
}
}
- fn theme_code(&mut self, theme: &Theme) -> String {
- let theme_name = theme.to_string();
- if theme_index(&theme_name, Theme::ALL).is_none() {
- (*self
- .theme_cache
- .entry(theme_name)
- .or_insert(theme_to_string(theme)))
- .to_string()
- } else {
- theme_name.replace(" ", "")
- }
- }
-
- pub async fn from_path(
- path: PathBuf,
- config: Arc<Config>,
- ) -> Result<(PathBuf, Self), Error> {
+ pub async fn from_path(path: PathBuf) -> Result<(PathBuf, Self), Error> {
let contents = tokio::fs::read_to_string(&path).await?;
- let mut project: Self = serde_json::from_str(&contents)?;
-
- let _ = project.theme_code(&project.get_theme(&config));
+ let project: Self = serde_json::from_str(&contents)?;
Ok((path, project))
}
- pub async fn from_file(
- config: Arc<Config>,
- ) -> Result<(PathBuf, Self), Error> {
+ pub async fn from_file() -> Result<(PathBuf, Self), Error> {
let picked_file = rfd::AsyncFileDialog::new()
.set_title("Open a JSON file...")
.add_filter("*.json, *.JSON", &["json", "JSON"])
@@ -81,7 +55,7 @@ impl Project {
let path = picked_file.path().to_owned();
- Self::from_path(path, config).await
+ Self::from_path(path).await
}
pub async fn write_to_file(
@@ -108,28 +82,21 @@ impl Project {
Ok(path)
}
- pub fn app_code(&mut self, config: &Config) -> Result<String, Error> {
- match self.element_tree {
+ pub fn app_code(&mut self) -> Result<String, Error> {
+ use iced::debug;
+ let codegen = debug::time("Code Generation");
+
+ let result = match self.element_tree {
Some(ref element_tree) => {
let (imports, view) = element_tree.codegen();
- let theme = self.get_theme(config);
- let theme_code = self.theme_code(&theme);
- let mut theme_imports = "";
- if theme_index(&theme.to_string(), Theme::ALL).is_none() {
- if theme_code.contains("Extended") {
- theme_imports = "use iced::{{color,theme::{{Palette,palette::{{Extended,Background,Primary,Secondary,Success,Danger,Warning,Pair}}}}}};\n";
- } else {
- theme_imports = "use iced::{{color,theme::Palette}};\n";
- }
- }
+ let theme = self.get_theme();
let app_code = format!(
r#"// Automatically generated by iced Builder
use iced::{{widget::{{{imports}}},Element}};
-{theme_imports}
fn main() -> iced::Result {{
- iced::application("{}", State::update, State::view).theme(State::theme).run()
+ iced::application(State::default, State::update, State::view).title("{}").theme(State::theme).run()
}}
#[derive(Default)]
@@ -153,7 +120,7 @@ impl State {{
Some(ref t) => t,
None => "New app",
},
- theme_code
+ theme.to_string().replace(" ", "")
);
let config = rust_format::Config::new_str()
.edition(Edition::Rust2021)
@@ -163,6 +130,9 @@ impl State {{
Ok(rustfmt.format_str(app_code)?)
}
None => Err("No element tree present".into()),
- }
+ };
+
+ codegen.finish();
+ result
}
}
diff --git a/src/types/rendered_element.rs b/src/types/rendered_element.rs
index 0a78dcd..020aa46 100755
--- a/src/types/rendered_element.rs
+++ b/src/types/rendered_element.rs
@@ -1,7 +1,7 @@
use std::collections::BTreeMap;
use iced::advanced::widget::Id;
-use iced::{Element, Length, widget};
+use iced::{Element, widget};
use serde::{Deserialize, Serialize};
use crate::Error;
@@ -171,34 +171,6 @@ impl RenderedElement {
self
}
- pub fn text_view<'a>(self) -> Element<'a, Message> {
- let mut children = widget::column![];
-
- if let Some(els) = self.child_elements.clone() {
- for el in els {
- children = children.push(el.clone().text_view());
- }
- }
- iced_drop::droppable(
- widget::container(
- widget::column![
- widget::text(self.name.clone().to_string()),
- children
- ]
- .width(Length::Fill)
- .spacing(10),
- )
- .padding(10)
- .style(widget::container::bordered_box),
- )
- .id(self.id().clone())
- .drag_hide(true)
- .on_drop(move |point, rect| {
- Message::MoveElement(self.clone(), point, rect)
- })
- .into()
- }
-
pub fn codegen(&self) -> (String, String) {
let mut imports = String::new();
let mut view = String::new();
@@ -223,7 +195,14 @@ impl RenderedElement {
match &self.name {
ElementName::Container => {
imports = format!("{imports}container,");
- view = format!("{view}\ncontainer({elements}){options}");
+ view = format!(
+ "{view}\ncontainer({}){options}",
+ if elements.is_empty() {
+ String::from("\"\"")
+ } else {
+ elements.to_string()
+ }
+ );
}
ElementName::Row => {
imports = format!("{imports}row,");
@@ -237,7 +216,7 @@ impl RenderedElement {
imports = format!("{imports}text,");
view = format!(
"{view}\ntext(\"{}\"){options}",
- if *string == String::new() {
+ if string.is_empty() {
"New Text"
} else {
string
@@ -248,7 +227,7 @@ impl RenderedElement {
imports = format!("{imports}button,");
view = format!(
"{view}\nbutton(\"{}\"){options}",
- if *string == String::new() {
+ if string.is_empty() {
"New Button"
} else {
string
@@ -317,53 +296,98 @@ impl<'a> From<RenderedElement> for Element<'a, Message> {
let child_elements = copy.child_elements.unwrap_or_default();
let content: Element<'a, Message> = match copy.name {
- ElementName::Text(s) => {
- if s.is_empty() {
- widget::text("New Text").apply_options(copy.options).into()
- } else {
- widget::text(s).apply_options(copy.options).into()
- }
- }
- ElementName::Button(s) => {
- if s.is_empty() {
- widget::button(widget::text("New Button"))
- .apply_options(copy.options)
- .into()
- } else {
- widget::button(widget::text(s))
- .apply_options(copy.options)
- .into()
- }
+ ElementName::Text(s) => if s.is_empty() {
+ widget::text("New Text")
+ } else {
+ widget::text(s)
}
+ .apply_options(copy.options)
+ .into(),
+ ElementName::Button(s) => widget::button(if s.is_empty() {
+ widget::text("New Button")
+ } else {
+ widget::text(s)
+ })
+ .apply_options(copy.options)
+ .into(),
ElementName::Svg(p) => {
widget::svg(p).apply_options(copy.options).into()
}
ElementName::Image(p) => {
widget::image(p).apply_options(copy.options).into()
}
- ElementName::Container => {
- widget::container(if child_elements.len() == 1 {
- child_elements[0].clone().into()
- } else {
- Element::from("")
- })
- .apply_options(copy.options)
- .padding(20)
- .into()
+ ElementName::Container => if child_elements.len() == 1 {
+ widget::container(child_elements[0].clone())
+ } else {
+ widget::container("New Container").style(
+ |theme: &iced::Theme| widget::container::Style {
+ border: iced::Border {
+ color: theme.palette().text,
+
+ width: 2.0,
+ radius: 4.into(),
+ },
+ ..Default::default()
+ },
+ )
}
- ElementName::Row => widget::Row::from_vec(
- child_elements.into_iter().map(Into::into).collect(),
- )
- .padding(20)
- .apply_options(copy.options)
- .into(),
- ElementName::Column => widget::Column::from_vec(
- child_elements.into_iter().map(Into::into).collect(),
- )
.padding(20)
.apply_options(copy.options)
.into(),
+ ElementName::Row => {
+ if !child_elements.is_empty() {
+ widget::Row::with_children(
+ child_elements.into_iter().map(Into::into),
+ )
+ .padding(20)
+ .apply_options(copy.options)
+ .into()
+ } else {
+ widget::container(
+ widget::row!["New Row"]
+ .padding(20)
+ .apply_options(copy.options),
+ )
+ .style(|theme: &iced::Theme| widget::container::Style {
+ border: iced::Border {
+ color: theme.palette().text,
+
+ width: 2.0,
+ radius: 4.into(),
+ },
+ ..Default::default()
+ })
+ .into()
+ }
+ }
+ ElementName::Column => {
+ if !child_elements.is_empty() {
+ widget::Column::with_children(
+ child_elements.into_iter().map(Into::into),
+ )
+ .padding(20)
+ .apply_options(copy.options)
+ .into()
+ } else {
+ widget::container(
+ widget::column!["New Column"]
+ .padding(20)
+ .apply_options(copy.options),
+ )
+ .style(|theme: &iced::Theme| widget::container::Style {
+ border: iced::Border {
+ color: theme.palette().text,
+
+ width: 2.0,
+ radius: 4.into(),
+ },
+ ..Default::default()
+ })
+ .into()
+ }
+ }
};
+
iced_drop::droppable(content)
.id(value.id().clone())
.drag_hide(true)