diff --git a/Cargo.lock b/Cargo.lock
index 7844227..4b37534 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -246,9 +246,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.83"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
+checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
[[package]]
name = "apply"
@@ -508,7 +508,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -543,7 +543,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -746,7 +746,7 @@ checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -836,6 +836,46 @@ dependencies = [
"windows-targets 0.52.6",
]
+[[package]]
+name = "clap"
+version = "4.5.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim 0.11.1",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
+dependencies = [
+ "heck 0.5.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.85",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+
[[package]]
name = "clipboard-win"
version = "5.3.1"
@@ -1036,15 +1076,33 @@ dependencies = [
"libc",
]
+[[package]]
+name = "cosmic-config"
+version = "0.1.0"
+source = "git+https://github.com/pop-os/libcosmic.git?branch=master#4b562867eccb65895953023a19393fa293aafb4b"
+dependencies = [
+ "atomicwrites",
+ "cosmic-config-derive 0.1.0 (git+https://github.com/pop-os/libcosmic.git?branch=master)",
+ "dirs",
+ "iced_futures 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git?branch=master)",
+ "known-folders",
+ "notify",
+ "once_cell",
+ "ron",
+ "serde",
+ "tracing",
+ "xdg",
+]
+
[[package]]
name = "cosmic-config"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic.git#4b562867eccb65895953023a19393fa293aafb4b"
dependencies = [
"atomicwrites",
- "cosmic-config-derive",
+ "cosmic-config-derive 0.1.0 (git+https://github.com/pop-os/libcosmic.git)",
"dirs",
- "iced_futures",
+ "iced_futures 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
"known-folders",
"notify",
"once_cell",
@@ -1055,6 +1113,15 @@ dependencies = [
"xdg",
]
+[[package]]
+name = "cosmic-config-derive"
+version = "0.1.0"
+source = "git+https://github.com/pop-os/libcosmic.git?branch=master#4b562867eccb65895953023a19393fa293aafb4b"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
[[package]]
name = "cosmic-config-derive"
version = "0.1.0"
@@ -1064,13 +1131,30 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "cosmic-ext-config-templates"
+version = "2.0.0"
+source = "git+https://github.com/ryanabx/cosmic-ext-config-templates#5e2ab667aa5a70ce4a63405e0e54369cc257a38a"
+dependencies = [
+ "anyhow",
+ "clap",
+ "cosmic-config 0.1.0 (git+https://github.com/pop-os/libcosmic.git?branch=master)",
+ "cosmic-panel-config 0.1.0 (git+https://github.com/pop-os/cosmic-panel?branch=master)",
+ "env_logger 0.11.5",
+ "log",
+ "ron",
+ "serde",
+ "walkdir",
+]
+
[[package]]
name = "cosmic-ext-tweaks"
version = "0.1.1"
dependencies = [
"anyhow",
"ashpd 0.8.1",
- "cosmic-panel-config",
+ "cosmic-ext-config-templates",
+ "cosmic-panel-config 0.1.0 (git+https://github.com/pop-os/cosmic-panel)",
"dirs",
"env_logger 0.11.5",
"i18n-embed",
@@ -1092,16 +1176,31 @@ dependencies = [
[[package]]
name = "cosmic-panel-config"
version = "0.1.0"
-source = "git+https://github.com/pop-os/cosmic-panel#1495bfa2abc4057129c7c3b0e8530b3afd853204"
+source = "git+https://github.com/pop-os/cosmic-panel?branch=master#041a44eb6f825b7e0b3d45ccf745252b136d5da9"
dependencies = [
"anyhow",
- "cosmic-config",
+ "cosmic-config 0.1.0 (git+https://github.com/pop-os/libcosmic.git)",
"ron",
"serde",
- "smithay-client-toolkit 0.18.0",
+ "smithay-client-toolkit",
"tracing",
- "wayland-protocols-wlr 0.2.0",
- "xdg-shell-wrapper-config",
+ "wayland-protocols-wlr",
+ "xdg-shell-wrapper-config 0.1.0 (git+https://github.com/pop-os/cosmic-panel?branch=master)",
+]
+
+[[package]]
+name = "cosmic-panel-config"
+version = "0.1.0"
+source = "git+https://github.com/pop-os/cosmic-panel#041a44eb6f825b7e0b3d45ccf745252b136d5da9"
+dependencies = [
+ "anyhow",
+ "cosmic-config 0.1.0 (git+https://github.com/pop-os/libcosmic.git)",
+ "ron",
+ "serde",
+ "smithay-client-toolkit",
+ "tracing",
+ "wayland-protocols-wlr",
+ "xdg-shell-wrapper-config 0.1.0 (git+https://github.com/pop-os/cosmic-panel)",
]
[[package]]
@@ -1133,7 +1232,7 @@ version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic.git#4b562867eccb65895953023a19393fa293aafb4b"
dependencies = [
"almost",
- "cosmic-config",
+ "cosmic-config 0.1.0 (git+https://github.com/pop-os/libcosmic.git)",
"csscolorparser",
"dirs",
"lazy_static",
@@ -1272,7 +1371,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -1283,7 +1382,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
dependencies = [
"darling_core",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -1334,7 +1433,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -1382,7 +1481,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -1411,7 +1510,7 @@ dependencies = [
"bitflags 2.6.0",
"mime 0.1.0",
"raw-window-handle",
- "smithay-client-toolkit 0.19.2",
+ "smithay-client-toolkit",
"smithay-clipboard",
]
@@ -1513,7 +1612,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -1873,7 +1972,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -2014,7 +2113,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -2260,6 +2359,12 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
[[package]]
name = "hermit-abi"
version = "0.3.9"
@@ -2456,7 +2561,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.10.0",
- "syn 2.0.63",
+ "syn 2.0.85",
"unic-langid",
]
@@ -2470,7 +2575,7 @@ dependencies = [
"i18n-config",
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -2503,8 +2608,8 @@ source = "git+https://github.com/pop-os/libcosmic.git#4b562867eccb65895953023a19
dependencies = [
"dnd",
"iced_accessibility",
- "iced_core",
- "iced_futures",
+ "iced_core 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
+ "iced_futures 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
"iced_renderer",
"iced_widget",
"iced_winit",
@@ -2523,6 +2628,28 @@ dependencies = [
"accesskit_winit",
]
+[[package]]
+name = "iced_core"
+version = "0.14.0-dev"
+source = "git+https://github.com/pop-os/libcosmic.git?branch=master#4b562867eccb65895953023a19393fa293aafb4b"
+dependencies = [
+ "bitflags 2.6.0",
+ "bytes",
+ "dnd",
+ "glam",
+ "log",
+ "mime 0.1.0",
+ "num-traits",
+ "once_cell",
+ "palette",
+ "raw-window-handle",
+ "rustc-hash 2.0.0",
+ "smol_str",
+ "thiserror",
+ "web-time",
+ "window_clipboard",
+]
+
[[package]]
name = "iced_core"
version = "0.14.0-dev"
@@ -2546,13 +2673,26 @@ dependencies = [
"window_clipboard",
]
+[[package]]
+name = "iced_futures"
+version = "0.14.0-dev"
+source = "git+https://github.com/pop-os/libcosmic.git?branch=master#4b562867eccb65895953023a19393fa293aafb4b"
+dependencies = [
+ "futures",
+ "iced_core 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git?branch=master)",
+ "log",
+ "rustc-hash 2.0.0",
+ "wasm-bindgen-futures",
+ "wasm-timer",
+]
+
[[package]]
name = "iced_futures"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic.git#4b562867eccb65895953023a19393fa293aafb4b"
dependencies = [
"futures",
- "iced_core",
+ "iced_core 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
"log",
"rustc-hash 2.0.0",
"tokio",
@@ -2581,8 +2721,8 @@ dependencies = [
"bytemuck",
"cosmic-text",
"half",
- "iced_core",
- "iced_futures",
+ "iced_core 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
+ "iced_futures 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
"image",
"kamadak-exif",
"log",
@@ -2613,8 +2753,8 @@ source = "git+https://github.com/pop-os/libcosmic.git#4b562867eccb65895953023a19
dependencies = [
"bytes",
"dnd",
- "iced_core",
- "iced_futures",
+ "iced_core 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
+ "iced_futures 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
"raw-window-handle",
"thiserror",
"window_clipboard",
@@ -2656,12 +2796,12 @@ dependencies = [
"resvg",
"rustc-hash 2.0.0",
"rustix 0.38.34",
- "smithay-client-toolkit 0.19.2",
+ "smithay-client-toolkit",
"thiserror",
"tiny-xlib",
"wayland-backend",
"wayland-client",
- "wayland-protocols 0.32.3",
+ "wayland-protocols",
"wayland-sys",
"wgpu",
"x11rb",
@@ -2690,7 +2830,7 @@ version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic.git#4b562867eccb65895953023a19393fa293aafb4b"
dependencies = [
"dnd",
- "iced_futures",
+ "iced_futures 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
"iced_graphics",
"iced_runtime",
"log",
@@ -3035,15 +3175,15 @@ dependencies = [
"apply",
"ashpd 0.9.1",
"chrono",
- "cosmic-config",
+ "cosmic-config 0.1.0 (git+https://github.com/pop-os/libcosmic.git)",
"cosmic-theme",
"css-color",
"derive_setters",
"fraction",
"freedesktop-icons",
"iced",
- "iced_core",
- "iced_futures",
+ "iced_core 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
+ "iced_futures 0.14.0-dev (git+https://github.com/pop-os/libcosmic.git)",
"iced_renderer",
"iced_runtime",
"iced_tiny_skia",
@@ -3072,7 +3212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
dependencies = [
"cfg-if",
- "windows-targets 0.52.6",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -3550,7 +3690,7 @@ dependencies = [
"proc-macro-crate 3.1.0",
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -3843,7 +3983,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -3916,12 +4056,12 @@ version = "0.18.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39b0deead1528fd0e5947a8546a9642a9777c25f6e1e26f34c97b204bbb465bd"
dependencies = [
- "heck",
+ "heck 0.4.1",
"itertools",
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -3955,7 +4095,7 @@ dependencies = [
"by_address",
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -4060,7 +4200,7 @@ dependencies = [
"phf_shared",
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -4095,7 +4235,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -4250,9 +4390,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.82"
+version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
@@ -4265,7 +4405,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
"version_check",
"yansi",
]
@@ -4604,7 +4744,7 @@ dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
- "syn 2.0.63",
+ "syn 2.0.85",
"walkdir",
]
@@ -4781,7 +4921,7 @@ dependencies = [
"ab_glyph",
"log",
"memmap2 0.9.4",
- "smithay-client-toolkit 0.19.2",
+ "smithay-client-toolkit",
"tiny-skia",
]
@@ -4825,22 +4965,22 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a"
[[package]]
name = "serde"
-version = "1.0.202"
+version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395"
+checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.202"
+version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
+checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -4864,7 +5004,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -4980,33 +5120,6 @@ version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
-[[package]]
-name = "smithay-client-toolkit"
-version = "0.18.0"
-source = "git+https://github.com/smithay/client-toolkit?rev=3bed072#3bed072b966022f5f929d12f3aff089b1ace980b"
-dependencies = [
- "bitflags 2.6.0",
- "bytemuck",
- "calloop",
- "calloop-wayland-source",
- "cursor-icon",
- "libc",
- "log",
- "memmap2 0.9.4",
- "pkg-config",
- "rustix 0.38.34",
- "thiserror",
- "wayland-backend",
- "wayland-client",
- "wayland-csd-frame",
- "wayland-cursor",
- "wayland-protocols 0.31.2",
- "wayland-protocols-wlr 0.2.0",
- "wayland-scanner",
- "xkbcommon",
- "xkeysym",
-]
-
[[package]]
name = "smithay-client-toolkit"
version = "0.19.2"
@@ -5028,8 +5141,8 @@ dependencies = [
"wayland-client",
"wayland-csd-frame",
"wayland-cursor",
- "wayland-protocols 0.32.3",
- "wayland-protocols-wlr 0.3.3",
+ "wayland-protocols",
+ "wayland-protocols-wlr",
"wayland-scanner",
"xkbcommon",
"xkeysym",
@@ -5042,7 +5155,7 @@ source = "git+https://github.com/pop-os/smithay-clipboard?tag=pop-dnd-5#5a3007de
dependencies = [
"libc",
"raw-window-handle",
- "smithay-client-toolkit 0.19.2",
+ "smithay-client-toolkit",
"wayland-backend",
]
@@ -5196,9 +5309,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.63"
+version = "2.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704"
+checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
dependencies = [
"proc-macro2",
"quote",
@@ -5293,7 +5406,7 @@ checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -5439,7 +5552,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -5598,7 +5711,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -5895,7 +6008,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
"wasm-bindgen-shared",
]
@@ -5929,7 +6042,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -6003,19 +6116,6 @@ dependencies = [
"xcursor",
]
-[[package]]
-name = "wayland-protocols"
-version = "0.31.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4"
-dependencies = [
- "bitflags 2.6.0",
- "wayland-backend",
- "wayland-client",
- "wayland-scanner",
- "wayland-server",
-]
-
[[package]]
name = "wayland-protocols"
version = "0.32.3"
@@ -6026,6 +6126,7 @@ dependencies = [
"wayland-backend",
"wayland-client",
"wayland-scanner",
+ "wayland-server",
]
[[package]]
@@ -6037,24 +6138,10 @@ dependencies = [
"bitflags 2.6.0",
"wayland-backend",
"wayland-client",
- "wayland-protocols 0.32.3",
+ "wayland-protocols",
"wayland-scanner",
]
-[[package]]
-name = "wayland-protocols-wlr"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6"
-dependencies = [
- "bitflags 2.6.0",
- "wayland-backend",
- "wayland-client",
- "wayland-protocols 0.31.2",
- "wayland-scanner",
- "wayland-server",
-]
-
[[package]]
name = "wayland-protocols-wlr"
version = "0.3.3"
@@ -6064,8 +6151,9 @@ dependencies = [
"bitflags 2.6.0",
"wayland-backend",
"wayland-client",
- "wayland-protocols 0.32.3",
+ "wayland-protocols",
"wayland-scanner",
+ "wayland-server",
]
[[package]]
@@ -6081,9 +6169,9 @@ dependencies = [
[[package]]
name = "wayland-server"
-version = "0.31.1"
+version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00e6e4d5c285bc24ba4ed2d5a4bd4febd5fd904451f465973225c8e99772fdb7"
+checksum = "2f0a4bab6d420ee4a609b63ef4d5f9b5d309c6b93a029fccab70f2594c0cb3ae"
dependencies = [
"bitflags 2.6.0",
"downcast-rs",
@@ -6338,7 +6426,7 @@ checksum = "942ac266be9249c84ca862f0a164a39533dc2f6f33dc98ec89c8da99b82ea0bd"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -6349,7 +6437,7 @@ checksum = "da33557140a288fae4e1d5f8873aaf9eb6613a9cf82c3e070223ff177f598b60"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
@@ -6638,7 +6726,7 @@ dependencies = [
"redox_syscall 0.4.1",
"rustix 0.38.34",
"sctk-adwaita",
- "smithay-client-toolkit 0.19.2",
+ "smithay-client-toolkit",
"smol_str",
"tracing",
"unicode-segmentation",
@@ -6646,7 +6734,7 @@ dependencies = [
"wasm-bindgen-futures",
"wayland-backend",
"wayland-client",
- "wayland-protocols 0.32.3",
+ "wayland-protocols",
"wayland-protocols-plasma",
"web-sys",
"web-time",
@@ -6731,10 +6819,19 @@ dependencies = [
[[package]]
name = "xdg-shell-wrapper-config"
version = "0.1.0"
-source = "git+https://github.com/pop-os/xdg-shell-wrapper#b5480042615ecfcf30262d5a40625e8f430b474a"
+source = "git+https://github.com/pop-os/cosmic-panel?branch=master#041a44eb6f825b7e0b3d45ccf745252b136d5da9"
+dependencies = [
+ "serde",
+ "wayland-protocols-wlr",
+]
+
+[[package]]
+name = "xdg-shell-wrapper-config"
+version = "0.1.0"
+source = "git+https://github.com/pop-os/cosmic-panel#041a44eb6f825b7e0b3d45ccf745252b136d5da9"
dependencies = [
"serde",
- "wayland-protocols-wlr 0.2.0",
+ "wayland-protocols-wlr",
]
[[package]]
@@ -6941,7 +7038,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.63",
+ "syn 2.0.85",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index b196825..63772d3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.1.1"
edition = "2021"
[dependencies]
-anyhow = "1.0.82"
ashpd = "0.8.1"
dirs = "5.0.1"
env_logger = "0.11.5"
@@ -17,12 +16,16 @@ reqwest = { version = "0.12", features = ["json"] }
ron = "0.8.1"
rust-embed = "8.3.0"
paste = "1.0"
+anyhow = "1.0.91"
[dependencies.libcosmic]
git = "https://github.com/pop-os/libcosmic.git"
default-features = false
features = ["multi-window", "tokio", "winit", "wgpu"]
+[dependencies.cosmic-ext-config-templates]
+git = "https://github.com/ryanabx/cosmic-ext-config-templates"
+
[dependencies.i18n-embed]
version = "0.14"
features = ["fluent-system", "desktop-requester"]
diff --git a/i18n/en/cosmic_ext_tweaks.ftl b/i18n/en/cosmic_ext_tweaks.ftl
index 066762c..6425c98 100644
--- a/i18n/en/cosmic_ext_tweaks.ftl
+++ b/i18n/en/cosmic_ext_tweaks.ftl
@@ -4,10 +4,12 @@ app-description = A tool to customize your COSMIC desktop experience.
home = Home
dock = Dock
panel = Panel
+layouts = Layouts
color-schemes = Color schemes
color-schemes-error = Error loading color schemes
import-color-scheme = Import color scheme
delete-color-scheme = Delete color scheme
+delete-layout = Delete layout
install-color-scheme = Install color scheme
find-color-schemes = Find color schemes
open-containing-folder = Open containing folder
@@ -33,6 +35,7 @@ spacing-description = Spacing is the space between the icons in the dock or pane
save = Save
cancel = Cancel
save-current-color-scheme = Save current color scheme
+save-current-layout = Save current layout
color-scheme-name = Color scheme name
## About
diff --git a/res/icons/bundled/view-coverflow-symbolic.svg b/res/icons/bundled/view-coverflow-symbolic.svg
new file mode 100644
index 0000000..b146e30
--- /dev/null
+++ b/res/icons/bundled/view-coverflow-symbolic.svg
@@ -0,0 +1 @@
+
diff --git a/res/layouts/cosmic.ron b/res/layouts/cosmic.ron
new file mode 100644
index 0000000..c4eb65b
--- /dev/null
+++ b/res/layouts/cosmic.ron
@@ -0,0 +1,79 @@
+Panel((
+ panel_config: (
+ config_list: [
+ (
+ name: "Panel",
+ anchor: Top,
+ anchor_gap: false,
+ layer: Top,
+ keyboard_interactivity: OnDemand,
+ size: XS,
+ output: All,
+ background: ThemeDefault,
+ plugins_wings: Some(([
+ "com.system76.CosmicPanelWorkspacesButton",
+ "com.system76.CosmicPanelAppButton",
+ ], [
+ "com.system76.CosmicAppletInputSources",
+ "com.system76.CosmicAppletStatusArea",
+ "com.system76.CosmicAppletTiling",
+ "com.system76.CosmicAppletAudio",
+ "com.system76.CosmicAppletNetwork",
+ "com.system76.CosmicAppletBattery",
+ "com.system76.CosmicAppletNotifications",
+ "com.system76.CosmicAppletBluetooth",
+ "com.system76.CosmicAppletPower",
+ ])),
+ plugins_center: Some([
+ "com.system76.CosmicAppletTime",
+ ]),
+ expand_to_edges: true,
+ padding: 0,
+ spacing: 2,
+ border_radius: 0,
+ exclusive_zone: true,
+ autohide: None,
+ margin: 0,
+ opacity: 1.0,
+ ),
+ (
+ name: "Dock",
+ anchor: Bottom,
+ anchor_gap: false,
+ layer: Top,
+ keyboard_interactivity: OnDemand,
+ size: L,
+ output: All,
+ background: ThemeDefault,
+ plugins_wings: None,
+ plugins_center: Some([
+ "com.system76.CosmicPanelLauncherButton",
+ "com.system76.CosmicPanelWorkspacesButton",
+ "com.system76.CosmicPanelAppButton",
+ "com.system76.CosmicAppList",
+ "com.system76.CosmicAppletMinimize",
+ ]),
+ expand_to_edges: true,
+ padding: 0,
+ spacing: 4,
+ border_radius: 0,
+ exclusive_zone: true,
+ autohide: None,
+ margin: 0,
+ opacity: 1.0,
+ ),
+ ],
+ ),
+ panel_config_version: 1,
+ panel_button_config: (
+ configs: {
+ "Dock": (
+ force_presentation: Some(Icon),
+ ),
+ "Panel": (
+ force_presentation: None,
+ ),
+ },
+ ),
+ panel_button_config_version: 1,
+))
\ No newline at end of file
diff --git a/res/layouts/mac.ron b/res/layouts/mac.ron
new file mode 100644
index 0000000..61c7305
--- /dev/null
+++ b/res/layouts/mac.ron
@@ -0,0 +1,71 @@
+Panel((
+ panel_config: (
+ config_list: [
+ (
+ name: "Panel",
+ anchor: Top,
+ anchor_gap: false,
+ layer: Top,
+ keyboard_interactivity: OnDemand,
+ size: XS,
+ output: All,
+ background: ThemeDefault,
+ plugins_wings: Some(([
+ "com.system76.CosmicAppletPower",
+ ], [
+ "com.system76.CosmicAppletStatusArea",
+ "com.system76.CosmicAppletBattery",
+ "com.system76.CosmicAppletNetwork",
+ "com.system76.CosmicPanelLauncherButton",
+ "com.system76.CosmicAppletNotifications",
+ "com.system76.CosmicAppletTime",
+ ])),
+ plugins_center: Some([]),
+ expand_to_edges: true,
+ padding: 4,
+ spacing: 4,
+ border_radius: 0,
+ exclusive_zone: true,
+ autohide: None,
+ margin: 0,
+ opacity: 0.91,
+ ),
+ (
+ name: "Dock",
+ anchor: Bottom,
+ anchor_gap: true,
+ layer: Top,
+ keyboard_interactivity: OnDemand,
+ size: S,
+ output: All,
+ background: ThemeDefault,
+ plugins_wings: Some(([], [])),
+ plugins_center: Some([
+ "com.system76.CosmicAppList",
+ "com.system76.CosmicPanelAppButton",
+ "com.system76.CosmicAppletMinimize",
+ ]),
+ expand_to_edges: false,
+ padding: 6,
+ spacing: 4,
+ border_radius: 8,
+ exclusive_zone: true,
+ autohide: None,
+ margin: 4,
+ opacity: 1.0,
+ ),
+ ],
+ ),
+ panel_config_version: 1,
+ panel_button_config: (
+ configs: {
+ "Panel": (
+ force_presentation: Some(Icon),
+ ),
+ "Dock": (
+ force_presentation: Some(Icon),
+ ),
+ },
+ ),
+ panel_button_config_version: 1,
+))
\ No newline at end of file
diff --git a/res/layouts/ubuntu.ron b/res/layouts/ubuntu.ron
new file mode 100644
index 0000000..8b25592
--- /dev/null
+++ b/res/layouts/ubuntu.ron
@@ -0,0 +1,79 @@
+Panel((
+ panel_config: (
+ config_list: [
+ (
+ name: "Panel",
+ anchor: Top,
+ anchor_gap: false,
+ layer: Top,
+ keyboard_interactivity: OnDemand,
+ size: XS,
+ output: All,
+ background: ThemeDefault,
+ plugins_wings: Some(([
+ "com.system76.CosmicPanelWorkspacesButton",
+ "com.system76.CosmicPanelAppButton",
+ ], [
+ "com.system76.CosmicAppletInputSources",
+ "com.system76.CosmicAppletStatusArea",
+ "com.system76.CosmicAppletTiling",
+ "com.system76.CosmicAppletAudio",
+ "com.system76.CosmicAppletNetwork",
+ "com.system76.CosmicAppletBattery",
+ "com.system76.CosmicAppletNotifications",
+ "com.system76.CosmicAppletBluetooth",
+ "com.system76.CosmicAppletPower",
+ ])),
+ plugins_center: Some([
+ "com.system76.CosmicAppletTime",
+ ]),
+ expand_to_edges: true,
+ padding: 0,
+ spacing: 2,
+ border_radius: 0,
+ exclusive_zone: true,
+ autohide: None,
+ margin: 0,
+ opacity: 1.0,
+ ),
+ (
+ name: "Dock",
+ anchor: Left,
+ anchor_gap: false,
+ layer: Top,
+ keyboard_interactivity: OnDemand,
+ size: M,
+ output: All,
+ background: ThemeDefault,
+ plugins_wings: Some(([
+ "com.system76.CosmicPanelLauncherButton",
+ "com.system76.CosmicPanelWorkspacesButton",
+ "com.system76.CosmicPanelAppButton",
+ "com.system76.CosmicAppList",
+ "com.system76.CosmicAppletMinimize",
+ ], [])),
+ plugins_center: Some([]),
+ expand_to_edges: true,
+ padding: 0,
+ spacing: 4,
+ border_radius: 0,
+ exclusive_zone: true,
+ autohide: None,
+ margin: 0,
+ opacity: 1.0,
+ ),
+ ],
+ ),
+ panel_config_version: 1,
+ panel_button_config: (
+ configs: {
+ "Panel": (
+ force_presentation: None,
+ ),
+ "Dock": (
+ force_presentation: Some(Icon),
+ ),
+ },
+ ),
+ panel_button_config_version: 1,
+))
\ No newline at end of file
diff --git a/res/layouts/windows.ron b/res/layouts/windows.ron
new file mode 100644
index 0000000..e50673f
--- /dev/null
+++ b/res/layouts/windows.ron
@@ -0,0 +1,50 @@
+Panel((
+ panel_config: (
+ config_list: [
+ (
+ name: "Panel",
+ anchor: Bottom,
+ anchor_gap: false,
+ layer: Top,
+ keyboard_interactivity: OnDemand,
+ size: S,
+ output: All,
+ background: ThemeDefault,
+ plugins_wings: Some(([
+ "com.system76.CosmicAppletPower",
+ ], [
+ "com.system76.CosmicAppletNetwork",
+ "com.system76.CosmicAppletAudio",
+ "com.system76.CosmicAppletBattery",
+ "com.system76.CosmicAppletTime",
+ "com.system76.CosmicAppletNotifications",
+ ])),
+ plugins_center: Some([
+ "com.system76.CosmicPanelAppButton",
+ "com.system76.CosmicPanelLauncherButton",
+ "com.system76.CosmicAppList",
+ ]),
+ expand_to_edges: true,
+ padding: 4,
+ spacing: 4,
+ border_radius: 0,
+ exclusive_zone: true,
+ autohide: None,
+ margin: 0,
+ opacity: 0.91,
+ ),
+ ],
+ ),
+ panel_config_version: 1,
+ panel_button_config: (
+ configs: {
+ "Dock": (
+ force_presentation: Some(Icon),
+ ),
+ "Panel": (
+ force_presentation: Some(Icon),
+ ),
+ },
+ ),
+ panel_button_config_version: 1,
+))
\ No newline at end of file
diff --git a/src/app.rs b/src/app.rs
index 5595566..a3319ab 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -1,12 +1,20 @@
-use std::collections::{HashMap, VecDeque};
+use std::{
+ any::TypeId,
+ collections::{HashMap, VecDeque},
+};
use cosmic::{
app::{self, Core},
- cosmic_config,
- iced::{Alignment, Length},
+ cosmic_config::{self, Update},
+ cosmic_theme::{self, ThemeMode},
+ iced::{
+ event,
+ keyboard::{Event as KeyEvent, Key, Modifiers},
+ Alignment, Event, Length, Subscription,
+ },
widget::{
self,
- menu::{self, KeyBind},
+ menu::{self, Action, KeyBind},
segmented_button,
},
Application, ApplicationExt, Apply, Element, Task,
@@ -20,19 +28,23 @@ use crate::{
pages::{
self,
color_schemes::{config::ColorScheme, preview, ColorSchemeProvider, ColorSchemes},
+ layouts::Layouts,
},
- settings::{AppTheme, TweaksSettings},
+ settings::{AppTheme, TweaksSettings, CONFIG_VERSION},
};
mod key_bind;
+pub mod style;
pub struct TweakTool {
core: Core,
nav_model: segmented_button::SingleSelectModel,
dialog_pages: VecDeque,
dialog_text_input: widget::Id,
- key_binds: HashMap,
+ key_binds: HashMap,
+ modifiers: Modifiers,
color_schemes: ColorSchemes,
+ layouts: Layouts,
context_page: ContextPage,
app_themes: Vec,
config_handler: Option,
@@ -51,15 +63,18 @@ pub enum Status {
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DialogPage {
- New(String),
+ SaveCurrentColorScheme(String),
+ SaveCurrentLayout(String),
}
#[derive(Debug, Clone)]
pub enum Message {
Dock(pages::dock::Message),
Panel(pages::panel::Message),
+ Layouts(pages::layouts::Message),
ColorSchemes(Box),
- OpenSaveDialog,
+ OpenSaveCurrentColorScheme,
+ OpenSaveCurrentLayout,
DialogUpdate(DialogPage),
DialogComplete,
DialogCancel,
@@ -69,6 +84,10 @@ pub enum Message {
AppTheme(usize),
FetchAvailableColorSchemes(ColorSchemeProvider, usize),
SetAvailableColorSchemes(Vec),
+ Key(Modifiers, Key),
+ Modifiers(Modifiers),
+ SystemThemeModeChange,
+ SaveNewLayout(String),
}
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -89,17 +108,17 @@ impl ContextPage {
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum Action {
+pub enum TweaksAction {
About,
Settings,
}
-impl cosmic::widget::menu::Action for Action {
+impl Action for TweaksAction {
type Message = Message;
fn message(&self) -> Self::Message {
match self {
- Action::About => Message::ToggleContextPage(ContextPage::About),
- Action::Settings => Message::ToggleContextPage(ContextPage::Settings),
+ TweaksAction::About => Message::ToggleContextPage(ContextPage::About),
+ TweaksAction::Settings => Message::ToggleContextPage(ContextPage::Settings),
}
}
}
@@ -133,8 +152,8 @@ impl Application for TweakTool {
menu::items(
&self.key_binds,
vec![
- menu::Item::Button(fl!("settings"), Action::Settings),
- menu::Item::Button(fl!("about"), Action::About),
+ menu::Item::Button(fl!("settings"), TweaksAction::Settings),
+ menu::Item::Button(fl!("about"), TweaksAction::About),
],
),
)]);
@@ -178,27 +197,33 @@ impl Application for TweakTool {
let spacing = cosmic::theme::active().cosmic().spacing;
- let dialog = match dialog_page {
- DialogPage::New(name) => widget::dialog(fl!("save-current-color-scheme"))
- .primary_action(
- widget::button::suggested(fl!("save"))
- .on_press_maybe(Some(Message::DialogComplete)),
- )
- .secondary_action(
- widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
- )
- .control(
- widget::column::with_children(vec![
- widget::text::body(fl!("color-scheme-name")).into(),
- widget::text_input("", name.as_str())
- .id(self.dialog_text_input.clone())
- .on_input(move |name| Message::DialogUpdate(DialogPage::New(name)))
- .into(),
- ])
- .spacing(spacing.space_xxs),
- ),
+ let text_input = match dialog_page {
+ DialogPage::SaveCurrentColorScheme(name) => widget::text_input("", name.as_str())
+ .id(self.dialog_text_input.clone())
+ .on_input(move |name| {
+ Message::DialogUpdate(DialogPage::SaveCurrentColorScheme(name))
+ }),
+ DialogPage::SaveCurrentLayout(name) => widget::text_input("", name.as_str())
+ .id(self.dialog_text_input.clone())
+ .on_input(move |name| Message::DialogUpdate(DialogPage::SaveCurrentLayout(name))),
};
+ let dialog = widget::dialog(fl!("save-current-color-scheme"))
+ .primary_action(
+ widget::button::suggested(fl!("save"))
+ .on_press_maybe(Some(Message::DialogComplete)),
+ )
+ .secondary_action(
+ widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
+ )
+ .control(
+ widget::column::with_children(vec![
+ widget::text::body(fl!("color-scheme-name")).into(),
+ text_input.into(),
+ ])
+ .spacing(spacing.space_xxs),
+ );
+
Some(dialog.into())
}
@@ -225,7 +250,9 @@ impl Application for TweakTool {
dialog_pages: VecDeque::new(),
dialog_text_input: widget::Id::unique(),
key_binds: key_binds(),
+ modifiers: Modifiers::empty(),
color_schemes: ColorSchemes::default(),
+ layouts: Layouts::default(),
context_page: ContextPage::About,
app_themes: vec![fl!("match-desktop"), fl!("dark"), fl!("light")],
config_handler: flags.config_handler,
@@ -257,6 +284,7 @@ impl Application for TweakTool {
.map(Message::ColorSchemes),
NavPage::Dock => pages::dock::Dock::default().view().map(Message::Dock),
NavPage::Panel => pages::panel::Panel::default().view().map(Message::Panel),
+ NavPage::Layouts => self.layouts.view().map(Message::Layouts),
};
widget::column::with_children(vec![view])
@@ -304,9 +332,9 @@ impl Application for TweakTool {
self.status = Status::LoadingMore;
}
self.limit = limit;
- self.offset = self.offset + self.limit;
- let limit = self.limit.clone();
- let offset = self.offset.clone();
+ self.offset += self.limit;
+ let limit = self.limit;
+ let offset = self.offset;
commands.push(Task::perform(
async move {
let url = match provider {
@@ -370,9 +398,15 @@ impl Application for TweakTool {
.update(message)
.map(cosmic::app::Message::App),
),
+ Message::Layouts(message) => match message {
+ pages::layouts::Message::OpenSaveDialog => {
+ commands.push(self.update(Message::OpenSaveCurrentLayout))
+ }
+ _ => commands.push(self.layouts.update(message).map(cosmic::app::Message::App)),
+ },
Message::ColorSchemes(message) => match *message {
pages::color_schemes::Message::SaveCurrentColorScheme(None) => {
- commands.push(self.update(Message::OpenSaveDialog))
+ commands.push(self.update(Message::OpenSaveCurrentColorScheme))
}
pages::color_schemes::Message::OpenAvailableThemes => commands
.push(self.update(Message::ToggleContextPage(ContextPage::AvailableThemes))),
@@ -389,8 +423,17 @@ impl Application for TweakTool {
pages::color_schemes::Message::SaveCurrentColorScheme(Some(name)),
))))
}
- Message::OpenSaveDialog => {
- self.dialog_pages.push_back(DialogPage::New(String::new()));
+ Message::SaveNewLayout(name) => commands.push(self.update(Message::Layouts(
+ pages::layouts::Message::SaveCurrentLayout(name),
+ ))),
+ Message::OpenSaveCurrentColorScheme => {
+ self.dialog_pages
+ .push_back(DialogPage::SaveCurrentColorScheme(String::new()));
+ return widget::text_input::focus(self.dialog_text_input.clone());
+ }
+ Message::OpenSaveCurrentLayout => {
+ self.dialog_pages
+ .push_back(DialogPage::SaveCurrentLayout(String::new()));
return widget::text_input::focus(self.dialog_text_input.clone());
}
Message::DialogUpdate(dialog_page) => {
@@ -399,18 +442,83 @@ impl Application for TweakTool {
Message::DialogComplete => {
if let Some(dialog_page) = self.dialog_pages.pop_front() {
match dialog_page {
- DialogPage::New(name) => {
+ DialogPage::SaveCurrentColorScheme(name) => {
commands.push(self.update(Message::SaveNewColorScheme(name)))
}
+ DialogPage::SaveCurrentLayout(name) => {
+ commands.push(self.update(Message::SaveNewLayout(name)))
+ }
}
}
}
Message::DialogCancel => {
self.dialog_pages.pop_front();
}
+ Message::Key(modifiers, key) => {
+ for (key_bind, action) in &self.key_binds {
+ if key_bind.matches(modifiers, &key) {
+ return self.update(action.message());
+ }
+ }
+ }
+ Message::Modifiers(modifiers) => {
+ self.modifiers = modifiers;
+ }
+ Message::SystemThemeModeChange => {
+ commands.push(self.update_config());
+ }
}
Task::batch(commands)
}
+
+ fn subscription(&self) -> cosmic::iced::Subscription {
+ struct ConfigSubscription;
+ struct ThemeSubscription;
+
+ let subscriptions = vec![
+ event::listen_with(|event, _status, _window_id| match event {
+ Event::Keyboard(KeyEvent::KeyPressed { key, modifiers, .. }) => {
+ Some(Message::Key(modifiers, key))
+ }
+ Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => {
+ Some(Message::Modifiers(modifiers))
+ }
+ _ => None,
+ }),
+ cosmic_config::config_subscription(
+ TypeId::of::(),
+ Self::APP_ID.into(),
+ CONFIG_VERSION,
+ )
+ .map(|update: Update| {
+ if !update.errors.is_empty() {
+ log::info!(
+ "errors loading config {:?}: {:?}",
+ update.keys,
+ update.errors
+ );
+ }
+ Message::SystemThemeModeChange
+ }),
+ cosmic_config::config_subscription::<_, cosmic_theme::ThemeMode>(
+ TypeId::of::(),
+ cosmic_theme::THEME_MODE_ID.into(),
+ cosmic_theme::ThemeMode::version(),
+ )
+ .map(|update: Update| {
+ if !update.errors.is_empty() {
+ log::info!(
+ "errors loading theme mode {:?}: {:?}",
+ update.keys,
+ update.errors
+ );
+ }
+ Message::SystemThemeModeChange
+ }),
+ ];
+
+ Subscription::batch(subscriptions)
+ }
}
impl TweakTool {
@@ -517,8 +625,8 @@ impl TweakTool {
widget::settings::view_column(
loading
.into_iter()
- .chain(available.into_iter())
- .chain(show_more_button.into_iter())
+ .chain(available)
+ .chain(show_more_button)
.collect(),
)
.into()
diff --git a/src/app/key_bind.rs b/src/app/key_bind.rs
index 5ca76d5..b4a5574 100644
--- a/src/app/key_bind.rs
+++ b/src/app/key_bind.rs
@@ -4,9 +4,9 @@ use cosmic::iced::keyboard::Key;
use cosmic::widget::menu::key_bind::KeyBind;
use cosmic::widget::menu::key_bind::Modifier;
-use crate::app::Action;
+use crate::app::TweaksAction;
-pub fn key_binds() -> HashMap {
+pub fn key_binds() -> HashMap {
let mut key_binds = HashMap::new();
macro_rules! bind {
@@ -16,7 +16,7 @@ pub fn key_binds() -> HashMap {
modifiers: vec![$(Modifier::$modifier),*],
key: $key,
},
- Action::$action,
+ TweaksAction::$action,
);
}};
}
diff --git a/src/app/style.rs b/src/app/style.rs
new file mode 100644
index 0000000..f6a4b04
--- /dev/null
+++ b/src/app/style.rs
@@ -0,0 +1,90 @@
+use cosmic::{
+ cosmic_theme::Theme,
+ iced::{Background, Border, Color},
+ iced_core::Shadow,
+ widget::{self, button, container},
+};
+
+pub fn background<'a>(theme: Theme) -> cosmic::theme::Container<'a> {
+ let corner_radii = cosmic::theme::active().cosmic().corner_radii;
+ cosmic::theme::Container::custom(move |_| container::Style {
+ icon_color: Some(Color::from(theme.background.on)),
+ text_color: Some(Color::from(theme.background.on)),
+ background: Some(cosmic::iced::Background::Color(
+ theme.background.base.into(),
+ )),
+ border: Border {
+ radius: corner_radii.radius_xs.into(),
+ ..Default::default()
+ },
+ shadow: Shadow::default(),
+ })
+}
+
+pub fn card<'a>(theme: Theme) -> cosmic::theme::Container<'a> {
+ let theme = theme.clone();
+ let corner_radii = cosmic::theme::active().cosmic().corner_radii;
+
+ cosmic::theme::Container::custom(move |_| container::Style {
+ icon_color: Some(Color::from(theme.primary.component.on)),
+ text_color: Some(Color::from(theme.primary.component.on)),
+ background: Some(cosmic::iced::Background::Color(
+ theme.primary.component.base.into(),
+ )),
+ border: Border {
+ radius: corner_radii.radius_s.into(),
+ ..Default::default()
+ },
+ shadow: Shadow::default(),
+ })
+}
+
+pub fn panel_style(theme: &cosmic::Theme) -> widget::container::Style {
+ let theme = theme.cosmic();
+ cosmic::widget::container::Style {
+ icon_color: Some(Color::from(theme.background.on)),
+ text_color: Some(Color::from(theme.background.on)),
+ background: Some(Background::Color(theme.background.base.into())),
+ border: Border {
+ radius: theme.corner_radii.radius_0.into(),
+ ..Default::default()
+ },
+ shadow: Shadow::default(),
+ }
+}
+
+#[allow(dead_code)]
+pub fn standard_button(theme: Theme) -> cosmic::theme::Button {
+ let active_theme = theme.clone();
+ let disabled_theme = theme.clone();
+ let hovered_theme = theme.clone();
+ let pressed_theme = theme.clone();
+ let _corner_radii = cosmic::theme::active().cosmic().corner_radii;
+
+ cosmic::theme::Button::Custom {
+ active: Box::new(move |_active, _cosmic| button::Style {
+ background: Some(cosmic::iced_core::Background::Color(
+ active_theme.on_accent_color().into(),
+ )),
+ ..Default::default()
+ }),
+ disabled: Box::new(move |_cosmic| button::Style {
+ background: Some(cosmic::iced_core::Background::Color(
+ disabled_theme.on_accent_color().into(),
+ )),
+ ..Default::default()
+ }),
+ hovered: Box::new(move |_hovered, _cosmic| button::Style {
+ background: Some(cosmic::iced_core::Background::Color(
+ hovered_theme.on_accent_color().into(),
+ )),
+ ..Default::default()
+ }),
+ pressed: Box::new(move |_pressed, _cosmic| button::Style {
+ background: Some(cosmic::iced_core::Background::Color(
+ pressed_theme.on_accent_color().into(),
+ )),
+ ..Default::default()
+ }),
+ }
+}
diff --git a/src/core/icons.rs b/src/core/icons.rs
index dff8946..015fea1 100644
--- a/src/core/icons.rs
+++ b/src/core/icons.rs
@@ -39,6 +39,7 @@ impl IconCache {
bundle!("dock-top-symbolic", 18);
bundle!("dark-mode-symbolic", 18);
bundle!("resize-mode-symbolic", 18);
+ bundle!("view-coverflow-symbolic", 18);
bundle!("arrow-into-box-symbolic", 16);
bundle!("document-save-symbolic", 16);
bundle!("search-global-symbolic", 16);
diff --git a/src/core/nav.rs b/src/core/nav.rs
index fab530f..be9538c 100644
--- a/src/core/nav.rs
+++ b/src/core/nav.rs
@@ -10,6 +10,7 @@ pub enum NavPage {
ColorSchemes,
Dock,
Panel,
+ Layouts,
}
impl Default for &NavPage {
@@ -24,6 +25,7 @@ impl NavPage {
Self::ColorSchemes => fl!("color-schemes"),
Self::Dock => fl!("dock"),
Self::Panel => fl!("panel"),
+ Self::Layouts => fl!("layouts"),
}
}
@@ -32,10 +34,11 @@ impl NavPage {
Self::ColorSchemes => icons::get_icon("dark-mode-symbolic", 18),
Self::Dock => icons::get_icon("dock-bottom-symbolic", 18),
Self::Panel => icons::get_icon("dock-top-symbolic", 18),
+ Self::Layouts => icons::get_icon("view-coverflow-symbolic", 18),
}
}
pub fn all() -> &'static [Self] {
- &[Self::ColorSchemes, Self::Dock, Self::Panel]
+ &[Self::ColorSchemes, Self::Dock, Self::Panel, Self::Layouts]
}
}
diff --git a/src/main.rs b/src/main.rs
index a109283..86aa88f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
mod app;
mod core;
mod pages;
+mod resources;
mod settings;
fn main() -> cosmic::iced::Result {
diff --git a/src/pages/color_schemes/preview.rs b/src/pages/color_schemes/preview.rs
index 195c45b..f8cdd40 100644
--- a/src/pages/color_schemes/preview.rs
+++ b/src/pages/color_schemes/preview.rs
@@ -1,9 +1,7 @@
use crate::fl;
use cosmic::{
- cosmic_theme::Theme,
- iced::{Alignment, Border, Color, Length},
- iced_core::Shadow,
- widget::{self, button, container, tooltip},
+ iced::{Alignment, Length},
+ widget::{self, tooltip},
Apply, Element,
};
@@ -32,7 +30,7 @@ pub fn installed<'a>(
.padding(spacing.space_xxs)
.width(Length::Fixed(100.0))
.height(Length::Fill)
- .class(card(theme.clone()))
+ .class(crate::app::style::card(theme.clone()))
.into(),
widget::horizontal_space().into(),
widget::tooltip::tooltip(
@@ -64,7 +62,7 @@ pub fn installed<'a>(
.width(Length::Fixed(200.0))
.height(Length::Fixed(160.0))
.apply(widget::container)
- .class(background(theme.clone())),
+ .class(crate::app::style::background(theme.clone())),
)
.selected(selected.name == color_scheme.name)
.class(cosmic::style::Button::Image)
@@ -94,7 +92,7 @@ pub fn available<'a>(color_scheme: &ColorScheme) -> Element<'a, crate::app::Mess
.padding(spacing.space_xxs)
.width(Length::Fixed(100.0))
.height(Length::Fill)
- .class(card(theme.clone()))
+ .class(crate::app::style::card(theme.clone()))
.into(),
widget::horizontal_space().into(),
widget::tooltip::tooltip(
@@ -129,7 +127,7 @@ pub fn available<'a>(color_scheme: &ColorScheme) -> Element<'a, crate::app::Mess
])
.height(Length::Fixed(160.0))
.apply(widget::container)
- .class(background(theme.clone())),
+ .class(crate::app::style::background(theme.clone())),
)
.class(cosmic::style::Button::Image)
.on_press(crate::app::Message::ColorSchemes(Box::new(
@@ -137,73 +135,3 @@ pub fn available<'a>(color_scheme: &ColorScheme) -> Element<'a, crate::app::Mess
)))
.into()
}
-
-pub fn background<'a>(theme: Theme) -> cosmic::theme::Container<'a> {
- let corner_radii = cosmic::theme::active().cosmic().corner_radii;
- cosmic::theme::Container::custom(move |_| container::Style {
- icon_color: Some(Color::from(theme.background.on)),
- text_color: Some(Color::from(theme.background.on)),
- background: Some(cosmic::iced::Background::Color(
- theme.background.base.into(),
- )),
- border: Border {
- radius: corner_radii.radius_xs.into(),
- ..Default::default()
- },
- shadow: Shadow::default(),
- })
-}
-
-pub fn card<'a>(theme: Theme) -> cosmic::theme::Container<'a> {
- let theme = theme.clone();
- let corner_radii = cosmic::theme::active().cosmic().corner_radii;
-
- cosmic::theme::Container::custom(move |_| container::Style {
- icon_color: Some(Color::from(theme.primary.component.on)),
- text_color: Some(Color::from(theme.primary.component.on)),
- background: Some(cosmic::iced::Background::Color(
- theme.primary.component.base.into(),
- )),
- border: Border {
- radius: corner_radii.radius_s.into(),
- ..Default::default()
- },
- shadow: Shadow::default(),
- })
-}
-
-#[allow(dead_code)]
-pub fn standard_button(theme: Theme) -> cosmic::theme::Button {
- let active_theme = theme.clone();
- let disabled_theme = theme.clone();
- let hovered_theme = theme.clone();
- let pressed_theme = theme.clone();
- let _corner_radii = cosmic::theme::active().cosmic().corner_radii;
-
- cosmic::theme::Button::Custom {
- active: Box::new(move |_active, _cosmic| button::Style {
- background: Some(cosmic::iced_core::Background::Color(
- active_theme.on_accent_color().into(),
- )),
- ..Default::default()
- }),
- disabled: Box::new(move |_cosmic| button::Style {
- background: Some(cosmic::iced_core::Background::Color(
- disabled_theme.on_accent_color().into(),
- )),
- ..Default::default()
- }),
- hovered: Box::new(move |_hovered, _cosmic| button::Style {
- background: Some(cosmic::iced_core::Background::Color(
- hovered_theme.on_accent_color().into(),
- )),
- ..Default::default()
- }),
- pressed: Box::new(move |_pressed, _cosmic| button::Style {
- background: Some(cosmic::iced_core::Background::Color(
- pressed_theme.on_accent_color().into(),
- )),
- ..Default::default()
- }),
- }
-}
diff --git a/src/pages/layouts.rs b/src/pages/layouts.rs
new file mode 100644
index 0000000..869503d
--- /dev/null
+++ b/src/pages/layouts.rs
@@ -0,0 +1,161 @@
+use config::{CustomLayout, Layout, LayoutsConfig};
+use cosmic::{
+ cosmic_config::Config, iced::alignment::Horizontal, widget, Application, Apply, Element, Task,
+};
+use cosmic_ext_config_templates::{load_template, panel::PanelSchema, Schema};
+use dirs::data_local_dir;
+
+use crate::{app::TweakTool, core::icons, fl};
+
+pub mod config;
+pub mod preview;
+
+#[derive(Debug)]
+pub struct Layouts {
+ pub helper: Option,
+ pub config: LayoutsConfig,
+ selected_layout: Option,
+}
+
+impl Default for Layouts {
+ fn default() -> Self {
+ let (helper, config) = (LayoutsConfig::helper(), LayoutsConfig::config());
+ Self {
+ helper,
+ config,
+ selected_layout: None,
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+pub enum Message {
+ ApplyLayout(Layout),
+ SelectLayout(Layout),
+ DeleteLayout,
+ OpenSaveDialog,
+ SaveCurrentLayout(String),
+}
+
+impl Layouts {
+ pub fn view(&self) -> Element {
+ let spacing = cosmic::theme::active().cosmic().spacing;
+ let layouts = self
+ .config
+ .layouts
+ .iter()
+ .map(|layout| {
+ widget::column()
+ .push(layout.preview())
+ .push(widget::text(layout.name()))
+ .spacing(spacing.space_xs)
+ .align_x(Horizontal::Center)
+ .into()
+ })
+ .collect::>>();
+
+ widget::scrollable(
+ widget::column::with_children(vec![
+ widget::row::with_children(vec![
+ widget::text::title3(fl!("layouts")).into(),
+ widget::horizontal_space().into(),
+ widget::tooltip::tooltip(
+ icons::get_handle("arrow-into-box-symbolic", 16)
+ .apply(widget::button::icon)
+ .padding(spacing.space_xxs)
+ .on_press(Message::OpenSaveDialog)
+ .class(cosmic::style::Button::Standard),
+ widget::text(fl!("save-current-layout")),
+ widget::tooltip::Position::Bottom,
+ )
+ .into(),
+ ])
+ .spacing(spacing.space_xxs)
+ .into(),
+ widget::settings::section()
+ .add(
+ widget::flex_row(layouts)
+ .row_spacing(spacing.space_s)
+ .column_spacing(spacing.space_s)
+ .apply(widget::container)
+ .padding([0, spacing.space_xxs]),
+ )
+ .into(),
+ ])
+ .spacing(spacing.space_s),
+ )
+ .into()
+ }
+
+ pub fn update(&mut self, message: Message) -> Task {
+ let mut commands = vec![];
+ match message {
+ Message::ApplyLayout(layout) => {
+ if let Err(e) = load_template(layout.schema().clone()) {
+ eprintln!("Failed to load template: {}", e);
+ }
+ }
+ Message::SelectLayout(layout) => self.selected_layout = Some(layout),
+ Message::OpenSaveDialog => commands.push(self.update(Message::OpenSaveDialog)),
+ Message::SaveCurrentLayout(name) => {
+ let path = data_local_dir()
+ .unwrap()
+ .join(TweakTool::APP_ID)
+ .join("layouts");
+
+ if !path.exists() {
+ if let Err(e) = std::fs::create_dir_all(&path) {
+ log::error!("{e}");
+ }
+ }
+ let mut path = path.join(&name);
+ path.set_extension("ron");
+ match PanelSchema::generate()
+ .and_then(|panel_schema| Schema::Panel(panel_schema).save(&path))
+ {
+ Ok(_) => {
+ if let Some(helper) = &self.helper {
+ let layout = CustomLayout::new(name, &path);
+ let mut layouts = self.config.layouts.clone();
+ layouts.push(Layout::Custom(layout));
+ match self.config.set_layouts(helper, layouts) {
+ Ok(written) => {
+ if !written {
+ log::error!("Failed to write layouts to config");
+ }
+ }
+ Err(e) => log::error!("Failed to set layouts: {}", e),
+ }
+ }
+ }
+ Err(e) => log::error!("Failed to generate template: {}", e),
+ }
+ }
+ Message::DeleteLayout => {
+ if let Some(layout) = &self.selected_layout {
+ if let Layout::Custom(existing_layout) = &layout {
+ if existing_layout.path().exists() {
+ if let Err(e) = std::fs::remove_file(existing_layout.path()) {
+ log::error!("Failed to delete layout: {}", e);
+ return Task::batch(commands);
+ }
+ }
+ let mut layouts = self.config.layouts.clone();
+ layouts.retain(|l| l != layout);
+ if let Some(helper) = &self.helper {
+ match self.config.set_layouts(helper, layouts) {
+ Ok(written) => {
+ if !written {
+ log::error!("Failed to write layouts to config");
+ }
+ }
+ Err(e) => log::error!("Failed to set layouts: {}", e),
+ }
+ }
+ }
+ }
+ }
+ }
+ Task::batch(commands)
+ }
+}
diff --git a/src/pages/layouts/config.rs b/src/pages/layouts/config.rs
new file mode 100644
index 0000000..dcffe51
--- /dev/null
+++ b/src/pages/layouts/config.rs
@@ -0,0 +1,171 @@
+use std::{
+ collections::HashMap,
+ path::{Path, PathBuf},
+};
+
+use super::{
+ preview::{LayoutPreview, PanelProperties, Position},
+ Message,
+};
+use crate::{app::TweakTool, fl, resources};
+use cosmic::{
+ cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, Config, CosmicConfigEntry},
+ widget::{self, menu::Action},
+ Application, Element,
+};
+use cosmic_ext_config_templates::Schema;
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Serialize, Clone, Deserialize, PartialEq, CosmicConfigEntry)]
+#[version = 1]
+pub struct LayoutsConfig {
+ pub layouts: Vec,
+}
+
+impl Default for LayoutsConfig {
+ fn default() -> Self {
+ Self {
+ layouts: vec![Layout::Cosmic, Layout::Mac, Layout::Windows, Layout::Ubuntu],
+ }
+ }
+}
+
+impl LayoutsConfig {
+ pub fn helper() -> Option {
+ Config::new(TweakTool::APP_ID, Self::VERSION).ok()
+ }
+
+ pub fn config() -> LayoutsConfig {
+ match Self::helper() {
+ Some(config_handler) => {
+ LayoutsConfig::get_entry(&config_handler).unwrap_or_else(|(errs, config)| {
+ log::info!("errors loading config: {:?}", errs);
+ config
+ })
+ }
+ None => LayoutsConfig::default(),
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum LayoutsAction {
+ DeleteLayout,
+}
+
+impl Action for LayoutsAction {
+ type Message = Message;
+ fn message(&self) -> Self::Message {
+ match self {
+ LayoutsAction::DeleteLayout => Message::DeleteLayout,
+ }
+ }
+}
+
+#[derive(Debug, Serialize, Clone, Deserialize, PartialEq)]
+pub enum Layout {
+ Cosmic,
+ Mac,
+ Windows,
+ Ubuntu,
+ Custom(CustomLayout),
+}
+
+impl Layout {
+ pub fn name(&self) -> &str {
+ match self {
+ Layout::Cosmic => "COSMIC",
+ Layout::Mac => "macOS",
+ Layout::Windows => "Windows",
+ Layout::Ubuntu => "Ubuntu",
+ Layout::Custom(custom_layout) => &custom_layout.name,
+ }
+ }
+
+ pub fn preview(&self) -> Element {
+ let layout = match self {
+ Layout::Cosmic => LayoutPreview::new(
+ Some(PanelProperties::new(Position::Top, true, 10.0)),
+ Some(PanelProperties::new(Position::Bottom, true, 20.0)),
+ 6,
+ true,
+ ),
+ Layout::Mac => LayoutPreview::new(
+ Some(PanelProperties::new(Position::Top, true, 10.0)),
+ Some(PanelProperties::new(Position::Bottom, false, 20.0)),
+ 6,
+ true,
+ ),
+ Layout::Windows => LayoutPreview::new(
+ None,
+ Some(PanelProperties::new(Position::Bottom, true, 15.0)),
+ 6,
+ true,
+ ),
+ Layout::Ubuntu => LayoutPreview::new(
+ Some(PanelProperties::new(Position::Top, true, 10.0)),
+ Some(PanelProperties::new(Position::Left, true, 20.0)),
+ 3,
+ true,
+ ),
+ Layout::Custom(_) => LayoutPreview::new(
+ Some(PanelProperties::new(Position::Top, true, 10.0)),
+ None,
+ 0,
+ true,
+ ),
+ };
+
+ widget::mouse_area(widget::context_menu(
+ widget::button::custom(layout.view())
+ .on_press(Message::ApplyLayout(self.clone()))
+ .class(cosmic::style::Button::Image),
+ if self.is_custom() {
+ Some(widget::menu::items(
+ &HashMap::new(),
+ vec![widget::menu::Item::Button(
+ fl!("delete-layout"),
+ LayoutsAction::DeleteLayout,
+ )],
+ ))
+ } else {
+ None
+ },
+ ))
+ .on_right_press(Message::SelectLayout(self.clone()))
+ .into()
+ }
+
+ pub fn schema(&self) -> Schema {
+ match self {
+ Layout::Cosmic => ron::from_str::(resources::COSMIC_LAYOUT).unwrap(),
+ Layout::Mac => ron::from_str::(resources::MAC_LAYOUT).unwrap(),
+ Layout::Windows => ron::from_str::(resources::WINDOWS_LAYOUT).unwrap(),
+ Layout::Ubuntu => ron::from_str::(resources::UBUNTU_LAYOUT).unwrap(),
+ Layout::Custom(custom_layout) => Schema::from_file(&custom_layout.path).unwrap(),
+ }
+ }
+
+ pub fn is_custom(&self) -> bool {
+ matches!(self, Layout::Custom(_))
+ }
+}
+
+#[derive(Debug, Serialize, Clone, Default, Deserialize, PartialEq, CosmicConfigEntry)]
+pub struct CustomLayout {
+ name: String,
+ path: PathBuf,
+}
+
+impl CustomLayout {
+ pub fn new(name: String, path: &Path) -> Self {
+ Self {
+ name,
+ path: path.to_path_buf(),
+ }
+ }
+
+ pub fn path(&self) -> &PathBuf {
+ &self.path
+ }
+}
diff --git a/src/pages/layouts/preview.rs b/src/pages/layouts/preview.rs
new file mode 100644
index 0000000..dc9f1c2
--- /dev/null
+++ b/src/pages/layouts/preview.rs
@@ -0,0 +1,339 @@
+use cosmic::{
+ iced::{
+ alignment::{Horizontal, Vertical},
+ Length,
+ },
+ widget::{self, horizontal_space, vertical_space},
+ Apply, Element,
+};
+
+use super::Message;
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub struct LayoutPreview {
+ panel: Option,
+ dock: Option,
+ dock_icons: u8,
+ show_window: bool,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub struct PanelProperties {
+ pub position: Position,
+ pub extend: bool,
+ pub size: f32,
+}
+
+impl PanelProperties {
+ pub fn new(position: Position, extend: bool, size: f32) -> Self {
+ Self {
+ position,
+ extend,
+ size,
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+#[allow(unused)]
+pub enum Position {
+ Top,
+ Bottom,
+ Left,
+ Right,
+}
+
+impl LayoutPreview {
+ pub fn new(
+ panel: Option,
+ dock: Option,
+ dock_icons: u8,
+ show_window: bool,
+ ) -> Self {
+ Self {
+ panel,
+ dock,
+ dock_icons,
+ show_window,
+ }
+ }
+
+ pub fn view<'a>(&self) -> Element<'a, Message> {
+ let column = widget::column().width(188).height(98);
+ let row = widget::row().width(188).height(98);
+ let spacing = cosmic::theme::active().cosmic().spacing;
+
+ let panel = widget::container(widget::text(""));
+
+ let content: Element<_> = match (self.panel, self.dock) {
+ (None, None) => column.into(),
+ (None, Some(dock_props)) => {
+ let extend_dock = if dock_props.extend {
+ Length::Fill
+ } else {
+ Length::Shrink
+ };
+
+ let icons = (0..self.dock_icons)
+ .map(|_| square(dock_props.size - 5.0))
+ .collect();
+
+ let icons: Element<_> =
+ if matches!(dock_props.position, Position::Top | Position::Bottom) {
+ widget::row::with_children(icons)
+ .spacing(spacing.space_xxs)
+ .align_y(Vertical::Center)
+ .into()
+ } else {
+ widget::column::with_children(icons)
+ .spacing(spacing.space_xxs)
+ .align_x(Horizontal::Center)
+ .into()
+ };
+
+ let dock = widget::container(icons)
+ .align_x(Horizontal::Center)
+ .align_y(Vertical::Center)
+ .padding(5)
+ .class(if dock_props.extend {
+ cosmic::style::Container::custom(crate::app::style::panel_style)
+ } else {
+ cosmic::style::Container::Background
+ });
+
+ match dock_props.position {
+ Position::Top => column
+ .push(dock.width(extend_dock))
+ .align_x(Horizontal::Center)
+ .into(),
+ Position::Bottom => column
+ .push(vertical_space())
+ .push(dock.width(extend_dock))
+ .align_x(Horizontal::Center)
+ .into(),
+ Position::Left => row.push(dock).align_y(Vertical::Center).into(),
+ Position::Right => row
+ .push(horizontal_space())
+ .push(dock)
+ .align_y(Vertical::Center)
+ .into(),
+ }
+ }
+ (Some(panel_props), None) => {
+ let panel = panel.class(if panel_props.extend {
+ cosmic::style::Container::custom(crate::app::style::panel_style)
+ } else {
+ cosmic::style::Container::Background
+ });
+ let extend_panel = if panel_props.extend {
+ Length::Fill
+ } else {
+ Length::Shrink
+ };
+ match panel_props.position {
+ Position::Top => column
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .align_x(Horizontal::Center)
+ .into(),
+ Position::Bottom => column
+ .push(vertical_space())
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .align_x(Horizontal::Center)
+ .into(),
+ Position::Left => row
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .align_y(Vertical::Center)
+ .into(),
+ Position::Right => row
+ .push(horizontal_space())
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .align_y(Vertical::Center)
+ .into(),
+ }
+ }
+ (Some(panel_props), Some(dock_props)) => {
+ let panel = panel.class(if panel_props.extend {
+ cosmic::style::Container::custom(crate::app::style::panel_style)
+ } else {
+ cosmic::style::Container::Background
+ });
+ let extend_panel = if panel_props.extend {
+ Length::Fill
+ } else {
+ Length::Shrink
+ };
+ let extend_dock = if dock_props.extend {
+ Length::Fill
+ } else {
+ Length::Shrink
+ };
+
+ let icons = (0..self.dock_icons)
+ .map(|_| square(dock_props.size - 5.0))
+ .collect();
+
+ let icons: Element<_> =
+ if matches!(dock_props.position, Position::Top | Position::Bottom) {
+ widget::row::with_children(icons)
+ .spacing(spacing.space_xxs)
+ .align_y(Vertical::Center)
+ .into()
+ } else {
+ widget::column::with_children(icons)
+ .spacing(spacing.space_xxs)
+ .align_x(Horizontal::Center)
+ .into()
+ };
+
+ let dock = widget::container(icons)
+ .align_x(Horizontal::Center)
+ .align_y(Vertical::Center)
+ .padding(5)
+ .class(if dock_props.extend {
+ cosmic::style::Container::custom(crate::app::style::panel_style)
+ } else {
+ cosmic::style::Container::Background
+ });
+
+ match (panel_props.position, dock_props.position) {
+ (Position::Top, Position::Top) => column
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .push(dock.width(extend_dock))
+ .align_x(Horizontal::Center)
+ .into(),
+ (Position::Top, Position::Bottom) => column
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .push(vertical_space())
+ .push(dock.width(extend_dock))
+ .align_x(Horizontal::Center)
+ .into(),
+ (Position::Top, Position::Left) => column
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .push(
+ widget::row()
+ .push(dock.height(extend_dock))
+ .width(Length::Fill),
+ )
+ .align_x(Horizontal::Center)
+ .into(),
+ (Position::Top, Position::Right) => column
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .push(
+ widget::row()
+ .push(horizontal_space())
+ .push(dock.height(extend_dock))
+ .width(Length::Fill),
+ )
+ .align_x(Horizontal::Center)
+ .into(),
+ (Position::Bottom, Position::Top) => column
+ .push(dock.width(extend_dock))
+ .push(vertical_space())
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .align_x(Horizontal::Center)
+ .into(),
+ (Position::Bottom, Position::Bottom) => column
+ .push(vertical_space())
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .push(dock.width(extend_dock))
+ .align_x(Horizontal::Center)
+ .into(),
+ (Position::Bottom, Position::Left) => column
+ .push(
+ widget::row()
+ .push(dock.height(extend_dock))
+ .width(Length::Fill),
+ )
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .align_x(Horizontal::Center)
+ .into(),
+ (Position::Bottom, Position::Right) => column
+ .push(
+ widget::row()
+ .push(horizontal_space())
+ .push(dock.height(extend_dock)),
+ )
+ .push(panel.width(extend_panel).height(panel_props.size))
+ .align_x(Horizontal::Center)
+ .into(),
+ (Position::Left, Position::Top) => row
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .push(
+ widget::column()
+ .push(dock.width(extend_dock))
+ .align_x(Horizontal::Center),
+ )
+ .align_y(Vertical::Center)
+ .into(),
+ (Position::Left, Position::Bottom) => row
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .push(
+ widget::column()
+ .push(horizontal_space())
+ .push(dock.width(extend_dock))
+ .align_x(Horizontal::Center),
+ )
+ .align_y(Vertical::Center)
+ .into(),
+ (Position::Left, Position::Left) => row
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .push(dock.height(extend_dock))
+ .align_y(Vertical::Center)
+ .into(),
+ (Position::Left, Position::Right) => row
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .push(horizontal_space())
+ .push(dock.height(extend_dock))
+ .align_y(Vertical::Center)
+ .into(),
+ (Position::Right, Position::Top) => row
+ .push(
+ widget::column()
+ .push(dock.width(extend_dock))
+ .align_x(Horizontal::Center),
+ )
+ .push(horizontal_space())
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .align_y(Vertical::Center)
+ .into(),
+ (Position::Right, Position::Bottom) => row
+ .push(
+ widget::column()
+ .push(vertical_space())
+ .push(dock.width(extend_dock))
+ .align_x(Horizontal::Center),
+ )
+ .push(horizontal_space())
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .align_y(Vertical::Center)
+ .into(),
+ (Position::Right, Position::Left) => row
+ .push(dock.height(extend_dock))
+ .push(horizontal_space())
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .align_y(Vertical::Center)
+ .into(),
+ (Position::Right, Position::Right) => row
+ .push(horizontal_space())
+ .push(dock.height(extend_dock))
+ .push(panel.width(panel_props.size).height(extend_panel))
+ .align_y(Vertical::Center)
+ .into(),
+ }
+ }
+ };
+
+ content
+ .apply(widget::container)
+ .class(cosmic::style::Container::Secondary)
+ .padding(spacing.space_xxxs)
+ .into()
+ }
+}
+
+pub fn square<'a>(size: f32) -> Element<'a, Message> {
+ widget::container(widget::text(""))
+ .width(Length::Fixed(size))
+ .height(Length::Fixed(size))
+ .class(cosmic::style::Container::Secondary)
+ .into()
+}
diff --git a/src/pages/mod.rs b/src/pages/mod.rs
index 873b69b..6b59826 100644
--- a/src/pages/mod.rs
+++ b/src/pages/mod.rs
@@ -1,3 +1,4 @@
pub mod color_schemes;
pub mod dock;
+pub mod layouts;
pub mod panel;
diff --git a/src/resources.rs b/src/resources.rs
new file mode 100644
index 0000000..98cd1df
--- /dev/null
+++ b/src/resources.rs
@@ -0,0 +1,4 @@
+pub const COSMIC_LAYOUT: &str = include_str!("../res/layouts/cosmic.ron");
+pub const MAC_LAYOUT: &str = include_str!("../res/layouts/mac.ron");
+pub const WINDOWS_LAYOUT: &str = include_str!("../res/layouts/windows.ron");
+pub const UBUNTU_LAYOUT: &str = include_str!("../res/layouts/ubuntu.ron");