From 53dc5464c2f595d1a32174598e280428d3265f15 Mon Sep 17 00:00:00 2001 From: pml68 Date: Tue, 8 Apr 2025 19:40:45 +0200 Subject: feat(material_theme): impl `menu::Catalog`, change `dialog::Catalog` impl --- src/types/rendered_element.rs | 105 +++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 36 deletions(-) (limited to 'src/types/rendered_element.rs') diff --git a/src/types/rendered_element.rs b/src/types/rendered_element.rs index 0a78dcd..77b76e4 100755 --- a/src/types/rendered_element.rs +++ b/src/types/rendered_element.rs @@ -317,53 +317,86 @@ impl<'a> From 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") + .padding(20) + .style(|theme| widget::container::Style { + border: iced::border::rounded(4).color( + theme.extended_palette().background.strongest.text, + ), + ..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), + ) + .apply_options(copy.options) + .into() + } else { + widget::container( + widget::row!["New Row"] + .padding(20) + .apply_options(copy.options), + ) + .style(|theme| widget::container::Style { + border: iced::border::rounded(4).color( + theme.extended_palette().background.strongest.text, + ), + ..Default::default() + }) + .into() + } + } + ElementName::Column => { + if !child_elements.is_empty() { + widget::Column::with_children( + child_elements.into_iter().map(Into::into), + ) + .apply_options(copy.options) + .into() + } else { + widget::container( + widget::column!["New Column"] + .padding(20) + .apply_options(copy.options), + ) + .style(|theme| widget::container::Style { + border: iced::border::rounded(4).color( + theme.extended_palette().background.strongest.text, + ), + ..Default::default() + }) + .into() + } + } }; + iced_drop::droppable(content) .id(value.id().clone()) .drag_hide(true) -- cgit v1.2.3 From 941eb51e043b6b847089130625c2df10b0674154 Mon Sep 17 00:00:00 2001 From: pml68 Date: Wed, 9 Apr 2025 00:29:34 +0200 Subject: feat: update `iced`, make designer view more usable --- Cargo.lock | 252 +++++++++++++++++++++++------------------- Cargo.toml | 4 +- src/main.rs | 18 ++- src/panes/designer_view.rs | 19 +++- src/types/rendered_element.rs | 42 ++++--- 5 files changed, 193 insertions(+), 142 deletions(-) (limited to 'src/types/rendered_element.rs') diff --git a/Cargo.lock b/Cargo.lock index b2ab721..a324ccd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,6 +57,12 @@ dependencies = [ "zerocopy 0.7.35", ] +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + [[package]] name = "aligned-vec" version = "0.5.0" @@ -105,15 +111,6 @@ version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - [[package]] name = "arbitrary" version = "1.4.1" @@ -569,12 +566,6 @@ version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" -[[package]] -name = "by_address" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" - [[package]] name = "bytemuck" version = "1.22.0" @@ -1316,12 +1307,6 @@ dependencies = [ "zune-inflate", ] -[[package]] -name = "fast-srgb8" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" - [[package]] name = "fastrand" version = "2.3.0" @@ -1767,9 +1752,9 @@ dependencies = [ [[package]] name = "half" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "cfg-if", "crunchy", @@ -1784,6 +1769,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "heck" version = "0.5.0" @@ -1938,11 +1929,14 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ "iced_core", + "iced_debug", + "iced_devtools", "iced_futures", "iced_renderer", + "iced_runtime", "iced_widget", "iced_winit", "image", @@ -1967,6 +1961,21 @@ dependencies = [ "syn", ] +[[package]] +name = "iced_beacon" +version = "0.14.0-dev" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" +dependencies = [ + "bincode", + "futures", + "iced_core", + "log", + "semver", + "serde", + "thiserror 1.0.69", + "tokio", +] + [[package]] name = "iced_builder" version = "0.1.0" @@ -1996,7 +2005,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ "bitflags 2.9.0", "bytes", @@ -2005,8 +2014,8 @@ dependencies = [ "lilt", "log", "num-traits", - "palette", "rustc-hash 2.1.1", + "serde", "smol_str", "thiserror 1.0.69", "web-time", @@ -2022,6 +2031,26 @@ dependencies = [ "two-face", ] +[[package]] +name = "iced_debug" +version = "0.14.0-dev" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" +dependencies = [ + "iced_beacon", + "iced_core", + "log", +] + +[[package]] +name = "iced_devtools" +version = "0.14.0-dev" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" +dependencies = [ + "iced_debug", + "iced_program", + "iced_widget", +] + [[package]] name = "iced_dialog" version = "0.14.0-dev" @@ -2055,7 +2084,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ "futures", "iced_core", @@ -2069,7 +2098,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ "bitflags 2.9.0", "bytemuck", @@ -2086,10 +2115,19 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "iced_program" +version = "0.14.0-dev" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" +dependencies = [ + "iced_graphics", + "iced_runtime", +] + [[package]] name = "iced_renderer" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2101,20 +2139,20 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ "bytes", "iced_core", + "iced_debug", "iced_futures", "raw-window-handle", - "sipper", "thiserror 1.0.69", ] [[package]] name = "iced_tiny_skia" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ "bytemuck", "cosmic-text", @@ -2130,7 +2168,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ "bitflags 2.9.0", "bytemuck", @@ -2149,12 +2187,13 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ "iced_renderer", "iced_runtime", "log", "num-traits", + "ouroboros", "rustc-hash 2.1.1", "thiserror 1.0.69", "unicode-segmentation", @@ -2163,11 +2202,10 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#1a84a8019cbd95ae1b1c88f75aeb0a15f0f3caf2" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#add48e518b3423bed980983ddc373cfb8f5e8980" dependencies = [ - "iced_futures", - "iced_graphics", - "iced_runtime", + "iced_debug", + "iced_program", "log", "rustc-hash 2.1.1", "thiserror 1.0.69", @@ -2758,9 +2796,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", "simd-adler32", @@ -3347,36 +3385,36 @@ dependencies = [ ] [[package]] -name = "owned_ttf_parser" -version = "0.25.0" +name = "ouroboros" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" +checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59" dependencies = [ - "ttf-parser 0.25.1", + "aliasable", + "ouroboros_macro", + "static_assertions", ] [[package]] -name = "palette" -version = "0.7.6" +name = "ouroboros_macro" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0" dependencies = [ - "approx", - "fast-srgb8", - "palette_derive", - "phf", + "heck 0.4.1", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", ] [[package]] -name = "palette_derive" -version = "0.7.6" +name = "owned_ttf_parser" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" dependencies = [ - "by_address", - "proc-macro2", - "quote", - "syn", + "ttf-parser 0.25.1", ] [[package]] @@ -3430,48 +3468,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher", -] - [[package]] name = "pico-args" version = "0.5.0" @@ -3600,6 +3596,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "version_check", + "yansi", +] + [[package]] name = "profiling" version = "1.0.16" @@ -4176,6 +4185,9 @@ name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +dependencies = [ + "serde", +] [[package]] name = "serde" @@ -4308,16 +4320,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" -[[package]] -name = "sipper" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bccb4192828b3d9a08e0b5a73f17795080dfb278b50190216e3ae2132cf4f95" -dependencies = [ - "futures", - "pin-project-lite", -] - [[package]] name = "skrifa" version = "0.26.6" @@ -4484,7 +4486,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", @@ -4612,7 +4614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" dependencies = [ "cfg-expr", - "heck", + "heck 0.5.0", "pkg-config", "toml", "version-compare", @@ -4790,9 +4792,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", @@ -4800,9 +4802,21 @@ dependencies = [ "mio", "pin-project-lite", "socket2", + "tokio-macros", "windows-sys 0.52.0", ] +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -6029,9 +6043,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" dependencies = [ "memchr", ] @@ -6161,6 +6175,12 @@ dependencies = [ "lzma-sys", ] +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + [[package]] name = "yazi" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index 63e5f89..e48a39c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ material_theme = { path = "material_theme" } serde.workspace = true serde_json = "1.0.140" toml.workspace = true -tokio = { version = "1.42.1", features = ["fs"] } +tokio = { version = "1.44.2", features = ["fs"] } tokio-stream = { version = "0.1", features = ["fs"] } # TODO: enable tokio when it actually compiles # rfd = { version = "0.15.2", default-features = false, features = ["tokio", "xdg-portal"] } @@ -43,7 +43,7 @@ toml = "0.8.20" [workspace.dependencies.iced] git = "https://github.com/pml68/iced" branch = "feat/rehighlight-on-redraw" -features = ["image", "svg", "advanced", "tokio"] +features = ["image", "svg", "advanced", "tokio", "lazy"] [build-dependencies] iced_fontello = "0.13.2" diff --git a/src/main.rs b/src/main.rs index 3895dbc..d58329a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,12 +54,18 @@ fn main() -> Result<(), Box> { rt.block_on(Config::load()) }; - iced::application(App::title, App::update, App::view) - .font(icon::FONT) - .theme(|state| state.theme.value().clone()) - .subscription(App::subscription) - .antialiasing(true) - .run_with(move || App::new(config_load))?; + iced::application( + move || App::new(config_load.clone()), + App::update, + App::view, + ) + .title(App::title) + .font(icon::FONT) + .theme(|state| state.theme.value().clone()) + .subscription(App::subscription) + .antialiasing(true) + .run()?; + Ok(()) } diff --git a/src/panes/designer_view.rs b/src/panes/designer_view.rs index 6340f73..69ff750 100644 --- a/src/panes/designer_view.rs +++ b/src/panes/designer_view.rs @@ -1,16 +1,29 @@ -use iced::widget::{Space, button, container, pane_grid, row, text, themer}; +use iced::widget::{ + Space, button, center, container, pane_grid, responsive, row, text, themer, +}; use iced::{Alignment, Element, Length}; use super::style; use crate::types::{DesignerPane, Message, RenderedElement}; pub fn view<'a>( - element_tree: Option<&RenderedElement>, + element_tree: Option<&'a RenderedElement>, designer_theme: iced::Theme, is_focused: bool, ) -> pane_grid::Content<'a, Message> { let el_tree: Element<'a, Message> = match element_tree { - Some(tree) => tree.clone().into(), + Some(tree) => responsive(|size| { + center( + container(tree.clone()) + .style(|theme| { + container::background(theme.palette().background) + }) + .height(size.height * 0.5) + .width(size.height * 0.8), + ) + .into() + }) + .into(), None => text("Open a project or begin creating one").into(), }; let content = container(themer(designer_theme, el_tree)) diff --git a/src/types/rendered_element.rs b/src/types/rendered_element.rs index 77b76e4..bd8187e 100755 --- a/src/types/rendered_element.rs +++ b/src/types/rendered_element.rs @@ -340,15 +340,19 @@ impl<'a> From for Element<'a, Message> { ElementName::Container => if child_elements.len() == 1 { widget::container(child_elements[0].clone()) } else { - widget::container("New Container") - .padding(20) - .style(|theme| widget::container::Style { - border: iced::border::rounded(4).color( - theme.extended_palette().background.strongest.text, - ), + 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() - }) + }, + ) } + .padding(20) .apply_options(copy.options) .into(), ElementName::Row => { @@ -356,6 +360,7 @@ impl<'a> From for Element<'a, Message> { widget::Row::with_children( child_elements.into_iter().map(Into::into), ) + .padding(20) .apply_options(copy.options) .into() } else { @@ -364,10 +369,13 @@ impl<'a> From for Element<'a, Message> { .padding(20) .apply_options(copy.options), ) - .style(|theme| widget::container::Style { - border: iced::border::rounded(4).color( - theme.extended_palette().background.strongest.text, - ), + .style(|theme: &iced::Theme| widget::container::Style { + border: iced::Border { + color: theme.palette().text, + + width: 2.0, + radius: 4.into(), + }, ..Default::default() }) .into() @@ -378,6 +386,7 @@ impl<'a> From for Element<'a, Message> { widget::Column::with_children( child_elements.into_iter().map(Into::into), ) + .padding(20) .apply_options(copy.options) .into() } else { @@ -386,10 +395,13 @@ impl<'a> From for Element<'a, Message> { .padding(20) .apply_options(copy.options), ) - .style(|theme| widget::container::Style { - border: iced::border::rounded(4).color( - theme.extended_palette().background.strongest.text, - ), + .style(|theme: &iced::Theme| widget::container::Style { + border: iced::Border { + color: theme.palette().text, + + width: 2.0, + radius: 4.into(), + }, ..Default::default() }) .into() -- cgit v1.2.3 From 1683717e93899d4c90641e605bfc96cbc2bf5ef1 Mon Sep 17 00:00:00 2001 From: pml68 Date: Fri, 18 Apr 2025 00:52:13 +0200 Subject: fix: `iced` 0.14 codegen --- Cargo.lock | 43 +++++++++++++++++++++---------------------- src/types/project.rs | 2 +- src/types/rendered_element.rs | 13 ++++++++++--- 3 files changed, 32 insertions(+), 26 deletions(-) (limited to 'src/types/rendered_element.rs') diff --git a/Cargo.lock b/Cargo.lock index e8a5b71..4f0a992 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,7 +187,7 @@ dependencies = [ "enumflags2", "futures-channel", "futures-util", - "rand 0.9.0", + "rand 0.9.1", "raw-window-handle", "serde", "serde_repr", @@ -1945,7 +1945,7 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "iced_core", "iced_debug", @@ -1980,7 +1980,7 @@ dependencies = [ [[package]] name = "iced_beacon" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "bincode", "futures", @@ -2021,7 +2021,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "bitflags 2.9.0", "bytes", @@ -2050,7 +2050,7 @@ dependencies = [ [[package]] name = "iced_debug" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "iced_beacon", "iced_core", @@ -2060,7 +2060,7 @@ dependencies = [ [[package]] name = "iced_devtools" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "iced_debug", "iced_program", @@ -2100,7 +2100,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "futures", "iced_core", @@ -2114,7 +2114,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "bitflags 2.9.0", "bytemuck", @@ -2135,7 +2135,7 @@ dependencies = [ [[package]] name = "iced_program" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "iced_graphics", "iced_runtime", @@ -2144,7 +2144,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2156,7 +2156,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "bytes", "iced_core", @@ -2169,7 +2169,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "bytemuck", "cosmic-text", @@ -2186,7 +2186,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "bitflags 2.9.0", "bytemuck", @@ -2207,7 +2207,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "iced_renderer", "iced_runtime", @@ -2225,7 +2225,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.14.0-dev" -source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#4f933c3b8919a115fa82d9aee94ec5b1c81c4dfe" +source = "git+https://github.com/pml68/iced?branch=feat%2Frehighlight-on-redraw#b6433c4637ddf4697154feeb14c66e06200e4e1b" dependencies = [ "iced_debug", "iced_program", @@ -3665,9 +3665,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -3781,13 +3781,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.24", ] [[package]] @@ -4602,9 +4601,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svg_fmt" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce5d813d71d82c4cbc1742135004e4a79fd870214c155443451c139c9470a0aa" +checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" [[package]] name = "svgtypes" diff --git a/src/types/project.rs b/src/types/project.rs index 50cbb69..145ab18 100644 --- a/src/types/project.rs +++ b/src/types/project.rs @@ -103,7 +103,7 @@ 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)] diff --git a/src/types/rendered_element.rs b/src/types/rendered_element.rs index bd8187e..9639299 100755 --- a/src/types/rendered_element.rs +++ b/src/types/rendered_element.rs @@ -223,7 +223,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 +244,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 +255,7 @@ impl RenderedElement { imports = format!("{imports}button,"); view = format!( "{view}\nbutton(\"{}\"){options}", - if *string == String::new() { + if string.is_empty() { "New Button" } else { string -- cgit v1.2.3 From e17ce59fa4c907511f38795c342b2232a7bba26d Mon Sep 17 00:00:00 2001 From: pml68 Date: Mon, 28 Apr 2025 10:59:52 +0200 Subject: feat: switch to fully custom, Material3-based theme --- assets/themes/rose_pine.toml | 41 ----- src/appearance.rs | 46 ++++++ src/config.rs | 41 +++-- src/dialogs.rs | 4 +- src/main.rs | 23 ++- src/options.rs | 2 +- src/panes/code_view.rs | 46 +++--- src/panes/designer_view.rs | 7 +- src/panes/element_list.rs | 7 +- src/panes/style.rs | 23 +-- src/theme.rs | 357 ------------------------------------------ src/types.rs | 6 +- src/types/project.rs | 18 +-- src/types/rendered_element.rs | 30 +--- src/widget.rs | 18 ++- theme_test/src/main.rs | 2 +- 16 files changed, 155 insertions(+), 516 deletions(-) delete mode 100644 assets/themes/rose_pine.toml create mode 100644 src/appearance.rs delete mode 100644 src/theme.rs (limited to 'src/types/rendered_element.rs') diff --git a/assets/themes/rose_pine.toml b/assets/themes/rose_pine.toml deleted file mode 100644 index e4540fb..0000000 --- a/assets/themes/rose_pine.toml +++ /dev/null @@ -1,41 +0,0 @@ -name = "Rosé Pine" - -dark = true - -[palette] -background = "#26233a" -text = "#e0def4" -primary = "#9ccfd8" -success = "#f6c177" -danger = "#eb6f92" -warning = "#e4b363" - -[background] -base = { color = "#191724", text = "#e0def4" } -weak = { color = "#1f1d2e", text = "#e0def4" } -strong = { color = "#26233a", text = "#f4ebd3" } - -[primary] -base = { color = "#eb6f92", text = "#000000" } -weak = { color = "#f6c177", text = "#000000" } -strong = { color = "#ebbcba", text = "#000000" } - -[secondary] -base = { color = "#31748f", text = "#ffffff" } -weak = { color = "#9ccfd8", text = "#000000" } -strong = { color = "#c4a7e7", text = "#000000" } - -[success] -base = { color = "#9ccfd8", text = "#000000" } -weak = { color = "#6e6a86", text = "#ffffff" } -strong = { color = "#908caa", text = "#000000" } - -[danger] -base = { color = "#eb6f92", text = "#ffffff" } -weak = { color = "#f6c177", text = "#ffffff" } -strong = { color = "#524f67", text = "#ffffff" } - -[warning] -base = { color = "#e4b363", text = "#ffffff" } -weak = { color = "#f4e1a1", text = "#000000" } -strong = { color = "#d8a343", text = "#ffffff" } diff --git a/src/appearance.rs b/src/appearance.rs new file mode 100644 index 0000000..78e782d --- /dev/null +++ b/src/appearance.rs @@ -0,0 +1,46 @@ +use std::sync::Arc; + +use material_theme::Theme; + +pub fn iced_theme_from_str(theme_name: &str) -> iced::Theme { + match theme_name { + "Light" => iced::Theme::Light, + "Dark" => iced::Theme::Dark, + "Dracula" => iced::Theme::Dracula, + "Nord" => iced::Theme::Nord, + "Solarized Light" => iced::Theme::SolarizedLight, + "Solarized Dark" => iced::Theme::SolarizedDark, + "Gruvbox Light" => iced::Theme::GruvboxLight, + "Gruvbox Dark" => iced::Theme::GruvboxDark, + "Catppuccin Latte" => iced::Theme::CatppuccinLatte, + "Catppuccin Frappé" => iced::Theme::CatppuccinFrappe, + "Catppuccin Macchiato" => iced::Theme::CatppuccinMacchiato, + "Catppuccin Mocha" => iced::Theme::CatppuccinMocha, + "Tokyo Night" => iced::Theme::TokyoNight, + "Tokyo Night Storm" => iced::Theme::TokyoNightStorm, + "Tokyo Night Light" => iced::Theme::TokyoNightLight, + "Kanagawa Wave" => iced::Theme::KanagawaWave, + "Kanagawa Dragon" => iced::Theme::KanagawaDragon, + "Kanagawa Lotus" => iced::Theme::KanagawaLotus, + "Moonfly" => iced::Theme::Moonfly, + "Nightfly" => iced::Theme::Nightfly, + "Oxocarbon" => iced::Theme::Oxocarbon, + "Ferra" => iced::Theme::Ferra, + _ => iced::Theme::default(), + } +} + +#[derive(Debug, Clone)] +pub struct Appearance { + pub selected: Theme, + pub all: Arc<[Theme]>, +} + +impl Default for Appearance { + fn default() -> Self { + Self { + selected: Theme::default(), + all: Theme::ALL.into(), + } + } +} diff --git a/src/config.rs b/src/config.rs index 1da1239..7f6f8ce 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,26 +1,36 @@ // (c) 2022-2024 Cory Forsstrom, Casper Rogild Storm, Calvin Lee, Andrew Baldwin, Reza Alizadeh Majd // (c) 2024-2025 Polesznyák Márk László -use std::path::PathBuf; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use material_theme::Theme; use serde::Deserialize; use tokio_stream::StreamExt; use tokio_stream::wrappers::ReadDirStream; -use crate::theme::{Appearance, Theme, theme_from_str, theme_index}; +use crate::appearance::Appearance; use crate::{Error, environment}; #[derive(Debug, Clone, Default)] pub struct Config { - pub theme: Appearance, - pub last_project: Option, + theme: Appearance, + last_project: Option, } impl Config { - pub fn selected_theme(&self) -> iced::Theme { + pub fn selected_theme(&self) -> Theme { self.theme.selected.clone() } + pub fn themes(&self) -> Arc<[Theme]> { + self.theme.all.clone() + } + + pub fn last_project(&self) -> Option<&Path> { + self.last_project.as_deref() + } + pub fn config_dir() -> PathBuf { let dir = environment::config_dir(); @@ -67,7 +77,7 @@ impl Config { last_project, } = toml::from_str(content.as_ref())?; - let theme = Self::load_theme(theme).await.unwrap_or_default(); + let theme = Self::load_appearance(&theme).await.unwrap_or_default(); Ok(Self { theme, @@ -75,7 +85,9 @@ impl Config { }) } - pub async fn load_theme(theme_name: String) -> Result { + pub async fn load_appearance( + theme_name: &str, + ) -> Result { use tokio::fs; let read_entry = async move |entry: fs::DirEntry| { @@ -83,15 +95,16 @@ impl Config { let theme: Theme = toml::from_str(content.as_ref()).ok()?; - Some(iced::Theme::from(theme)) + Some(theme) }; - let mut selected = Theme::default().into(); - let mut all = iced::Theme::ALL.to_owned(); - all.push(Theme::default().into()); + let mut selected = Theme::default(); + let mut all = Theme::ALL.to_owned(); - if theme_index(&theme_name, iced::Theme::ALL).is_some() { - selected = theme_from_str(None, &theme_name); + if let Some(index) = + Theme::ALL.iter().position(|t| t.name() == theme_name) + { + selected = Theme::ALL[index].clone(); } let mut stream = @@ -102,7 +115,7 @@ impl Config { }; if let Some(theme) = read_entry(entry).await { - if theme.to_string() == theme_name { + if theme.name() == theme_name { selected = theme.clone(); } all.push(theme); diff --git a/src/dialogs.rs b/src/dialogs.rs index a623f35..c1933ec 100644 --- a/src/dialogs.rs +++ b/src/dialogs.rs @@ -1,8 +1,8 @@ -use iced::{Element, Task}; +use iced::Task; use iced_dialog::button; use crate::Message; -use crate::types::{DialogAction, DialogButtons}; +use crate::types::{DialogAction, DialogButtons, Element}; pub const UNSAVED_CHANGES_TITLE: &str = "Unsaved changes"; pub const WARNING_TITLE: &str = "Heads up!"; diff --git a/src/main.rs b/src/main.rs index 5014077..1ac1d67 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +mod appearance; mod config; mod dialogs; mod environment; @@ -6,7 +7,6 @@ mod error; mod icon; mod options; mod panes; -mod theme; mod types; mod values; mod widget; @@ -24,13 +24,15 @@ use iced::advanced::widget::Id; use iced::widget::{ Column, container, pane_grid, pick_list, row, text, text_editor, }; -use iced::{Alignment, Element, Length, Task, Theme, clipboard, keyboard}; +use iced::{Alignment, Length, Task, clipboard, keyboard}; use iced_anim::transition::Easing; use iced_anim::{Animated, Animation}; use iced_dialog::dialog::Dialog; +use material_theme::Theme; use panes::{code_view, designer_view, element_list}; use types::{ - Action, DesignerPane, DialogAction, DialogButtons, Message, Project, + Action, DesignerPane, DialogAction, DialogButtons, Element, Message, + Project, }; fn main() -> Result<(), Box> { @@ -148,11 +150,10 @@ impl IcedBuilder { self.config = Arc::new(config); self.theme.update(self.config.selected_theme().into()); - return if let Some(path) = self.config.last_project.clone() - { + return if let Some(path) = self.config.last_project() { if path.exists() && path.is_file() { Task::perform( - Project::from_path(path), + Project::from_path(path.to_owned()), Message::FileOpened, ) } else { @@ -394,7 +395,7 @@ impl IcedBuilder { fn view(&self) -> Element<'_, Message> { let header = row![pick_list( - self.config.theme.all.clone(), + self.config.themes(), Some(self.theme.target()), |theme| Message::SwitchTheme(theme.into()) )] @@ -442,13 +443,7 @@ impl IcedBuilder { DialogButtons::OkCancel => vec![ok_button(), cancel_button()], }, ) - .title(self.dialog_title) - .container_style(|theme| container::Style { - background: Some( - theme.extended_palette().background.strong.color.into(), - ), - ..Default::default() - }); + .title(self.dialog_title); Animation::new(&self.theme, content) .on_update(Message::SwitchTheme) diff --git a/src/options.rs b/src/options.rs index 2dc25d7..931182a 100644 --- a/src/options.rs +++ b/src/options.rs @@ -258,7 +258,7 @@ impl ApplyOptions for Row<'_, Message> { } } -impl ApplyOptions for Image { +impl ApplyOptions for Image<'_, Handle> { fn apply_options(self, options: BTreeMap>) -> Self { let mut image = self; diff --git a/src/panes/code_view.rs b/src/panes/code_view.rs index 890af8a..5999b8f 100644 --- a/src/panes/code_view.rs +++ b/src/panes/code_view.rs @@ -1,27 +1,36 @@ use iced::advanced::text::highlighter::Format; -use iced::widget::{Space, button, pane_grid, row, text, text_editor}; -use iced::{Alignment, Background, Border, Font, Length, Theme}; +use iced::border::Radius; +use iced::widget::{button, pane_grid, row, text, text_editor}; +use iced::{Alignment, Border, Font, Length}; use iced_custom_highlighter::{Highlight, Highlighter, Scope, Settings}; +use material_theme::Theme; use super::style; use crate::icon; use crate::types::{DesignerPane, Message}; use crate::widget::tip; +// TODO: implement a highlight style for the material theme fn highlight_style(theme: &Theme, scope: &Scope) -> Format { + let theme = if theme.is_dark() { + iced::Theme::SolarizedDark + } else { + iced::Theme::SolarizedLight + }; + match scope { Scope::Custom { .. } | Scope::Other => Format { color: Some(theme.extended_palette().primary.strong.color), font: None, }, - _ => Highlight::default_style(theme, scope), + _ => Highlight::default_style(&theme, scope), } } pub fn view( editor_content: &text_editor::Content, is_focused: bool, -) -> pane_grid::Content<'_, Message> { +) -> pane_grid::Content<'_, Message, Theme> { let title_bar = pane_grid::TitleBar::new(text("Generated Code").center()) .controls(pane_grid::Controls::dynamic( row![ @@ -29,28 +38,28 @@ pub fn view( button(icon::copy()) .on_press(Message::CopyCode) .padding([2, 7]) - .style(button::text), + .style(material_theme::button::text), "Copy", tip::Position::FollowCursor ), - Space::with_width(20), button("Switch to Designer view") .on_press(Message::SwitchPage(DesignerPane::DesignerView)) ] + .spacing(20) .align_y(Alignment::Center), row![ tip( button(icon::copy()) .on_press(Message::CopyCode) .padding([2, 7]) - .style(button::text), + .style(material_theme::button::text), "Copy", tip::Position::FollowCursor ), - Space::with_width(20), button(icon::switch()) .on_press(Message::SwitchPage(DesignerPane::DesignerView)) ] + .spacing(20) .align_y(Alignment::Center), )) .padding(10) @@ -60,25 +69,22 @@ pub fn view( text_editor(editor_content) .on_action(Message::EditorAction) .font(Font::MONOSPACE) - .highlight_with::( + .highlight_with::>( Settings::new(vec![], highlight_style, "rs"), Highlight::to_format, ) .style(|theme, _| { - let palette = theme.extended_palette(); + let style = material_theme::text_editor::default( + theme, + text_editor::Status::Active, + ); + text_editor::Style { - background: Background::Color( - palette.background.base.color, - ), border: Border { - radius: 2.into(), - width: 1.0, - color: palette.background.strong.color, + radius: Radius::default(), + ..style.border }, - icon: palette.background.weak.text, - placeholder: palette.background.strong.color, - value: palette.background.base.text, - selection: palette.primary.weak.color, + ..style } }) .height(Length::Fill) diff --git a/src/panes/designer_view.rs b/src/panes/designer_view.rs index af72022..0255b40 100644 --- a/src/panes/designer_view.rs +++ b/src/panes/designer_view.rs @@ -1,7 +1,8 @@ use iced::widget::{ button, center, container, pane_grid, responsive, row, text, themer, }; -use iced::{Alignment, Element, Length}; +use iced::{Alignment, Length}; +use material_theme::Theme; use super::style; use crate::icon; @@ -11,8 +12,8 @@ pub fn view<'a>( element_tree: Option<&'a RenderedElement>, designer_theme: iced::Theme, is_focused: bool, -) -> pane_grid::Content<'a, Message> { - let el_tree: Element<'a, Message> = match element_tree { +) -> pane_grid::Content<'a, Message, Theme> { + let el_tree: iced::Element<'a, Message> = match element_tree { Some(tree) => responsive(|size| { center( container(tree.clone()) diff --git a/src/panes/element_list.rs b/src/panes/element_list.rs index 594c203..0e5dbfe 100644 --- a/src/panes/element_list.rs +++ b/src/panes/element_list.rs @@ -1,9 +1,10 @@ use iced::widget::{Column, column, container, pane_grid, text}; -use iced::{Alignment, Element, Length}; +use iced::{Alignment, Length}; use iced_drop::droppable; +use material_theme::Theme; use super::style; -use crate::types::{ElementName, Message}; +use crate::types::{Element, ElementName, Message}; fn items_list_view<'a>() -> Element<'a, Message> { let mut column = Column::new() @@ -25,7 +26,7 @@ fn items_list_view<'a>() -> Element<'a, Message> { .into() } -pub fn view<'a>(is_focused: bool) -> pane_grid::Content<'a, Message> { +pub fn view<'a>(is_focused: bool) -> pane_grid::Content<'a, Message, Theme> { let items_list = items_list_view(); let content = column![items_list] .align_x(Alignment::Center) diff --git a/src/panes/style.rs b/src/panes/style.rs index 1eefb2d..acca6f9 100644 --- a/src/panes/style.rs +++ b/src/panes/style.rs @@ -1,24 +1,25 @@ use iced::widget::container::Style; -use iced::{Border, Theme}; +use iced::{Background, Border}; +use material_theme::Theme; pub fn title_bar(theme: &Theme) -> Style { - let palette = theme.extended_palette(); + let surface = theme.colors().surface; Style { - text_color: Some(palette.background.strong.text), - background: Some(palette.background.strong.color.into()), + text_color: Some(surface.on_surface), + background: Some(Background::Color(surface.surface_container.high)), ..Default::default() } } pub fn pane_active(theme: &Theme) -> Style { - let palette = theme.extended_palette(); + let surface = theme.colors().surface; Style { - background: Some(palette.background.weak.color.into()), + background: Some(Background::Color(surface.surface_container.low)), border: Border { width: 1.0, - color: palette.background.strong.color, + color: surface.surface_container.high, ..Border::default() }, ..Default::default() @@ -26,13 +27,13 @@ pub fn pane_active(theme: &Theme) -> Style { } pub fn pane_focused(theme: &Theme) -> Style { - let palette = theme.extended_palette(); + let surface = theme.colors().surface; Style { - background: Some(palette.background.weak.color.into()), + background: Some(Background::Color(surface.surface_container.low)), border: Border { - width: 4.0, - color: palette.background.strong.color, + width: 2.0, + color: surface.surface_container.high, ..Border::default() }, ..Default::default() diff --git a/src/theme.rs b/src/theme.rs deleted file mode 100644 index b721ddc..0000000 --- a/src/theme.rs +++ /dev/null @@ -1,357 +0,0 @@ -use std::sync::Arc; - -use iced::Color; -use iced::theme::palette::Extended; -use serde::Deserialize; - -use crate::config::Config; - -const DEFAULT_THEME_CONTENT: &str = - include_str!("../assets/themes/rose_pine.toml"); - -pub fn theme_index(theme_name: &str, slice: &[iced::Theme]) -> Option { - slice - .iter() - .position(|theme| theme.to_string() == theme_name) -} - -pub fn theme_from_str( - config: Option<&Config>, - theme_name: &str, -) -> iced::Theme { - match theme_name { - "Light" => iced::Theme::Light, - "Dark" => iced::Theme::Dark, - "Dracula" => iced::Theme::Dracula, - "Nord" => iced::Theme::Nord, - "Solarized Light" => iced::Theme::SolarizedLight, - "Solarized Dark" => iced::Theme::SolarizedDark, - "Gruvbox Light" => iced::Theme::GruvboxLight, - "Gruvbox Dark" => iced::Theme::GruvboxDark, - "Catppuccin Latte" => iced::Theme::CatppuccinLatte, - "Catppuccin Frappé" => iced::Theme::CatppuccinFrappe, - "Catppuccin Macchiato" => iced::Theme::CatppuccinMacchiato, - "Catppuccin Mocha" => iced::Theme::CatppuccinMocha, - "Tokyo Night" => iced::Theme::TokyoNight, - "Tokyo Night Storm" => iced::Theme::TokyoNightStorm, - "Tokyo Night Light" => iced::Theme::TokyoNightLight, - "Kanagawa Wave" => iced::Theme::KanagawaWave, - "Kanagawa Dragon" => iced::Theme::KanagawaDragon, - "Kanagawa Lotus" => iced::Theme::KanagawaLotus, - "Moonfly" => iced::Theme::Moonfly, - "Nightfly" => iced::Theme::Nightfly, - "Oxocarbon" => iced::Theme::Oxocarbon, - "Ferra" => iced::Theme::Ferra, - _ => { - if let Some(config) = config { - if theme_name == config.theme.selected.to_string() { - config.theme.selected.clone() - } else if let Some(index) = - theme_index(theme_name, &config.theme.all) - { - config.theme.all[index].clone() - } else { - iced::Theme::default() - } - } else { - iced::Theme::default() - } - } - } -} - -#[derive(Debug, Clone)] -pub struct Appearance { - pub selected: iced::Theme, - pub all: Arc<[iced::Theme]>, -} - -impl Default for Appearance { - fn default() -> Self { - Self { - selected: Theme::default().into(), - all: { - let mut themes = iced::Theme::ALL.to_owned(); - themes.push(Theme::default().into()); - themes.into() - }, - } - } -} - -#[derive(Debug, Deserialize)] -pub struct Theme { - name: String, - palette: ThemePalette, - dark: Option, - #[serde(flatten)] - extended: Option, -} - -impl From for iced::Theme { - fn from(value: Theme) -> Self { - iced::Theme::custom_with_fn( - value.name.clone(), - value.palette.into(), - |_| value.into(), - ) - } -} - -impl Default for Theme { - fn default() -> Self { - toml::from_str(DEFAULT_THEME_CONTENT).expect("parse default theme") - } -} - -#[derive(Debug, Clone, Copy, Deserialize)] -pub struct ThemePalette { - #[serde(with = "color_serde")] - background: Color, - #[serde(with = "color_serde")] - text: Color, - #[serde(with = "color_serde")] - primary: Color, - #[serde(with = "color_serde")] - success: Color, - #[serde(with = "color_serde")] - danger: Color, - #[serde(with = "color_serde")] - warning: Color, -} - -impl Default for ThemePalette { - fn default() -> Self { - let palette = iced::Theme::default().palette(); - Self { - background: palette.background, - text: palette.text, - primary: palette.primary, - success: palette.success, - danger: palette.danger, - warning: palette.warning, - } - } -} - -impl From for iced::theme::Palette { - fn from(palette: ThemePalette) -> Self { - iced::theme::Palette { - background: palette.background, - text: palette.text, - primary: palette.primary, - success: palette.success, - danger: palette.danger, - warning: palette.warning, - } - } -} - -impl From for Extended { - fn from(theme: Theme) -> Self { - let mut extended = Extended::generate(theme.palette.into()); - - if let Some(is_dark) = theme.dark { - extended.is_dark = is_dark; - } - - if let Some(extended_palette) = theme.extended { - if let Some(background) = extended_palette.background { - if let Some(base) = background.base { - extended.background.base = base.into(); - } - if let Some(weak) = background.weak { - extended.background.weak = weak.into(); - } - if let Some(strong) = background.strong { - extended.background.strong = strong.into(); - } - } - - if let Some(primary) = extended_palette.primary { - if let Some(base) = primary.base { - extended.primary.base = base.into(); - } - if let Some(weak) = primary.weak { - extended.primary.weak = weak.into(); - } - if let Some(strong) = primary.strong { - extended.primary.strong = strong.into(); - } - } - - if let Some(secondary) = extended_palette.secondary { - if let Some(base) = secondary.base { - extended.secondary.base = base.into(); - } - if let Some(weak) = secondary.weak { - extended.secondary.weak = weak.into(); - } - if let Some(strong) = secondary.strong { - extended.secondary.strong = strong.into(); - } - } - - if let Some(success) = extended_palette.success { - if let Some(base) = success.base { - extended.success.base = base.into(); - } - if let Some(weak) = success.weak { - extended.success.weak = weak.into(); - } - if let Some(strong) = success.strong { - extended.success.strong = strong.into(); - } - } - - if let Some(danger) = extended_palette.danger { - if let Some(base) = danger.base { - extended.danger.base = base.into(); - } - if let Some(weak) = danger.weak { - extended.danger.weak = weak.into(); - } - if let Some(strong) = danger.strong { - extended.danger.strong = strong.into(); - } - } - - if let Some(warning) = extended_palette.warning { - if let Some(base) = warning.base { - extended.warning.base = base.into(); - } - if let Some(weak) = warning.weak { - extended.warning.weak = weak.into(); - } - if let Some(strong) = warning.strong { - extended.warning.strong = strong.into(); - } - } - } - - extended - } -} - -#[derive(Debug, Clone, Copy, Default, Deserialize)] -struct ExtendedThemePalette { - background: Option, - primary: Option, - secondary: Option, - success: Option, - danger: Option, - warning: Option, -} - -#[derive(Debug, Clone, Copy, Default, Deserialize)] -struct ThemeBackground { - base: Option, - weak: Option, - strong: Option, -} - -#[derive(Debug, Clone, Copy, Default, Deserialize)] -struct ThemePrimary { - base: Option, - weak: Option, - strong: Option, -} - -#[derive(Debug, Clone, Copy, Default, Deserialize)] -struct ThemeSecondary { - base: Option, - weak: Option, - strong: Option, -} - -#[derive(Debug, Clone, Copy, Default, Deserialize)] -struct ThemeSuccess { - base: Option, - weak: Option, - strong: Option, -} - -#[derive(Debug, Clone, Copy, Default, Deserialize)] -struct ThemeDanger { - base: Option, - weak: Option, - strong: Option, -} - -#[derive(Debug, Clone, Copy, Default, Deserialize)] -struct ThemeWarning { - base: Option, - weak: Option, - strong: Option, -} - -#[derive(Debug, Clone, Copy, Default, Deserialize)] -struct ThemePair { - #[serde(with = "color_serde")] - color: Color, - #[serde(with = "color_serde")] - text: Color, -} - -impl From for iced::theme::palette::Pair { - fn from(pair: ThemePair) -> Self { - Self { - color: pair.color, - text: pair.text, - } - } -} - -pub fn parse_argb(s: &str) -> Option { - let hex = s.strip_prefix('#').unwrap_or(s); - - let parse_channel = |from: usize, to: usize| { - let num = - usize::from_str_radix(&hex[from..=to], 16).ok()? as f32 / 255.0; - - // If we only got half a byte (one letter), expand it into a full byte (two letters) - Some(if from == to { num + num * 16.0 } else { num }) - }; - - Some(match hex.len() { - 3 => Color::from_rgb( - parse_channel(0, 0)?, - parse_channel(1, 1)?, - parse_channel(2, 2)?, - ), - 4 => Color::from_rgba( - parse_channel(1, 1)?, - parse_channel(2, 2)?, - parse_channel(3, 3)?, - parse_channel(0, 0)?, - ), - 6 => Color::from_rgb( - parse_channel(0, 1)?, - parse_channel(2, 3)?, - parse_channel(4, 5)?, - ), - 8 => Color::from_rgba( - parse_channel(2, 3)?, - parse_channel(4, 5)?, - parse_channel(6, 7)?, - parse_channel(0, 1)?, - ), - _ => None?, - }) -} - -mod color_serde { - use iced::Color; - use serde::{Deserialize, Deserializer}; - - use super::parse_argb; - - pub fn deserialize<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(String::deserialize(deserializer) - .map(|hex| parse_argb(&hex))? - .unwrap_or(Color::TRANSPARENT)) - } -} diff --git a/src/types.rs b/src/types.rs index adb788e..608f285 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,16 +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 { ConfigLoad(Result), - SwitchTheme(Event), + SwitchTheme(Event), CopyCode, SwitchPage(DesignerPane), EditorAction(text_editor::Action), diff --git a/src/types/project.rs b/src/types/project.rs index 91b2bb1..11789ac 100644 --- a/src/types/project.rs +++ b/src/types/project.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use super::rendered_element::RenderedElement; use crate::Error; -use crate::theme::{theme_from_str, theme_index}; +use crate::appearance::iced_theme_from_str; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Project { @@ -33,8 +33,8 @@ impl Project { pub fn get_theme(&self) -> Theme { match &self.theme { - Some(theme) => theme_from_str(None, theme), - None => Theme::default(), + Some(theme) => iced_theme_from_str(theme), + None => iced::Theme::default(), } } @@ -90,20 +90,10 @@ impl Project { Some(ref element_tree) => { let (imports, view) = element_tree.codegen(); let theme = self.get_theme(); - let theme_code = theme.to_string().replace(" ", ""); - 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 app_code = format!( r#"// Automatically generated by iced Builder use iced::{{widget::{{{imports}}},Element}}; -{theme_imports} fn main() -> iced::Result {{ iced::application(State::default, State::update, State::view).title("{}").theme(State::theme).run() @@ -130,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) diff --git a/src/types/rendered_element.rs b/src/types/rendered_element.rs index 9639299..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(); diff --git a/src/widget.rs b/src/widget.rs index f1eb0f3..859d25e 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1,5 +1,7 @@ -use iced::Element; -use iced::widget::{container, text, tooltip}; +use iced::widget::{self, container, text, tooltip}; +use material_theme::Theme; + +use crate::types::Element; pub mod tip { pub use super::tooltip::Position; @@ -12,10 +14,16 @@ pub fn tip<'a, Message: 'a>( ) -> Element<'a, Message> { tooltip( target, - container(text(tip).size(14)) - .padding(5) - .style(container::rounded_box), + container(text(tip).size(14)).padding(5).style(|theme| { + let base = material_theme::container::surface_container_low(theme); + container::Style { + border: iced::border::rounded(4), + ..base + } + }), position, ) .into() } + +pub type Text<'a> = widget::Text<'a, Theme>; diff --git a/theme_test/src/main.rs b/theme_test/src/main.rs index b4a7731..cba4377 100644 --- a/theme_test/src/main.rs +++ b/theme_test/src/main.rs @@ -18,7 +18,7 @@ use material_theme::text::surface_variant; fn main() -> iced::Result { iced::application(State::default, State::update, State::view) - .theme(|state| *state.theme.value()) + .theme(|state| state.theme.value().clone()) .run() } -- cgit v1.2.3