diff options
| author | Ruben Beltran del Rio <jj@r.bdr.sh> | 2026-03-23 20:52:55 +0100 |
|---|---|---|
| committer | Rubén Beltrán del Río <jj@r.bdr.sh> | 2026-03-26 18:07:20 +0100 |
| commit | 8ce55652306908bf24ee351caad60bd21b0bef72 (patch) | |
| tree | c4710c2be73bcfc5afb172dd76284735ee6924f0 | |
| parent | 34a4ddeb3ad4c2b4e317648f58db5a460f4a14bb (diff) | |
Use breakpoints to disable horizontal layout at smaller sizes
| -rw-r--r-- | Cargo.lock | 330 | ||||
| -rw-r--r-- | Cargo.toml | 12 | ||||
| -rw-r--r-- | src/actions.rs | 4 | ||||
| -rw-r--r-- | src/dialogs.rs | 12 | ||||
| -rw-r--r-- | src/file_registry.rs | 8 | ||||
| -rw-r--r-- | src/main.rs | 246 | ||||
| -rw-r--r-- | src/preferences/pages/general.rs | 6 | ||||
| -rw-r--r-- | src/preferences/window.rs | 6 |
8 files changed, 377 insertions, 247 deletions
@@ -24,6 +24,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] name = "approx" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -147,23 +153,23 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -201,7 +207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -209,6 +215,9 @@ name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +dependencies = [ + "getrandom 0.2.16", +] [[package]] name = "field-offset" @@ -244,13 +253,13 @@ checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" [[package]] name = "flume" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" dependencies = [ + "fastrand", "futures-core", "futures-sink", - "nanorand", "spin", ] @@ -475,8 +484,21 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", "wasip2", + "wasip3", ] [[package]] @@ -526,7 +548,7 @@ dependencies = [ "gobject-sys", "libc", "system-deps", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -791,6 +813,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35e6d558e6d4c7b82bc51d9c771e7a927862a161a7d87bf2b0541450e0e20915" [[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] name = "indexmap" version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -798,6 +826,8 @@ checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] @@ -832,6 +862,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] name = "libadwaita" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -929,7 +965,7 @@ dependencies = [ [[package]] name = "map" -version = "1.0.1" +version = "1.0.2" dependencies = [ "cairo-rs", "dirs", @@ -949,9 +985,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memoffset" @@ -973,15 +1009,6 @@ dependencies = [ ] [[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom 0.2.16", -] - -[[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1084,6 +1111,16 @@ dependencies = [ ] [[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] name = "proc-macro-crate" version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1127,6 +1164,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1178,13 +1221,13 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -1218,9 +1261,9 @@ checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "relm4" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bae902de22fd92e62641f047975abf228573425b9b8de175e8ab5b6cda10379" +checksum = "1701679d08c984064e3e920f52ae10c8a0b522eeee223625622b23c27008a472" dependencies = [ "flume", "fragile", @@ -1236,9 +1279,9 @@ dependencies = [ [[package]] name = "relm4-components" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3155d84425d33cdc62929ed2c79bfcfdcb2fff6340c5f7041ed24b56577c9d57" +checksum = "7051ebd4c79fd7cb37dadcb4b54573a327c6cfed0da9d326e84fb68da95a5564" dependencies = [ "once_cell", "relm4", @@ -1253,9 +1296,9 @@ checksum = "37dbe7a114855a22618f0e13595ce6b3f165478c13c2dfc4f4f99614da105797" [[package]] name = "relm4-icons" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28869f8322ed72bed568cbb704403037ff62a66c966ded7a862ad5732f108530" +checksum = "98d855c42d60cec35fbdf0217e2c3606fe3f8ee000fe7371c5c87e05e37e79de" dependencies = [ "gtk4", ] @@ -1274,9 +1317,9 @@ dependencies = [ [[package]] name = "relm4-macros" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175fce497fc6f11dde7ea56daa30ff7ad29a534bbc209d59d766659c880ba5f1" +checksum = "25edbb5b2e8126975f1dd8e85c48cd310afc150beed0dc97df22247b3243971e" dependencies = [ "proc-macro2", "quote", @@ -1325,7 +1368,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1501,9 +1544,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "syn" -version = "2.0.111" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -1545,16 +1588,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", + "windows-sys", ] [[package]] @@ -1563,18 +1597,7 @@ version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.17", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] @@ -1706,12 +1729,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] name = "uuid" -version = "1.19.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.2", "js-sys", "serde_core", "wasm-bindgen", @@ -1745,7 +1774,16 @@ version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.46.0", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", ] [[package]] @@ -1794,6 +1832,40 @@ dependencies = [ ] [[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1815,7 +1887,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1832,15 +1904,6 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" @@ -1849,76 +1912,107 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.48.5" +name = "winnow" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "memchr", ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] [[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +name = "wit-bindgen-core" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +name = "wit-bindgen-rust" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "wit-bindgen-rust-macro" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] [[package]] -name = "winnow" -version = "0.7.14" +name = "wit-component" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ - "memchr", + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", ] [[package]] -name = "wit-bindgen" -version = "0.46.0" +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "wmap-parser" @@ -1937,7 +2031,7 @@ dependencies = [ "once_cell", "rustc-hash", "tempfile", - "thiserror 2.0.17", + "thiserror", "wmap-parser", ] @@ -9,16 +9,16 @@ authors = ["Rubén Beltrán del Río <wmap@r.bdr.sh>"] [dependencies] cairo-rs = "0.21.5" -dirs = "5.0" +dirs = "6.0" gettext-rs = { version = "0.7", features = ["gettext-system"] } -relm4 = { version = "0.10.0", features = ["gnome_48", "libadwaita"] } -relm4-components = "0.10.0" -relm4-icons = "0.10.0" -relm4-macros = "0.10.0" +relm4 = { version = "0.10.1", features = ["gnome_48", "libadwaita"] } +relm4-components = "0.10.1" +relm4-icons = "0.10.1" +relm4-macros = "0.10.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" sourceview5 = "0.10.0" -uuid = { version = "1.0", features = ["v4", "serde"] } +uuid = { version = "1.22", features = ["v4", "serde"] } wmap-parser = "1.0.0" wmap-renderer = "1.1.0" diff --git a/src/actions.rs b/src/actions.rs index fdea125..1d60820 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -60,6 +60,10 @@ pub enum Action { MarkInitialized, CloseWindow, + // Layout Transition + DisableHorizontalLayout, + EnableHorizontalLayout, + // Preferences ShowPreferences, PreferencesChanged(UserPreferences), diff --git a/src/dialogs.rs b/src/dialogs.rs index 242f3d6..22b12df 100644 --- a/src/dialogs.rs +++ b/src/dialogs.rs @@ -20,7 +20,7 @@ use std::path::PathBuf; use gtk::prelude::*; use relm4::gtk::gio; -use relm4::{ComponentSender, gtk}; +use relm4::{ComponentSender, adw, gtk}; use crate::AppModel; use crate::actions::{Action, ImageFormat}; @@ -38,7 +38,7 @@ pub fn create_file_filter() -> gtk::FileFilter { } /// Shows an error dialog with the given title and message. -pub fn show_error(window: >k::Window, title: &str, message: &str) { +pub fn show_error(window: &adw::Window, title: &str, message: &str) { let dialog = gtk::AlertDialog::builder() .modal(true) .buttons([&tr!("dialog.action.cancel"), "Ok"]) @@ -50,7 +50,7 @@ pub fn show_error(window: >k::Window, title: &str, message: &str) { /// Shows a file open dialog and handles the response. pub fn show_open_dialog( - window: >k::Window, + window: &adw::Window, is_empty_document: bool, sender: ComponentSender<AppModel>, ) { @@ -86,7 +86,7 @@ pub fn show_open_dialog( /// Shows a file save dialog and handles the response. pub fn show_save_dialog( - window: >k::Window, + window: &adw::Window, current_file: Option<&PathBuf>, close_after: bool, sender: ComponentSender<AppModel>, @@ -127,7 +127,7 @@ pub fn show_save_dialog( /// Shows a dialog asking whether to save unsaved changes before closing. pub fn show_unsaved_changes_dialog( - window: >k::Window, + window: &adw::Window, current_file: Option<PathBuf>, sender: ComponentSender<AppModel>, ) { @@ -184,7 +184,7 @@ fn create_image_filter(format: ImageFormat) -> gtk::FileFilter { /// Shows an export image dialog and handles the response. pub fn show_export_dialog( - window: >k::Window, + window: &adw::Window, current_file: Option<&PathBuf>, sender: ComponentSender<AppModel>, ) { diff --git a/src/file_registry.rs b/src/file_registry.rs index 749697d..188e1fe 100644 --- a/src/file_registry.rs +++ b/src/file_registry.rs @@ -21,7 +21,7 @@ use std::cell::RefCell; use std::path::PathBuf; use relm4::component::Controller; -use relm4::gtk; +use relm4::{adw}; use crate::AppModel; use crate::actions::Action; @@ -31,7 +31,7 @@ thread_local! { static WINDOW_CONTROLLERS: RefCell<Vec<Controller<AppModel>>> = const { RefCell::new(Vec::new()) }; /// Tracks which files are currently open to prevent duplicate windows. - static OPEN_FILES: RefCell<Vec<(PathBuf, gtk::Window)>> = const { RefCell::new(Vec::new()) }; + static OPEN_FILES: RefCell<Vec<(PathBuf, adw::Window)>> = const { RefCell::new(Vec::new()) }; /// Stores senders for all windows (including main window) to enable broadcasting. static WINDOW_SENDERS: RefCell<Vec<relm4::Sender<Action>>> = const { RefCell::new(Vec::new()) }; @@ -45,7 +45,7 @@ pub fn store_controller(controller: Controller<AppModel>) { } /// Returns the window that has the given file open, if any. -pub fn find_window_for_file(path: &PathBuf) -> Option<gtk::Window> { +pub fn find_window_for_file(path: &PathBuf) -> Option<adw::Window> { OPEN_FILES.with_borrow(|files| { files .iter() @@ -55,7 +55,7 @@ pub fn find_window_for_file(path: &PathBuf) -> Option<gtk::Window> { } /// Registers a file as being open in the given window. -pub fn register_file(path: &PathBuf, window: >k::Window) { +pub fn register_file(path: &PathBuf, window: &adw::Window) { OPEN_FILES.with_borrow_mut(|files| { if !files.iter().any(|(file_path, _)| file_path == path) { files.push((path.clone(), window.clone())); diff --git a/src/main.rs b/src/main.rs index 41d3f68..e1d3bc9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,8 +47,9 @@ use relm4::{ Component, ComponentController, ComponentParts, ComponentSender, RelmApp, RelmWidgetExt, SimpleComponent, actions::{AccelsPlus, ActionablePlus, RelmAction, RelmActionGroup}, - gtk, + gtk, adw }; +use adw::prelude::*; use sourceview5::LanguageManager; use sourceview5::prelude::*; use stages::{ALL_STAGE_TYPES, LocalizedStageType}; @@ -88,105 +89,12 @@ macro_rules! register_action { let action: RelmAction<$action_type> = RelmAction::new_stateless(move |_| { sender.input($message); }); - $group.add_action(action); + $group.add_action(action.clone()); $app.set_accelerators_for_action::<$action_type>($accelerators); + action }}; } -fn setup_actions(window: >k::Window, sender: &ComponentSender<AppModel>) { - let application = relm4::main_application(); - let mut action_group = RelmActionGroup::<WindowActionGroup>::new(); - - register_action!( - action_group, - application, - sender, - ZoomInAction, - Action::ZoomIn, - &["<Primary>equal", "<Primary>plus"] - ); - register_action!( - action_group, - application, - sender, - ZoomOutAction, - Action::ZoomOut, - &["<Primary>minus"] - ); - register_action!( - action_group, - application, - sender, - ChangeOrientationAction, - Action::ChangeOrientation, - &["<Primary>l"] - ); - register_action!( - action_group, - application, - sender, - ExportImageAction, - Action::ExportImage, - &["<Primary>e"] - ); - register_action!( - action_group, - application, - sender, - NewAction, - Action::New, - &["<Primary>n"] - ); - register_action!( - action_group, - application, - sender, - SaveAction, - Action::Save { close_after: false }, - &["<Primary>s"] - ); - register_action!( - action_group, - application, - sender, - SaveAsAction, - Action::SaveAs { close_after: false }, - &["<Primary><Shift>s"] - ); - register_action!( - action_group, - application, - sender, - OpenAction, - Action::Open, - &["<Primary>o"] - ); - register_action!( - action_group, - application, - sender, - CloseAction, - Action::CloseWindow, - &["<Primary>w"] - ); - register_action!( - action_group, - application, - sender, - PreferencesAction, - Action::ShowPreferences, - &["<Primary>comma"] - ); - - let sender = sender.clone(); - let action: RelmAction<NewFromTemplateAction> = - RelmAction::new_with_target_value(move |_, template_id| { - sender.input(Action::NewFromTemplateById(template_id)); - }); - action_group.add_action(action); - action_group.register_for_widget(window); -} - struct AppInit { zoom: f64, file_path: Option<PathBuf>, @@ -211,12 +119,14 @@ struct AppModel { modified: bool, pending_load_events: RefCell<u32>, initialized: bool, - window: gtk::Window, + window: adw::Window, preferences: preferences::UserPreferences, preferences_window: Option<relm4::Controller<preferences::PreferencesWindow>>, editor_css_provider: gtk::CssProvider, templates_menu: gio::Menu, main_menu: gio::Menu, + horizontal_layout_enabled: bool, + layout_action: RelmAction<ChangeOrientationAction> } impl AppModel { @@ -487,7 +397,7 @@ impl SimpleComponent for AppModel { view! { #[root] - gtk::Window { + adw::Window { #[watch] set_title: Some(&model.window_title()), set_default_width: constants::DEFAULT_WINDOW_WIDTH, @@ -497,10 +407,8 @@ impl SimpleComponent for AppModel { set_orientation: gtk::Orientation::Vertical, set_spacing: 0, - gtk::HeaderBar { - pack_start = >k::Box { - set_orientation: gtk::Orientation::Horizontal, - + adw::HeaderBar { + pack_start = &adw::ToolbarView { gtk::Button::with_label(&match model.orientation { gtk::Orientation::Horizontal => tr!("command.view.use_vertical_layout"), _ => tr!("command.view.use_horizontal_layout") @@ -510,11 +418,12 @@ impl SimpleComponent for AppModel { gtk::Orientation::Horizontal => SPLIT_VERTICAL_REGULAR, _ => SPLIT_HORIZONTAL_REGULAR }, + #[watch] + set_visible: model.horizontal_layout_enabled, ActionablePlus::set_stateless_action::<ChangeOrientationAction>: &(), } }, - pack_end = >k::Box { - set_orientation: gtk::Orientation::Horizontal, + pack_end = &adw::ToolbarView { gtk::Button::with_label(&tr!("command.file.export")) { set_icon_name: IMAGE_REGULAR, @@ -540,7 +449,7 @@ impl SimpleComponent for AppModel { gtk::Paned { #[watch] - set_orientation: model.orientation, + set_orientation: if model.horizontal_layout_enabled { model.orientation } else { gtk::Orientation::Vertical }, set_expand: true, #[wrap(Some)] @@ -623,8 +532,6 @@ impl SimpleComponent for AppModel { let (source, initial_content, current_file) = Self::init_source_buffer(&init, &sender); - setup_actions(&root, &sender); - let source_view = sourceview5::View::with_buffer(&source); source_view.set_monospace(true); @@ -648,6 +555,100 @@ impl SimpleComponent for AppModel { let prefs = preferences::storage::load(); let (templates_menu, main_menu) = Self::init_main_menu(&prefs); + // Actions + + let application = relm4::main_application(); + let mut action_group = RelmActionGroup::<WindowActionGroup>::new(); + + register_action!( + action_group, + application, + sender, + ZoomInAction, + Action::ZoomIn, + &["<Primary>equal", "<Primary>plus"] + ); + register_action!( + action_group, + application, + sender, + ZoomOutAction, + Action::ZoomOut, + &["<Primary>minus"] + ); + let layout_action = register_action!( + action_group, + application, + sender, + ChangeOrientationAction, + Action::ChangeOrientation, + &["<Primary>l"] + ); + register_action!( + action_group, + application, + sender, + ExportImageAction, + Action::ExportImage, + &["<Primary>e"] + ); + register_action!( + action_group, + application, + sender, + NewAction, + Action::New, + &["<Primary>n"] + ); + register_action!( + action_group, + application, + sender, + SaveAction, + Action::Save { close_after: false }, + &["<Primary>s"] + ); + register_action!( + action_group, + application, + sender, + SaveAsAction, + Action::SaveAs { close_after: false }, + &["<Primary><Shift>s"] + ); + register_action!( + action_group, + application, + sender, + OpenAction, + Action::Open, + &["<Primary>o"] + ); + register_action!( + action_group, + application, + sender, + CloseAction, + Action::CloseWindow, + &["<Primary>w"] + ); + register_action!( + action_group, + application, + sender, + PreferencesAction, + Action::ShowPreferences, + &["<Primary>comma"] + ); + + let sender_clone = sender.clone(); + let action: RelmAction<NewFromTemplateAction> = + RelmAction::new_with_target_value(move |_, template_id| { + sender_clone.input(Action::NewFromTemplateById(template_id)); + }); + action_group.add_action(action); + action_group.register_for_widget(&root); + let mut model = AppModel { orientation: gtk::Orientation::Horizontal, stage_type_list, @@ -672,6 +673,8 @@ impl SimpleComponent for AppModel { editor_css_provider, templates_menu, main_menu, + horizontal_layout_enabled: true, + layout_action }; model.apply_preferences(); @@ -697,6 +700,23 @@ impl SimpleComponent for AppModel { let widgets = view_output!(); + // Breakpoints for Smaller Layouts + let breakpoint = adw::Breakpoint::new( + adw::BreakpointCondition::new_length( + adw::BreakpointConditionLengthType::MinWidth, + 440.0, + adw::LengthUnit::Sp + ) + ); + let sender_clone = sender.clone(); + breakpoint.connect_apply(move |_| { + sender_clone.input(Action::EnableHorizontalLayout); + }); + let sender_clone = sender.clone(); + breakpoint.connect_unapply(move |_| { + sender_clone.input(Action::DisableHorizontalLayout); + }); + root.add_breakpoint(breakpoint); ComponentParts { model, widgets } } @@ -764,6 +784,18 @@ impl SimpleComponent for AppModel { Action::MarkInitialized => self.initialized = true, + // Layout Transition + Action::DisableHorizontalLayout => { + self.horizontal_layout_enabled = false; + self.layout_action.set_enabled(false); + }, + Action::EnableHorizontalLayout => { + self.horizontal_layout_enabled = true; + self.layout_action.set_enabled(true); + }, + + // Preferences + Action::ShowPreferences => { if self.preferences_window.is_none() { let controller = preferences::PreferencesWindow::builder() diff --git a/src/preferences/pages/general.rs b/src/preferences/pages/general.rs index d1596c4..e65ede6 100644 --- a/src/preferences/pages/general.rs +++ b/src/preferences/pages/general.rs @@ -17,7 +17,7 @@ use gtk::FileFilter; use gtk::prelude::*; use relm4::Sender; -use relm4::gtk; +use relm4::{adw, gtk}; use crate::tr; @@ -92,7 +92,7 @@ impl GeneralPage { } } -pub fn show_export_dialog(sender: &Sender<PreferencesInput>, window: >k::Window) { +pub fn show_export_dialog(sender: &Sender<PreferencesInput>, window: &adw::Window) { let filter = FileFilter::new(); filter.add_pattern("*.json"); filter.set_name(Some(&tr!("dialog.file_type.json"))); @@ -118,7 +118,7 @@ pub fn show_export_dialog(sender: &Sender<PreferencesInput>, window: >k::Windo }); } -pub fn show_import_dialog(sender: &Sender<PreferencesInput>, window: >k::Window) { +pub fn show_import_dialog(sender: &Sender<PreferencesInput>, window: &adw::Window) { let filter = FileFilter::new(); filter.add_pattern("*.json"); filter.set_name(Some(&tr!("dialog.file_type.json"))); diff --git a/src/preferences/window.rs b/src/preferences/window.rs index 0997716..b7db8c5 100644 --- a/src/preferences/window.rs +++ b/src/preferences/window.rs @@ -20,7 +20,7 @@ use std::path::PathBuf; use gtk::prelude::*; -use relm4::{ComponentParts, ComponentSender, SimpleComponent, gtk}; +use relm4::{ComponentParts, ComponentSender, SimpleComponent, adw, gtk}; use crate::tr; @@ -85,7 +85,7 @@ pub enum PreferencesOutput { pub struct PreferencesWindow { preferences: UserPreferences, - window: gtk::Window, + window: adw::Window, // Widget references for pages general_page: general::GeneralPage, editor_page: editor::EditorPage, @@ -101,7 +101,7 @@ impl SimpleComponent for PreferencesWindow { type Output = PreferencesOutput; view! { - gtk::Window { + adw::Window { set_title: Some(&tr!("preferences.title")), set_default_width: 700, set_default_height: 500, |