From 0ddaea62b9a82c81e385d486c5912900bb999726 Mon Sep 17 00:00:00 2001 From: Felix Zwettler Date: Sun, 15 Sep 2024 18:00:22 +0200 Subject: [PATCH 1/3] chore: bump gtk related deps, patch piet for now --- Cargo.lock | 521 ++++++++++++-------------- Cargo.toml | 23 +- crates/rnote-ui/src/appwindow/imp.rs | 16 +- crates/rnote-ui/src/dialogs/export.rs | 6 +- crates/rnote-ui/src/dialogs/import.rs | 4 +- crates/rnote-ui/src/dialogs/mod.rs | 4 +- crates/rnote-ui/src/overlays.rs | 4 +- 7 files changed, 273 insertions(+), 305 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e621c14dda..da0c4c5eff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "approx" @@ -162,14 +162,14 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "arrayref" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", @@ -259,9 +259,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.2.4" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ "async-channel", "async-io", @@ -274,7 +274,6 @@ dependencies = [ "futures-lite", "rustix", "tracing", - "windows-sys 0.59.0", ] [[package]] @@ -344,22 +343,20 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bindgen" -version = "0.69.4" +version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", + "itertools 0.13.0", "proc-macro2", "quote", "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -428,9 +425,9 @@ checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd4c6dcc3b0aea2f5c0b4b82c2b15fe39ddbc76041a310848f4706edf76bb31" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" [[package]] name = "byteorder" @@ -452,26 +449,25 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cairo-rs" -version = "0.19.4" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ac2a4d0e69036cf0062976f6efcba1aaee3e448594e6514bb2ddf87acce562" +checksum = "e8a0ea147c94108c9613235388f540e4d14c327f7081c9e471fc8ee8a2533e69" dependencies = [ "bitflags 2.6.0", "cairo-sys-rs", "glib", "libc", - "thiserror", ] [[package]] name = "cairo-sys-rs" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3bb3119664efbd78b5e6c93957447944f16bdbced84c17a9f41c7829b81e64" +checksum = "428290f914b9b86089f60f5d8a9f6e440508e1bcff23b25afd51502b0a2da88f" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 7.0.2", ] [[package]] @@ -482,9 +478,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.14" +version = "1.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" dependencies = [ "jobserver", "libc", @@ -516,6 +512,16 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cfg-expr" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345c78335be0624ed29012dc10c49102196c6882c12dde65d9f35b02da2aada8" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -549,9 +555,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -559,9 +565,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -578,7 +584,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -659,9 +665,9 @@ dependencies = [ [[package]] name = "coreaudio-sys" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f01585027057ff5f0a5bf276174ae4c1594a2c5bde93d5f46a016d76270f5a9" +checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" dependencies = [ "bindgen", ] @@ -758,7 +764,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -820,18 +826,18 @@ checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" [[package]] name = "derive_builder" -version = "0.11.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.11.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ "darling", "proc-macro2", @@ -841,9 +847,9 @@ dependencies = [ [[package]] name = "derive_builder_macro" -version = "0.11.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" dependencies = [ "derive_builder_core", "syn 1.0.109", @@ -857,7 +863,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -943,9 +949,9 @@ dependencies = [ [[package]] name = "euclid" -version = "0.22.10" +version = "0.22.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f0eb73b934648cd7a4a61f1b15391cd95dab0b4da6e2e66c2a072c144b4a20" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" dependencies = [ "num-traits", ] @@ -1001,9 +1007,9 @@ checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fdeflate" @@ -1035,9 +1041,9 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", @@ -1047,9 +1053,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1211,7 +1217,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1255,9 +1261,9 @@ dependencies = [ [[package]] name = "gdk-pixbuf" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624eaba126021103c7339b2e179ae4ee8cdab842daab419040710f38ed9f8699" +checksum = "8730751991b97419fc3f0c2dca2c9e45b48edf46e48e0f965964ecf33889812f" dependencies = [ "gdk-pixbuf-sys", "gio", @@ -1267,22 +1273,22 @@ dependencies = [ [[package]] name = "gdk-pixbuf-sys" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4efa05a4f83c8cc50eb4d883787b919b85e5f1d8dd10b5a1df53bf5689782379" +checksum = "1ffbf649fd5b1c8c0f0feeb015b7533c3ef92da2887fb95ddd338bc2b1644a7c" dependencies = [ "gio-sys", "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.2", ] [[package]] name = "gdk4" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db265c9dd42d6a371e09e52deab3a84808427198b86ac792d75fd35c07990a07" +checksum = "4b7d7237c1487ed4b300aac7744efcbf1319e12d60d7afcd6f505414bd5b5dea" dependencies = [ "cairo-rs", "gdk-pixbuf", @@ -1295,9 +1301,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9418fb4e8a67074919fe7604429c45aa74eb9df82e7ca529767c6d4e9dc66dd" +checksum = "a67576c8ec012156d7f680e201a807b4432a77babb3157e0555e990ab6bcd878" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -1307,7 +1313,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps", + "system-deps 7.0.2", ] [[package]] @@ -1391,9 +1397,9 @@ dependencies = [ [[package]] name = "gio" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c49f117d373ffcc98a35d114db5478bc223341cff53e39a5d6feced9e2ddffe" +checksum = "dcacaa37401cad0a95aadd266bc39c72a131d454fc012f6dfd217f891d76cc52" dependencies = [ "futures-channel", "futures-core", @@ -1404,27 +1410,26 @@ dependencies = [ "libc", "pin-project-lite", "smallvec", - "thiserror", ] [[package]] name = "gio-sys" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd743ba4714d671ad6b6234e8ab2a13b42304d0e13ab7eba1dcdd78a7d6d4ef" +checksum = "5237611e97e9b86ab5768adc3eef853ae713ea797aa3835404acdfacffc9fb38" dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.2", "windows-sys 0.52.0", ] [[package]] name = "glib" -version = "0.19.9" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39650279f135469465018daae0ba53357942a5212137515777d5fdca74984a44" +checksum = "95648aac01b75503000bb3bcaa5ec7a7a2dd61e43636b8b1814854de94dd80e4" dependencies = [ "bitflags 2.6.0", "futures-channel", @@ -1439,39 +1444,38 @@ dependencies = [ "libc", "memchr", "smallvec", - "thiserror", ] [[package]] name = "glib-build-tools" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "108f374fff60efd14b0d70d8916e7213aed18d7dd071ba3e9334ed2dac1dc86a" +checksum = "7029c2651d9b5d5a3eea93ec8a1995665c6d3a69ce9bf6042ad9064d134736d8" dependencies = [ "gio", ] [[package]] name = "glib-macros" -version = "0.19.9" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4429b0277a14ae9751350ad9b658b1be0abb5b54faa5bcdf6e74a3372582fad7" +checksum = "302f1d633c9cdef4350330e7b68fd8016e2834bb106c93fdf9789fcde753c1ab" dependencies = [ "heck", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "glib-sys" -version = "0.19.8" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2dc18d3a82b0006d470b13304fbbb3e0a9bd4884cf985a60a7ed733ac2c4a5" +checksum = "92eee4531c1c9abba945d19378b205031b5890e1f99c319ba0503b6e0c06a163" dependencies = [ "libc", - "system-deps", + "system-deps 7.0.2", ] [[package]] @@ -1482,20 +1486,20 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "gobject-sys" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e697e252d6e0416fd1d9e169bda51c0f1c926026c39ca21fbe8b1bb5c3b8b9e" +checksum = "fa3d1dcd8a1eb2e7c22be3d5e792b14b186f3524f79b25631730f9a8c169d49a" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 7.0.2", ] [[package]] name = "graphene-rs" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb86031d24d9ec0a2a15978fc7a65d545a2549642cf1eb7c3dda358da42bcf" +checksum = "80aac87f74e81c0e13433e892a047237abdc37945c86887f5eed905038356e69" dependencies = [ "glib", "graphene-sys", @@ -1504,21 +1508,21 @@ dependencies = [ [[package]] name = "graphene-sys" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f530e0944bccba4b55065e9c69f4975ad691609191ebac16e13ab8e1f27af05" +checksum = "cc2f91ecd32989efad60326cc20a8fb252bd2852239a08e4e70cde8c100de9ca" dependencies = [ "glib-sys", "libc", "pkg-config", - "system-deps", + "system-deps 7.0.2", ] [[package]] name = "gsk4" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7563884bf6939f4468e5d94654945bdd9afcaf8c3ba4c5dd17b5342b747221be" +checksum = "1f3cf2091e1af185b347b3450817d93dea6fe435df7abd4c2cd7fb5bcb4cfda8" dependencies = [ "cairo-rs", "gdk4", @@ -1531,9 +1535,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23024bf2636c38bbd1f822f58acc9d1c25b28da896ff0f291a1a232d4272b3dc" +checksum = "6aa69614a26d8760c186c3690f1b0fbb917572ca23ef83137445770ceddf8cde" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -1542,14 +1546,14 @@ dependencies = [ "graphene-sys", "libc", "pango-sys", - "system-deps", + "system-deps 7.0.2", ] [[package]] name = "gtk4" -version = "0.8.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b04e11319b08af11358ab543105a9e49b0c491faca35e2b8e7e36bfba8b671ab" +checksum = "f4fe572bf318e5dbc6f5a2f8a25d853f1ae3f42768c0b08af6ca20a18f4057e1" dependencies = [ "cairo-rs", "field-offset", @@ -1568,21 +1572,21 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.8.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec655a7ef88d8ce9592899deb8b2d0fa50bab1e6dd69182deb764e643c522408" +checksum = "e9e7b362c8fccd2712297903717d65d30defdab2b509bc9d209cbe5ffb9fabaf" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "gtk4-sys" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c8aa86b7f85ea71d66ea88c1d4bae1cfacf51ca4856274565133838d77e57b5" +checksum = "1114a207af8ada02cf4658a76692f4190f06f093380d5be07e3ca8b43aa7c666" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -1594,7 +1598,7 @@ dependencies = [ "gsk4-sys", "libc", "pango-sys", - "system-deps", + "system-deps 7.0.2", ] [[package]] @@ -1705,24 +1709,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "image" -version = "0.24.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "exr", - "gif", - "jpeg-decoder", - "num-traits", - "png", - "qoi", - "tiff", -] - [[package]] name = "image" version = "0.25.2" @@ -1770,9 +1756,9 @@ checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" [[package]] name = "indexmap" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -1836,7 +1822,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1933,9 +1919,6 @@ name = "jpeg-decoder" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" -dependencies = [ - "rayon", -] [[package]] name = "js-sys" @@ -1966,6 +1949,15 @@ dependencies = [ "libc", ] +[[package]] +name = "kurbo" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b" +dependencies = [ + "arrayvec", +] + [[package]] name = "kurbo" version = "0.10.4" @@ -1978,9 +1970,9 @@ dependencies = [ [[package]] name = "kurbo" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5aa9f0f96a938266bdb12928a67169e8d22c6a786fda8ed984b85e6ba93c3c" +checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f" dependencies = [ "arrayvec", "smallvec", @@ -1998,12 +1990,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "lebe" version = "0.5.2" @@ -2012,11 +1998,10 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libadwaita" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91b4990248b9e1ec5e72094a2ccaea70ec3809f88f6fd52192f2af306b87c5d9" +checksum = "2ff9c222b5c783729de45185f07b2fec2d43a7f9c63961e777d3667e20443878" dependencies = [ - "gdk-pixbuf", "gdk4", "gio", "glib", @@ -2028,9 +2013,9 @@ dependencies = [ [[package]] name = "libadwaita-sys" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a748e4e92be1265cd9e93d569c0b5dfc7814107985aa6743d670ab281ea1a8" +checksum = "1c44d8bdbad31d6639e1f20cc9c1424f1a8e02d751fc28d44659bf743fb9eca6" dependencies = [ "gdk4-sys", "gio-sys", @@ -2039,7 +2024,7 @@ dependencies = [ "gtk4-sys", "libc", "pango-sys", - "system-deps", + "system-deps 7.0.2", ] [[package]] @@ -2088,9 +2073,9 @@ dependencies = [ [[package]] name = "librsvg" -version = "2.58.3" +version = "2.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff9730931997875af50628b90fc9b2c2e11bf4bd708a53583299b5634bf68c5" +checksum = "db9c28a25579fda28754054028cd8f8eec230178560786d5afaef4d7eacd2703" dependencies = [ "cairo-rs", "cast", @@ -2100,13 +2085,13 @@ dependencies = [ "float-cmp", "gio", "glib", - "image 0.24.9", - "itertools 0.12.1", + "image", + "itertools 0.13.0", "language-tags", "libc", "locale_config", "markup5ever", - "nalgebra 0.32.6", + "nalgebra", "num-traits", "pango", "pangocairo", @@ -2116,7 +2101,7 @@ dependencies = [ "rgb", "selectors", "string_cache", - "system-deps", + "system-deps 7.0.2", "tinyvec", "url", "xml5ever", @@ -2192,13 +2177,13 @@ dependencies = [ [[package]] name = "markup5ever" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" dependencies = [ "log", - "phf 0.10.1", - "phf_codegen", + "phf 0.11.2", + "phf_codegen 0.11.2", "string_cache", "string_cache_codegen", "tendril", @@ -2246,9 +2231,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] @@ -2299,22 +2284,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "nalgebra" -version = "0.32.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" -dependencies = [ - "approx", - "matrixmultiply", - "nalgebra-macros", - "num-complex", - "num-rational", - "num-traits", - "simba 0.8.1", - "typenum", -] - [[package]] name = "nalgebra" version = "0.33.0" @@ -2328,7 +2297,7 @@ dependencies = [ "num-rational", "num-traits", "serde", - "simba 0.9.0", + "simba", "typenum", ] @@ -2340,7 +2309,7 @@ checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -2465,7 +2434,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -2526,7 +2495,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -2595,9 +2564,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" [[package]] name = "open" @@ -2646,14 +2615,14 @@ dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "pango" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0d328648058085cfd6897c9ae4272884098a926f3a833cd50c8c73e6eccecd" +checksum = "5764e5a174a5a0ec054fe5962ce6d4fc7052e2d0dcc23bbc77202b40a4a403d3" dependencies = [ "gio", "glib", @@ -2663,21 +2632,21 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff03da4fa086c0b244d4a4587d3e20622a3ecdb21daea9edf66597224c634ba0" +checksum = "fd317e1de76b14b3d3efe05518c08b360327f1ab7fec150473a89ffcad4b072d" dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.2", ] [[package]] name = "pangocairo" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c8b43c02ec1c4e16daf7fc50fbce6b8ead5705c18ae56274f703233cce1cd9" +checksum = "50e67bf91c19fccbf9394049d98c67cccec183dd73cbe54a0205da983d4174e7" dependencies = [ "cairo-rs", "glib", @@ -2688,22 +2657,22 @@ dependencies = [ [[package]] name = "pangocairo-sys" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "591904498438879785f5b7a2fdf7c38e9ec08c514b93c614b5c3b48cd11dd8d7" +checksum = "025f26935d210969dda291fa21afee60da792c4976269581170ea715e00f09c0" dependencies = [ "cairo-sys-rs", "glib-sys", "libc", "pango-sys", - "system-deps", + "system-deps 7.0.2", ] [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -2730,9 +2699,9 @@ dependencies = [ [[package]] name = "parry2d-f64" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83cb2f7d0e018b2fc6c3cecfc05c82a198b9087534f16d2ea2a5552c2ac0fc2b" +checksum = "b9ef77dcfb95073cf0fb746ae2ba87a747d0bc3eaf3c3fd207a53af5f33fb642" dependencies = [ "approx", "arrayvec", @@ -2740,13 +2709,13 @@ dependencies = [ "downcast-rs", "either", "log", - "nalgebra 0.33.0", + "nalgebra", "num-derive", "num-traits", "ordered-float", "rustc-hash 2.0.0", "serde", - "simba 0.9.0", + "simba", "slab", "smallvec", "spade", @@ -2818,6 +2787,16 @@ dependencies = [ "phf_shared 0.10.0", ] +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + [[package]] name = "phf_generator" version = "0.10.0" @@ -2848,7 +2827,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -2878,7 +2857,7 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "piet" version = "0.6.2" -source = "git+https://github.com/linebender/piet?rev=02eb5f0152e893626c43980bf37eeb0ccb1acb46#02eb5f0152e893626c43980bf37eeb0ccb1acb46" +source = "git+https://github.com/flxzt/piet?rev=a480bc20bd0d235928d46b009dae54e52e32767a#a480bc20bd0d235928d46b009dae54e52e32767a" dependencies = [ "kurbo 0.10.4", "unic-bidi", @@ -2887,7 +2866,7 @@ dependencies = [ [[package]] name = "piet-cairo" version = "0.6.2" -source = "git+https://github.com/linebender/piet?rev=02eb5f0152e893626c43980bf37eeb0ccb1acb46#02eb5f0152e893626c43980bf37eeb0ccb1acb46" +source = "git+https://github.com/flxzt/piet?rev=a480bc20bd0d235928d46b009dae54e52e32767a#a480bc20bd0d235928d46b009dae54e52e32767a" dependencies = [ "cairo-rs", "pango", @@ -2942,8 +2921,7 @@ dependencies = [ [[package]] name = "points_on_curve" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd55aaa619ef3e710ba6515663cb9afdf54ab4b09b2b3d069622f3a71736295" +source = "git+https://github.com/orhanbalci/rough-rs?rev=0701ce0b874061707ef726533b43e1806af8b666#0701ce0b874061707ef726533b43e1806af8b666" dependencies = [ "euclid", "num-traits", @@ -2966,9 +2944,9 @@ dependencies = [ [[package]] name = "poppler-rs" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9421853a6cc8dfaea2e31bd751fb037abdc3a727f04d0eb10fcf7061f6eff562" +checksum = "45b1f21ffe55c78cbe3b301950cf15a143c8ff2a0f05a2b9e8e9c80605347206" dependencies = [ "cairo-rs", "gio", @@ -2979,16 +2957,16 @@ dependencies = [ [[package]] name = "poppler-sys-rs" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f6737da38a7bb0126931c4a7b23b7bea517410bd48676f18af6b38c5f88d51" +checksum = "e970afd57f25a79b8e526c257bf9c8cd5a6a68973331b6da341c422a6db47755" dependencies = [ "cairo-sys-rs", "gio-sys", "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.2", ] [[package]] @@ -3014,11 +2992,11 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit 0.21.1", + "toml_edit 0.22.20", ] [[package]] @@ -3046,7 +3024,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3151,7 +3129,7 @@ dependencies = [ "rand", "rand_chacha", "simd_helpers", - "system-deps", + "system-deps 6.2.2", "thiserror", "v_frame", "wasm-bindgen", @@ -3205,9 +3183,9 @@ checksum = "e03e7866abec1101869ffa8e2c8355c4c2419d0214ece0cc3e428e5b94dea6e9" [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ "bitflags 2.6.0", ] @@ -3258,9 +3236,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rgb" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f86ae463694029097b846d8f99fd5536740602ae00022c0c50c5600720b2f71" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -3280,11 +3258,11 @@ dependencies = [ "glib-build-tools", "gtk4", "ijson", - "image 0.25.2", + "image", "itertools 0.13.0", "kurbo 0.10.4", "libadwaita", - "nalgebra 0.33.0", + "nalgebra", "notify-debouncer-full", "num-derive", "num-traits", @@ -3325,7 +3303,7 @@ dependencies = [ "clap", "dialoguer", "indicatif", - "nalgebra 0.33.0", + "nalgebra", "open", "parry2d-f64", "rnote-compose", @@ -3345,7 +3323,7 @@ dependencies = [ "clap", "ink-stroke-modeler-rs", "kurbo 0.10.4", - "nalgebra 0.33.0", + "nalgebra", "num-derive", "num-traits", "once_cell", @@ -3381,11 +3359,11 @@ dependencies = [ "glib", "gtk4", "ijson", - "image 0.25.2", + "image", "itertools 0.13.0", "kurbo 0.10.4", "librsvg", - "nalgebra 0.33.0", + "nalgebra", "num-derive", "num-traits", "once_cell", @@ -3436,8 +3414,7 @@ dependencies = [ [[package]] name = "rough_piet" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe58846983e22ea4e24f4340733df25c4788f74333d6afb92fa0611b0616557" +source = "git+https://github.com/orhanbalci/rough-rs?rev=0701ce0b874061707ef726533b43e1806af8b666#0701ce0b874061707ef726533b43e1806af8b666" dependencies = [ "euclid", "num-traits", @@ -3449,8 +3426,7 @@ dependencies = [ [[package]] name = "roughr" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d622b5059d31ffa6aae33cd2e58b2e7f4c44c607af50731bb36ff4e39109cac" +source = "git+https://github.com/orhanbalci/rough-rs?rev=0701ce0b874061707ef726533b43e1806af8b666#0701ce0b874061707ef726533b43e1806af8b666" dependencies = [ "derive_builder", "euclid", @@ -3459,7 +3435,7 @@ dependencies = [ "points_on_curve", "rand", "svg_path_ops", - "svgtypes 0.8.2", + "svgtypes 0.11.0", ] [[package]] @@ -3493,18 +3469,18 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -3574,7 +3550,7 @@ dependencies = [ "log", "new_debug_unreachable", "phf 0.10.1", - "phf_codegen", + "phf_codegen 0.10.0", "precomputed-hash", "servo_arc", "smallvec", @@ -3591,29 +3567,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.208" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -3669,19 +3645,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simba" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" -dependencies = [ - "approx", - "num-complex", - "num-traits", - "paste", - "wide", -] - [[package]] name = "simba" version = "0.9.0" @@ -3758,9 +3721,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smol" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aad24f41392790e6ac67f4f4cd871da61f7d758e07b5622431e491e897d9c8a7" +checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" dependencies = [ "async-channel", "async-executor", @@ -3775,9 +3738,9 @@ dependencies = [ [[package]] name = "spade" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd14cf9e23b5241e1b1289ed3b9afc7746c95ead8df52d9254f5ed2d40c561b" +checksum = "93f5ef1f863aca7d1d7dda7ccfc36a0a4279bd6d3c375176e5e0712e25cb4889" dependencies = [ "hashbrown", "num-traits", @@ -3856,18 +3819,18 @@ checksum = "700efb40f3f559c23c18b446e8ed62b08b56b2bb3197b36d57e0470b4102779e" [[package]] name = "svg_path_ops" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9f934257a2a95c29314aceebc68a34b201e9c1fc875fc1c5d63e96895ace8cd" +source = "git+https://github.com/orhanbalci/rough-rs?rev=0701ce0b874061707ef726533b43e1806af8b666#0701ce0b874061707ef726533b43e1806af8b666" dependencies = [ - "svgtypes 0.8.2", + "svgtypes 0.11.0", ] [[package]] name = "svgtypes" -version = "0.8.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22975e8a2bac6a76bb54f898a6b18764633b00e780330f0b689f65afb3975564" +checksum = "ed4b0611e7f3277f68c0fa18e385d9e2d26923691379690039548f867cef02a7" dependencies = [ + "kurbo 0.9.5", "siphasher 0.3.11", ] @@ -3877,7 +3840,7 @@ version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "794de53cc48eaabeed0ab6a3404a65f40b3e38c067e4435883a65d2aa4ca000e" dependencies = [ - "kurbo 0.11.0", + "kurbo 0.11.1", "siphasher 1.0.1", ] @@ -3965,9 +3928,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -3980,7 +3943,20 @@ version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" dependencies = [ - "cfg-expr", + "cfg-expr 0.15.8", + "heck", + "pkg-config", + "toml 0.8.19", + "version-compare", +] + +[[package]] +name = "system-deps" +version = "7.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "070a0a5e7da2d24be457809c4b3baa57a835fd2829ad8b86f9a049052fe71031" +dependencies = [ + "cfg-expr 0.16.0", "heck", "pkg-config", "toml 0.8.19", @@ -4040,7 +4016,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -4136,17 +4112,6 @@ dependencies = [ "winnow 0.5.40", ] -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.20" @@ -4179,7 +4144,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -4307,9 +4272,9 @@ checksum = "260bc6647b3893a9a90668360803a15f96b85a5257b1c3a0c3daf6ae2496de42" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" @@ -4334,9 +4299,9 @@ checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-vo" @@ -4372,7 +4337,7 @@ dependencies = [ "flate2", "fontdb", "imagesize", - "kurbo 0.11.0", + "kurbo 0.11.1", "log", "pico-args", "roxmltree", @@ -4467,7 +4432,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-shared", ] @@ -4501,7 +4466,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4857,9 +4822,9 @@ checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" [[package]] name = "xml5ever" -version = "0.17.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4034e1d05af98b51ad7214527730626f019682d797ba38b51689212118d8e650" +checksum = "9bbb26405d8e919bc1547a5aa9abc95cbfa438f04844f5fdd9dc7596b748bf69" dependencies = [ "log", "mac", @@ -4890,7 +4855,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 8b1b67481b..873b12d679 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,12 +20,12 @@ version = "0.11.0" rnote-compose = { version = "0.11.0", path = "crates/rnote-compose" } rnote-engine = { version = "0.11.0", path = "crates/rnote-engine" } -adw = { version = "0.6.0", package = "libadwaita", features = ["v1_5"] } +adw = { version = "0.7.0", package = "libadwaita", features = ["v1_5"] } anyhow = "1.0" approx = "0.5.1" async-fs = "2.1" base64 = "0.22.1" -cairo-rs = { version = "0.19.4", features = ["v1_18", "png", "svg", "pdf"] } +cairo-rs = { version = "0.20.1", features = ["v1_18", "png", "svg", "pdf"] } chrono = "0.4.38" clap = { version = "4.5", features = ["derive"] } dialoguer = "0.11.0" @@ -34,17 +34,17 @@ fs_extra = "1.3" futures = "0.3.30" geo = "0.28.0" gettext-rs = { version = "0.7.1", features = ["gettext-system"] } -gio = "0.19.5" -glib = "0.19.7" -glib-build-tools = "0.19.0" -gtk4 = { version = "0.8.2", features = ["v4_12"] } +gio = "0.20.1" +glib = "0.20.3" +glib-build-tools = "0.20.0" +gtk4 = { version = "0.9.1", features = ["v4_14"] } ijson = "0.1.3" image = "0.25.2" indicatif = "0.17.8" ink-stroke-modeler-rs = { git = "https://github.com/flxzt/ink-stroke-modeler-rs", rev = "84d311e9b0d034dcd955a1f353d37f54b2bda70f" } itertools = "0.13.0" kurbo = "0.10.4" -librsvg = "2.58.2" +librsvg = "2.59.0" nalgebra = { version = "0.33.0", features = ["serde-serialize"] } notify-debouncer-full = "0.3.1" num-derive = "0.4.2" @@ -84,12 +84,15 @@ usvg = "0.43.0" winresource = "0.1.17" xmlwriter = "0.1.0" # Enabling feature > v20_9 causes linker errors on mingw -poppler-rs = { version = "0.23.0", features = ["v20_9"] } +poppler-rs = { version = "0.24.1", features = ["v20_9"] } [patch.crates-io] # once a new piet (current v0.6.2) is released with updated cairo and kurbo deps, this can be removed. -piet = { git = "https://github.com/linebender/piet", rev = "02eb5f0152e893626c43980bf37eeb0ccb1acb46" } -piet-cairo = { git = "https://github.com/linebender/piet", rev = "02eb5f0152e893626c43980bf37eeb0ccb1acb46" } +piet = { git = "https://github.com/flxzt/piet", rev = "a480bc20bd0d235928d46b009dae54e52e32767a" } +piet-cairo = { git = "https://github.com/flxzt/piet", rev = "a480bc20bd0d235928d46b009dae54e52e32767a" } +# the latest commit in rough depends on nightly-only features +roughr = { git = "https://github.com/orhanbalci/rough-rs", rev = "0701ce0b874061707ef726533b43e1806af8b666" } +rough_piet = { git = "https://github.com/orhanbalci/rough-rs", rev = "0701ce0b874061707ef726533b43e1806af8b666" } [profile.dev] debug = true diff --git a/crates/rnote-ui/src/appwindow/imp.rs b/crates/rnote-ui/src/appwindow/imp.rs index 78ff49b3a3..2ce3676ac4 100644 --- a/crates/rnote-ui/src/appwindow/imp.rs +++ b/crates/rnote-ui/src/appwindow/imp.rs @@ -535,22 +535,22 @@ impl RnAppWindow { obj.sidebar() .workspacebrowser() .files_scroller() - .set_window_placement(CornerType::TopRight); + .set_placement(CornerType::TopRight); obj.sidebar() .workspacebrowser() .workspacesbar() .workspaces_scroller() - .set_window_placement(CornerType::TopRight); + .set_placement(CornerType::TopRight); obj.sidebar() .settings_panel() .settings_scroller() - .set_window_placement(CornerType::TopRight); + .set_placement(CornerType::TopRight); obj.overlays().sidebar_box().set_halign(Align::Start); obj.overlays() .sidebar_scroller() - .set_window_placement(CornerType::TopRight); + .set_placement(CornerType::TopRight); obj.overlays() .penssidebar() .brush_page() @@ -662,22 +662,22 @@ impl RnAppWindow { obj.sidebar() .workspacebrowser() .files_scroller() - .set_window_placement(CornerType::TopLeft); + .set_placement(CornerType::TopLeft); obj.sidebar() .workspacebrowser() .workspacesbar() .workspaces_scroller() - .set_window_placement(CornerType::TopLeft); + .set_placement(CornerType::TopLeft); obj.sidebar() .settings_panel() .settings_scroller() - .set_window_placement(CornerType::TopLeft); + .set_placement(CornerType::TopLeft); obj.overlays().sidebar_box().set_halign(Align::End); obj.overlays() .sidebar_scroller() - .set_window_placement(CornerType::TopLeft); + .set_placement(CornerType::TopLeft); obj.overlays() .penssidebar() .brush_page() diff --git a/crates/rnote-ui/src/dialogs/export.rs b/crates/rnote-ui/src/dialogs/export.rs index f2802312ba..a8aa8fc386 100644 --- a/crates/rnote-ui/src/dialogs/export.rs +++ b/crates/rnote-ui/src/dialogs/export.rs @@ -274,7 +274,7 @@ pub(crate) async fn dialog_export_doc_w_prefs(appwindow: &RnAppWindow, canvas: & } })); - dialog.present(appwindow); + dialog.present(appwindow.root().as_ref()); } fn create_filedialog_export_doc( @@ -604,7 +604,7 @@ pub(crate) async fn dialog_export_doc_pages_w_prefs(appwindow: &RnAppWindow, can } })); - dialog.present(appwindow); + dialog.present(appwindow.root().as_ref()); } fn create_filedialog_export_doc_pages( @@ -896,7 +896,7 @@ pub(crate) async fn dialog_export_selection_w_prefs(appwindow: &RnAppWindow, can })); })); - dialog.present(appwindow); + dialog.present(appwindow.root().as_ref()); } /// Returns (if possible) a "reasonable" folder for export operations diff --git a/crates/rnote-ui/src/dialogs/import.rs b/crates/rnote-ui/src/dialogs/import.rs index 14491c8346..e4fd8be5e5 100644 --- a/crates/rnote-ui/src/dialogs/import.rs +++ b/crates/rnote-ui/src/dialogs/import.rs @@ -344,7 +344,7 @@ pub(crate) async fn dialog_import_pdf_w_prefs( dialog.add_controller(controller); // Present than wait for a response from the dialog - dialog.present(appwindow); + dialog.present(appwindow.root().as_ref()); match rx.next().await { Some(res) => res, @@ -436,7 +436,7 @@ pub(crate) async fn dialog_import_xopp_w_prefs( dialog.add_controller(controller); // Present than wait for a response from the dialog - dialog.present(appwindow); + dialog.present(appwindow.root().as_ref()); match rx.next().await { Some(res) => res, diff --git a/crates/rnote-ui/src/dialogs/mod.rs b/crates/rnote-ui/src/dialogs/mod.rs index 566e3e1431..cf4cdd40af 100644 --- a/crates/rnote-ui/src/dialogs/mod.rs +++ b/crates/rnote-ui/src/dialogs/mod.rs @@ -44,7 +44,7 @@ pub(crate) fn dialog_about(appwindow: &RnAppWindow) { aboutdialog.add_css_class("devel"); } - aboutdialog.present(appwindow); + aboutdialog.present(appwindow.root().as_ref()); } pub(crate) fn dialog_keyboard_shortcuts(appwindow: &RnAppWindow) { @@ -549,7 +549,7 @@ pub(crate) async fn dialog_edit_selected_workspace(appwindow: &RnAppWindow) { }), ); - dialog.present(appwindow); + dialog.present(appwindow.root().as_ref()); } const WORKSPACELISTENTRY_ICONS_LIST: &[&str] = &[ diff --git a/crates/rnote-ui/src/overlays.rs b/crates/rnote-ui/src/overlays.rs index 0a4d7935b0..d5538fa684 100644 --- a/crates/rnote-ui/src/overlays.rs +++ b/crates/rnote-ui/src/overlays.rs @@ -246,7 +246,7 @@ impl RnOverlays { ); imp.tabview.connect_close_page( - clone!(@weak self as overlays, @weak appwindow => @default-return true, move |_, page| { + clone!(@weak self as overlays, @weak appwindow => @default-return glib::Propagation::Proceed, move |_, page| { glib::spawn_future_local(clone!(@weak overlays, @weak appwindow, @weak page => async move { let close_finish_confirm = if page .child() @@ -263,7 +263,7 @@ impl RnOverlays { appwindow.close_tab_finish(&page, close_finish_confirm); })); - true + glib::Propagation::Proceed }), ); From c51929b8129f0dc8dd4d916c34db7cbc7949e95c Mon Sep 17 00:00:00 2001 From: Felix Zwettler Date: Sun, 15 Sep 2024 19:26:55 +0200 Subject: [PATCH 2/3] refactor: replace all uses of old glib macro with new syntax --- crates/rnote-ui/src/app/appactions.rs | 30 +- crates/rnote-ui/src/app/mod.rs | 20 +- crates/rnote-ui/src/appwindow/actions.rs | 1186 +++++++++++------ crates/rnote-ui/src/appwindow/appsettings.rs | 53 +- crates/rnote-ui/src/appwindow/imp.rs | 60 +- crates/rnote-ui/src/canvas/mod.rs | 273 ++-- crates/rnote-ui/src/canvaswrapper.rs | 525 +++++--- crates/rnote-ui/src/colorpicker/mod.rs | 105 +- crates/rnote-ui/src/dialogs/export.rs | 505 ++++--- crates/rnote-ui/src/dialogs/import.rs | 188 ++- crates/rnote-ui/src/dialogs/mod.rs | 120 +- .../rnote-ui/src/groupediconpicker/group.rs | 51 +- crates/rnote-ui/src/groupediconpicker/mod.rs | 29 +- crates/rnote-ui/src/iconpicker.rs | 14 +- crates/rnote-ui/src/overlays.rs | 249 ++-- crates/rnote-ui/src/penpicker.rs | 99 +- crates/rnote-ui/src/penssidebar/brushpage.rs | 235 +++- crates/rnote-ui/src/penssidebar/eraserpage.rs | 62 +- crates/rnote-ui/src/penssidebar/mod.rs | 82 +- .../rnote-ui/src/penssidebar/selectorpage.rs | 98 +- crates/rnote-ui/src/penssidebar/shaperpage.rs | 341 +++-- crates/rnote-ui/src/penssidebar/toolspage.rs | 117 +- .../src/penssidebar/typewriterpage.rs | 232 ++-- crates/rnote-ui/src/settingspanel/mod.rs | 723 +++++++--- .../src/settingspanel/penshortcutrow.rs | 24 +- crates/rnote-ui/src/sidebar.rs | 18 +- crates/rnote-ui/src/strokecontentpaintable.rs | 34 +- crates/rnote-ui/src/strokecontentpreview.rs | 122 +- crates/rnote-ui/src/strokewidthpicker/mod.rs | 40 +- crates/rnote-ui/src/unitentry.rs | 10 +- .../filerow/actions/duplicate.rs | 4 +- .../workspacebrowser/filerow/actions/open.rs | 28 +- .../filerow/actions/open_in_default_app.rs | 22 +- .../filerow/actions/rename.rs | 120 +- .../workspacebrowser/filerow/actions/trash.rs | 37 +- .../src/workspacebrowser/filerow/mod.rs | 37 +- crates/rnote-ui/src/workspacebrowser/mod.rs | 116 +- .../src/workspacebrowser/widgethelper.rs | 10 +- .../workspaceactions/createfolder.rs | 104 +- .../src/workspacebrowser/workspacesbar/mod.rs | 251 +++- .../workspacesbar/workspacerow.rs | 40 +- 41 files changed, 4369 insertions(+), 2045 deletions(-) diff --git a/crates/rnote-ui/src/app/appactions.rs b/crates/rnote-ui/src/app/appactions.rs index 962d5f0000..ab9f78afd0 100644 --- a/crates/rnote-ui/src/app/appactions.rs +++ b/crates/rnote-ui/src/app/appactions.rs @@ -39,20 +39,28 @@ impl RnApp { .build(); // Quit App - action_quit.connect_activate(clone!(@weak self as app => move |_, _| { - // Request closing all windows. They then get the chance to display a save dialog on unsaved changes - for appwindow in app.windows() { - appwindow.close(); - } + action_quit.connect_activate(clone!( + #[weak(rename_to = app)] + self, + move |_, _| { + // Request closing all windows. They then get the chance to display a save dialog on unsaved changes + for appwindow in app.windows() { + appwindow.close(); + } - if app.windows().is_empty() { - app.quit(); + if app.windows().is_empty() { + app.quit(); + } } - })); + )); - action_new_window.connect_activate(clone!(@weak self as app => move |_, _| { - app.new_appwindow_init_show(); - })); + action_new_window.connect_activate(clone!( + #[weak(rename_to = app)] + self, + move |_, _| { + app.new_appwindow_init_show(); + } + )); } // Accelerators / Keyboard Shortcuts diff --git a/crates/rnote-ui/src/app/mod.rs b/crates/rnote-ui/src/app/mod.rs index 1f9dc8fcb2..80a9c0081a 100644 --- a/crates/rnote-ui/src/app/mod.rs +++ b/crates/rnote-ui/src/app/mod.rs @@ -74,9 +74,13 @@ mod imp { .map(|w| w.downcast::().unwrap()) { if let Some(input_file) = input_file { - glib::spawn_future_local(clone!(@weak appwindow => async move { - appwindow.open_file_w_dialogs(input_file, None, true).await; - })); + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + appwindow.open_file_w_dialogs(input_file, None, true).await; + } + )); } } else { self.new_appwindow_init_show(input_file); @@ -133,9 +137,13 @@ mod imp { // Loading in input file in the first tab, if Some if let Some(input_file) = input_file { - glib::spawn_future_local(clone!(@weak appwindow => async move { - appwindow.open_file_w_dialogs(input_file, None, false).await; - })); + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + appwindow.open_file_w_dialogs(input_file, None, false).await; + } + )); } } } diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index 3bfcb036f6..39c322b6e4 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -174,57 +174,86 @@ impl RnAppWindow { self.add_action(&action_drawing_pad_pressed_button_3); // Open settings - action_open_settings.connect_activate(clone!(@weak self as appwindow => move |_, _| { - appwindow.sidebar().sidebar_stack().set_visible_child_name("settings_page"); - appwindow.split_view().set_show_sidebar(true); - })); + action_open_settings.connect_activate(clone!( + #[weak(rename_to = appwindow)] + self, + move |_, _| { + appwindow + .sidebar() + .sidebar_stack() + .set_visible_child_name("settings_page"); + appwindow.split_view().set_show_sidebar(true); + } + )); // About Dialog - action_about.connect_activate(clone!(@weak self as appwindow => move |_, _| { - dialogs::dialog_about(&appwindow); - })); + action_about.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + dialogs::dialog_about(&appwindow); + } + )); // Donate - action_donate.connect_activate(clone!(@weak self as appwindow => move |_, _| { - UriLauncher::new(config::APP_DONATE_URL).launch(None::<&Window>, gio::Cancellable::NONE, |res| { - if let Err(e) = res { - error!("Launching donate URL failed, Err: {e:?}"); - } - }) + action_donate.connect_activate(clone!(move |_, _| { + UriLauncher::new(config::APP_DONATE_URL).launch( + None::<&Window>, + gio::Cancellable::NONE, + |res| { + if let Err(e) = res { + error!("Launching donate URL failed, Err: {e:?}"); + } + }, + ) })); // Keyboard shortcuts - action_keyboard_shortcuts_dialog.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_keyboard_shortcuts_dialog.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { dialogs::dialog_keyboard_shortcuts(&appwindow); - }), - ); + } + )); // Open Canvas Menu - action_open_canvasmenu.connect_activate(clone!(@weak self as appwindow => move |_,_| { - if appwindow.split_view().shows_sidebar() && appwindow.split_view().is_collapsed() { - appwindow.split_view().set_show_sidebar(false); + action_open_canvasmenu.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + if appwindow.split_view().shows_sidebar() && appwindow.split_view().is_collapsed() { + appwindow.split_view().set_show_sidebar(false); + } + appwindow.main_header().canvasmenu().popovermenu().popup(); } - appwindow.main_header().canvasmenu().popovermenu().popup(); - })); + )); // Open App Menu - action_open_appmenu.connect_activate(clone!(@weak self as appwindow => move |_,_| { - if !appwindow.split_view().shows_sidebar() { - appwindow.main_header().appmenu().popovermenu().popup(); - return - } - if appwindow.split_view().is_collapsed() { - appwindow.split_view().set_show_sidebar(false); - appwindow.main_header().appmenu().popovermenu().popup(); - } else { - appwindow.sidebar().appmenu().popovermenu().popup(); + action_open_appmenu.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + if !appwindow.split_view().shows_sidebar() { + appwindow.main_header().appmenu().popovermenu().popup(); + return; + } + if appwindow.split_view().is_collapsed() { + appwindow.split_view().set_show_sidebar(false); + appwindow.main_header().appmenu().popovermenu().popup(); + } else { + appwindow.sidebar().appmenu().popovermenu().popup(); + } } - })); + )); // Developer mode - action_devel_mode.connect_activate( - clone!(@weak self as appwindow, @weak action_devel_menu, @weak action_visual_debug => move |action, _| { + action_devel_mode.connect_activate(clone!( + #[weak] + action_devel_menu, + #[weak] + action_visual_debug, + move |action, _| { let state = action.state().unwrap().get::().unwrap(); // Enable the devel menu action to reveal it in the app menu @@ -236,8 +265,8 @@ impl RnAppWindow { action_visual_debug.change_state(&false.to_variant()); } action.change_state(&(!state).to_variant()); - }), - ); + } + )); // Developer settings // Its enabled state toggles the visibility of the developer settings menu entry. @@ -245,83 +274,128 @@ impl RnAppWindow { action_devel_menu.set_enabled(false); // Visual debugging - action_visual_debug.connect_change_state( - clone!(@weak self as appwindow => move |action, state_request| { + action_visual_debug.connect_change_state(clone!( + #[weak(rename_to=appwindow)] + self, + move |action, state_request| { let visual_debug = state_request.unwrap().get::().unwrap(); let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().set_visual_debug(visual_debug); appwindow.handle_widget_flags(widget_flags, &canvas); action.set_state(&visual_debug.to_variant()); - }), - ); + } + )); // Create page - action_new_tab.connect_activate(clone!(@weak self as appwindow => move |_, _| { - let wrapper = appwindow.new_canvas_wrapper(); - appwindow.append_wrapper_new_tab(&wrapper); - })); + action_new_tab.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let wrapper = appwindow.new_canvas_wrapper(); + appwindow.append_wrapper_new_tab(&wrapper); + } + )); // Export engine state - action_debug_export_engine_state.connect_activate( - clone!(@weak self as appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::export::filechooser_export_engine_state(&appwindow, &appwindow.active_tab_wrapper().canvas()).await; - })); - }), - ); + action_debug_export_engine_state.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::export::filechooser_export_engine_state( + &appwindow, + &appwindow.active_tab_wrapper().canvas(), + ) + .await; + } + )); + } + )); // Export engine config - action_debug_export_engine_config.connect_activate( - clone!(@weak self as appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::export::filechooser_export_engine_config(&appwindow, &appwindow.active_tab_wrapper().canvas()).await; - })); - }), - ); + action_debug_export_engine_config.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::export::filechooser_export_engine_config( + &appwindow, + &appwindow.active_tab_wrapper().canvas(), + ) + .await; + } + )); + } + )); // Pen sounds - action_pen_sounds.connect_change_state( - clone!(@weak self as appwindow => move |action, state_request| { + action_pen_sounds.connect_change_state(clone!( + #[weak(rename_to=appwindow)] + self, + move |action, state_request| { let pen_sounds = state_request.unwrap().get::().unwrap(); - appwindow.active_tab_wrapper().canvas().engine_mut().set_pen_sounds(pen_sounds, crate::env::pkg_data_dir().ok()); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .set_pen_sounds(pen_sounds, crate::env::pkg_data_dir().ok()); action.set_state(&pen_sounds.to_variant()); - }), - ); + } + )); // Snap positions - action_snap_positions.connect_change_state( - clone!(@weak self as appwindow => move |action, state_request| { + action_snap_positions.connect_change_state(clone!( + #[weak(rename_to=appwindow)] + self, + move |action, state_request| { let snap_positions = state_request.unwrap().get::().unwrap(); - appwindow.active_tab_wrapper().canvas().engine_mut().document.snap_positions = snap_positions; + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .document + .snap_positions = snap_positions; action.set_state(&snap_positions.to_variant()); - }), - ); + } + )); // Show format borders - action_show_format_borders.connect_change_state( - clone!(@weak self as appwindow => move |action, state_request| { + action_show_format_borders.connect_change_state(clone!( + #[weak(rename_to=appwindow)] + self, + move |action, state_request| { let show_format_borders = state_request.unwrap().get::().unwrap(); let canvas = appwindow.active_tab_wrapper().canvas(); canvas.engine_mut().document.format.show_borders = show_format_borders; canvas.queue_draw(); action.set_state(&show_format_borders.to_variant()); - }), - ); + } + )); // Show origin indicator - action_show_origin_indicator.connect_change_state( - clone!(@weak self as appwindow => move |action, state_request| { + action_show_origin_indicator.connect_change_state(clone!( + #[weak(rename_to=appwindow)] + self, + move |action, state_request| { let show_origin_indicator = state_request.unwrap().get::().unwrap(); let canvas = appwindow.active_tab_wrapper().canvas(); canvas.engine_mut().document.format.show_origin_indicator = show_origin_indicator; canvas.queue_draw(); action.set_state(&show_origin_indicator.to_variant()); - }), - ); + } + )); // Pen style - action_pen_style.connect_activate( - clone!(@weak self as appwindow => move |action, target| { + action_pen_style.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |action, target| { let pen_style_str = target.unwrap().str().unwrap(); let pen_style = match PenStyle::from_str(pen_style_str) { Ok(s) => s, @@ -341,342 +415,550 @@ impl RnAppWindow { } action.set_state(&pen_style_str.to_variant()); - }), - ); + } + )); // Tab actions - action_active_tab_move_left.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_active_tab_move_left.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { let active_tab_page = appwindow.active_tab_page(); - appwindow.overlays().tabview().reorder_backward(&active_tab_page); - }), - ); - action_active_tab_move_right.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + appwindow + .overlays() + .tabview() + .reorder_backward(&active_tab_page); + } + )); + action_active_tab_move_right.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { let active_tab_page = appwindow.active_tab_page(); - appwindow.overlays().tabview().reorder_forward(&active_tab_page); - }), - ); - action_active_tab_close.connect_activate(clone!(@weak self as appwindow => move |_, _| { - let active_tab_page = appwindow.active_tab_page(); - if appwindow.overlays().tabview().n_pages() <= 1 { - // If there is only one tab left, request to close the entire window. - appwindow.close(); - } else { - appwindow.close_tab_request(&active_tab_page); + appwindow + .overlays() + .tabview() + .reorder_forward(&active_tab_page); } - })); + )); + action_active_tab_close.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let active_tab_page = appwindow.active_tab_page(); + if appwindow.overlays().tabview().n_pages() <= 1 { + // If there is only one tab left, request to close the entire window. + appwindow.close(); + } else { + appwindow.close_tab_request(&active_tab_page); + } + } + )); // Drawing pad buttons - action_drawing_pad_pressed_button_0.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_drawing_pad_pressed_button_0.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { debug!("Pressed drawing pad button 0"); let canvas = appwindow.active_tab_wrapper().canvas(); - let (_, widget_flags) = canvas.engine_mut().handle_pressed_shortcut_key(ShortcutKey::DrawingPadButton0, Instant::now()); + let (_, widget_flags) = canvas + .engine_mut() + .handle_pressed_shortcut_key(ShortcutKey::DrawingPadButton0, Instant::now()); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); - action_drawing_pad_pressed_button_1.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_drawing_pad_pressed_button_1.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { debug!("Pressed drawing pad button 1"); let canvas = appwindow.active_tab_wrapper().canvas(); - let (_, widget_flags) = canvas.engine_mut().handle_pressed_shortcut_key(ShortcutKey::DrawingPadButton1, Instant::now()); + let (_, widget_flags) = canvas + .engine_mut() + .handle_pressed_shortcut_key(ShortcutKey::DrawingPadButton1, Instant::now()); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); - action_drawing_pad_pressed_button_2.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_drawing_pad_pressed_button_2.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { debug!("Pressed drawing pad button 2"); let canvas = appwindow.active_tab_wrapper().canvas(); - let (_, widget_flags) = canvas.engine_mut().handle_pressed_shortcut_key(ShortcutKey::DrawingPadButton2, Instant::now()); + let (_, widget_flags) = canvas + .engine_mut() + .handle_pressed_shortcut_key(ShortcutKey::DrawingPadButton2, Instant::now()); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); - action_drawing_pad_pressed_button_3.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_drawing_pad_pressed_button_3.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { debug!("Pressed drawing pad button 3"); let canvas = appwindow.active_tab_wrapper().canvas(); - let (_, widget_flags) = canvas.engine_mut().handle_pressed_shortcut_key(ShortcutKey::DrawingPadButton3, Instant::now()); + let (_, widget_flags) = canvas + .engine_mut() + .handle_pressed_shortcut_key(ShortcutKey::DrawingPadButton3, Instant::now()); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); // Trash Selection - action_selection_trash.connect_activate(clone!(@weak self as appwindow => move |_, _| { - let canvas = appwindow.active_tab_wrapper().canvas(); - let widget_flags = canvas.engine_mut().trash_selection(); - appwindow.handle_widget_flags(widget_flags, &canvas); - })); + action_selection_trash.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let canvas = appwindow.active_tab_wrapper().canvas(); + let widget_flags = canvas.engine_mut().trash_selection(); + appwindow.handle_widget_flags(widget_flags, &canvas); + } + )); // Duplicate Selection - action_selection_duplicate.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_selection_duplicate.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().duplicate_selection(); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); // invert color brightness of selection - action_selection_invert_color.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_selection_invert_color.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().invert_selection_colors(); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); // select all strokes - action_selection_select_all.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_selection_select_all.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().select_all_strokes(); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); // deselect all strokes - action_selection_deselect_all.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_selection_deselect_all.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().deselect_all_strokes(); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); // Clear doc - action_clear_doc.connect_activate(clone!(@weak self as appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::dialog_clear_doc(&appwindow, &appwindow.active_tab_wrapper().canvas()).await; - })); - })); + action_clear_doc.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::dialog_clear_doc( + &appwindow, + &appwindow.active_tab_wrapper().canvas(), + ) + .await; + } + )); + } + )); // Undo stroke - action_undo_stroke.connect_activate(clone!(@weak self as appwindow => move |_,_| { - let canvas = appwindow.active_tab_wrapper().canvas(); - let widget_flags = canvas.engine_mut().undo(Instant::now()); - appwindow.handle_widget_flags(widget_flags, &canvas); - })); + action_undo_stroke.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let canvas = appwindow.active_tab_wrapper().canvas(); + let widget_flags = canvas.engine_mut().undo(Instant::now()); + appwindow.handle_widget_flags(widget_flags, &canvas); + } + )); // Redo stroke - action_redo_stroke.connect_activate(clone!(@weak self as appwindow => move |_,_| { - let canvas = appwindow.active_tab_wrapper().canvas(); - let widget_flags = canvas.engine_mut().redo(Instant::now()); - appwindow.handle_widget_flags(widget_flags, &canvas); - })); + action_redo_stroke.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let canvas = appwindow.active_tab_wrapper().canvas(); + let widget_flags = canvas.engine_mut().redo(Instant::now()); + appwindow.handle_widget_flags(widget_flags, &canvas); + } + )); // Zoom reset - action_zoom_reset.connect_activate(clone!(@weak self as appwindow => move |_,_| { - let canvas = appwindow.active_tab_wrapper().canvas(); - let viewport_center = canvas.engine_ref().camera.viewport_center(); - let new_zoom = Camera::ZOOM_DEFAULT; - let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); - widget_flags |= canvas.engine_mut().camera.set_viewport_center(viewport_center); - appwindow.handle_widget_flags(widget_flags, &canvas) - })); + action_zoom_reset.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let canvas = appwindow.active_tab_wrapper().canvas(); + let viewport_center = canvas.engine_ref().camera.viewport_center(); + let new_zoom = Camera::ZOOM_DEFAULT; + let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); + widget_flags |= canvas + .engine_mut() + .camera + .set_viewport_center(viewport_center); + appwindow.handle_widget_flags(widget_flags, &canvas) + } + )); // Zoom fit to width - action_zoom_fit_width.connect_activate(clone!(@weak self as appwindow => move |_,_| { - let canvaswrapper = appwindow.active_tab_wrapper(); - let canvas = canvaswrapper.canvas(); - let viewport_center = canvas.engine_ref().camera.viewport_center(); - let new_zoom = f64::from(canvaswrapper.scroller().width()) - / (canvaswrapper.canvas().engine_ref().document.format.width() + 2.0 * Camera::OVERSHOOT_HORIZONTAL); - let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); - widget_flags |= canvas.engine_mut().camera.set_viewport_center(viewport_center); - appwindow.handle_widget_flags(widget_flags, &canvas) - })); + action_zoom_fit_width.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let canvaswrapper = appwindow.active_tab_wrapper(); + let canvas = canvaswrapper.canvas(); + let viewport_center = canvas.engine_ref().camera.viewport_center(); + let new_zoom = f64::from(canvaswrapper.scroller().width()) + / (canvaswrapper.canvas().engine_ref().document.format.width() + + 2.0 * Camera::OVERSHOOT_HORIZONTAL); + let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); + widget_flags |= canvas + .engine_mut() + .camera + .set_viewport_center(viewport_center); + appwindow.handle_widget_flags(widget_flags, &canvas) + } + )); // Zoom in - action_zoomin.connect_activate(clone!(@weak self as appwindow => move |_,_| { - let canvas = appwindow.active_tab_wrapper().canvas(); - let viewport_center = canvas.engine_ref().camera.viewport_center(); - let new_zoom = canvas.engine_ref().camera.total_zoom() * (1.0 + RnCanvas::ZOOM_SCROLL_STEP); - let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); - widget_flags |= canvas.engine_mut().camera.set_viewport_center(viewport_center); - appwindow.handle_widget_flags(widget_flags, &canvas) - })); + action_zoomin.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let canvas = appwindow.active_tab_wrapper().canvas(); + let viewport_center = canvas.engine_ref().camera.viewport_center(); + let new_zoom = + canvas.engine_ref().camera.total_zoom() * (1.0 + RnCanvas::ZOOM_SCROLL_STEP); + let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); + widget_flags |= canvas + .engine_mut() + .camera + .set_viewport_center(viewport_center); + appwindow.handle_widget_flags(widget_flags, &canvas) + } + )); // Zoom out - action_zoomout.connect_activate(clone!(@weak self as appwindow => move |_,_| { - let canvas = appwindow.active_tab_wrapper().canvas(); - let viewport_center = canvas.engine_ref().camera.viewport_center(); - let new_zoom = canvas.engine_ref().camera.total_zoom() * (1.0 - RnCanvas::ZOOM_SCROLL_STEP); - let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); - widget_flags |= canvas.engine_mut().camera.set_viewport_center(viewport_center); - appwindow.handle_widget_flags(widget_flags, &canvas) - })); + action_zoomout.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let canvas = appwindow.active_tab_wrapper().canvas(); + let viewport_center = canvas.engine_ref().camera.viewport_center(); + let new_zoom = + canvas.engine_ref().camera.total_zoom() * (1.0 - RnCanvas::ZOOM_SCROLL_STEP); + let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); + widget_flags |= canvas + .engine_mut() + .camera + .set_viewport_center(viewport_center); + appwindow.handle_widget_flags(widget_flags, &canvas) + } + )); // Add page to doc in fixed size mode - action_add_page_to_doc.connect_activate( - clone!(@weak self as appwindow => move |_action_add_page_to_doc, _| { + action_add_page_to_doc.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_action_add_page_to_doc, _| { let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().doc_add_page_fixed_size(); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); // Remove page from doc in fixed size mode - action_remove_page_from_doc.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_remove_page_from_doc.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().doc_remove_page_fixed_size(); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); // Resize to fit content - action_resize_to_fit_content.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_resize_to_fit_content.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().doc_resize_to_fit_content(); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); // Return to the origin page - action_return_origin_page.connect_activate(clone!(@weak self as appwindow => move |_,_| { - let canvas = appwindow.active_tab_wrapper().canvas(); + action_return_origin_page.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + let canvas = appwindow.active_tab_wrapper().canvas(); - let widget_flags = canvas.engine_mut().return_to_origin(canvas.parent().map(|p| p.width() as f64)); - appwindow.handle_widget_flags(widget_flags, &canvas); - })); + let widget_flags = canvas + .engine_mut() + .return_to_origin(canvas.parent().map(|p| p.width() as f64)); + appwindow.handle_widget_flags(widget_flags, &canvas); + } + )); // New doc - action_new_doc.connect_activate(clone!(@weak self as appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::dialog_new_doc(&appwindow, &appwindow.active_tab_wrapper().canvas()).await; - })); - })); + action_new_doc.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::dialog_new_doc( + &appwindow, + &appwindow.active_tab_wrapper().canvas(), + ) + .await; + } + )); + } + )); // Open doc - action_open_doc.connect_activate(clone!(@weak self as appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::import::filedialog_open_doc(&appwindow).await; - })); - })); + action_open_doc.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::import::filedialog_open_doc(&appwindow).await; + } + )); + } + )); // Save doc - action_save_doc.connect_activate(clone!(@weak self as appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - let canvas = appwindow.active_tab_wrapper().canvas(); - - if let Some(output_file) = canvas.output_file() { - appwindow.overlays().progressbar_start_pulsing(); - - if let Err(e) = canvas.save_document_to_file(&output_file).await { - error!("Saving document failed, Err: `{e:?}`"); - canvas.set_output_file(None); - appwindow.overlays().dispatch_toast_error(&gettext("Saving document failed")); - appwindow.overlays().progressbar_abort(); - } else { - appwindow.overlays().progressbar_finish(); - // No success toast on saving without dialog, success is already indicated in the header title + action_save_doc.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + let canvas = appwindow.active_tab_wrapper().canvas(); + + if let Some(output_file) = canvas.output_file() { + appwindow.overlays().progressbar_start_pulsing(); + + if let Err(e) = canvas.save_document_to_file(&output_file).await { + error!("Saving document failed, Err: `{e:?}`"); + canvas.set_output_file(None); + appwindow + .overlays() + .dispatch_toast_error(&gettext("Saving document failed")); + appwindow.overlays().progressbar_abort(); + } else { + appwindow.overlays().progressbar_finish(); + // No success toast on saving without dialog, success is already indicated in the header title + } + } else { + // Open a dialog to choose a save location + dialogs::export::dialog_save_doc_as(&appwindow, &canvas).await; + } } - } else { - // Open a dialog to choose a save location - dialogs::export::dialog_save_doc_as(&appwindow, &canvas).await; - } - })); - })); + )); + } + )); // Save doc as - action_save_doc_as.connect_activate(clone!(@weak self as appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::export::dialog_save_doc_as(&appwindow, &appwindow.active_tab_wrapper().canvas()).await; - })); - })); + action_save_doc_as.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::export::dialog_save_doc_as( + &appwindow, + &appwindow.active_tab_wrapper().canvas(), + ) + .await; + } + )); + } + )); // Print doc - action_print_doc.connect_activate(clone!(@weak self as appwindow => move |_, _| { - // TODO: Expose these variables as options in the print dialog - let draw_background = true; - let draw_pattern = true; - let optimize_printing = false; - let page_order = SplitOrder::default(); - let margin = 0.0; - - let canvas = appwindow.active_tab_wrapper().canvas(); - let pages_content = canvas.engine_ref().extract_pages_content(page_order); - let n_pages = pages_content.len(); - - appwindow.overlays().progressbar_start_pulsing(); - - let print_op = PrintOperation::builder() - .unit(Unit::None) - .build(); - - print_op.connect_begin_print(clone!(@weak appwindow => move |print_op, _print_cx| { - print_op.set_n_pages(n_pages as i32); - })); + action_print_doc.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + // TODO: Expose these variables as options in the print dialog + let draw_background = true; + let draw_pattern = true; + let optimize_printing = false; + let page_order = SplitOrder::default(); + let margin = 0.0; - print_op.connect_draw_page(clone!(@weak appwindow, @weak canvas => move |_print_op, print_cx, page_no| { - let page_content = &pages_content[page_no as usize]; - let page_bounds = page_content.bounds.unwrap().loosened(margin); - let print_scale = (print_cx.width() / page_bounds.extents()[0]).min(print_cx.height() / page_bounds.extents()[1]); - let cairo_cx = print_cx.cairo_context(); + let canvas = appwindow.active_tab_wrapper().canvas(); + let pages_content = canvas.engine_ref().extract_pages_content(page_order); + let n_pages = pages_content.len(); - cairo_cx.scale(print_scale, print_scale); - cairo_cx.translate(-page_bounds.mins[0], -page_bounds.mins[1]); - if let Err(e) = page_content.draw_to_cairo(&cairo_cx, draw_background, draw_pattern, optimize_printing, margin, Engine::STROKE_EXPORT_IMAGE_SCALE) { - error!("Drawing page no: {page_no} while printing failed, Err: {e:?}"); - } - })); + appwindow.overlays().progressbar_start_pulsing(); - print_op.connect_status_changed(clone!(@weak appwindow => move |print_op| { - debug!("Print operation status has changed to: {:?}", print_op.status()); - })); + let print_op = PrintOperation::builder().unit(Unit::None).build(); - // Run the print op - if let Err(e) = print_op.run(PrintOperationAction::PrintDialog, Some(&appwindow)){ - error!("Running print operation failed , Err: {e:?}"); - appwindow.overlays().dispatch_toast_error(&gettext("Printing document failed")); - appwindow.overlays().progressbar_abort(); - } else { - appwindow.overlays().progressbar_finish(); + print_op.connect_begin_print(clone!(move |print_op, _print_cx| { + print_op.set_n_pages(n_pages as i32); + })); + + print_op.connect_draw_page(clone!(move |_print_op, print_cx, page_no| { + let page_content = &pages_content[page_no as usize]; + let page_bounds = page_content.bounds.unwrap().loosened(margin); + let print_scale = (print_cx.width() / page_bounds.extents()[0]) + .min(print_cx.height() / page_bounds.extents()[1]); + let cairo_cx = print_cx.cairo_context(); + + cairo_cx.scale(print_scale, print_scale); + cairo_cx.translate(-page_bounds.mins[0], -page_bounds.mins[1]); + if let Err(e) = page_content.draw_to_cairo( + &cairo_cx, + draw_background, + draw_pattern, + optimize_printing, + margin, + Engine::STROKE_EXPORT_IMAGE_SCALE, + ) { + error!("Drawing page no: {page_no} while printing failed, Err: {e:?}"); + } + })); + + print_op.connect_status_changed(clone!(move |print_op| { + debug!( + "Print operation status has changed to: {:?}", + print_op.status() + ); + })); + + // Run the print op + if let Err(e) = print_op.run(PrintOperationAction::PrintDialog, Some(&appwindow)) { + error!("Running print operation failed , Err: {e:?}"); + appwindow + .overlays() + .dispatch_toast_error(&gettext("Printing document failed")); + appwindow.overlays().progressbar_abort(); + } else { + appwindow.overlays().progressbar_finish(); + } } - })); + )); // Import - action_import_file.connect_activate(clone!(@weak self as appwindow => move |_,_| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::import::filedialog_import_file(&appwindow).await; - })); - })); + action_import_file.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::import::filedialog_import_file(&appwindow).await; + } + )); + } + )); // Export document - action_export_doc.connect_activate(clone!(@weak self as appwindow => move |_,_| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::export::dialog_export_doc_w_prefs(&appwindow, &appwindow.active_tab_wrapper().canvas()).await; - })); - })); + action_export_doc.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::export::dialog_export_doc_w_prefs( + &appwindow, + &appwindow.active_tab_wrapper().canvas(), + ) + .await; + } + )); + } + )); // Export document pages - action_export_doc_pages.connect_activate(clone!(@weak self as appwindow => move |_,_| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::export::dialog_export_doc_pages_w_prefs(&appwindow, &appwindow.active_tab_wrapper().canvas()).await; - })); - })); + action_export_doc_pages.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::export::dialog_export_doc_pages_w_prefs( + &appwindow, + &appwindow.active_tab_wrapper().canvas(), + ) + .await; + } + )); + } + )); // Export selection - action_export_selection.connect_activate(clone!(@weak self as appwindow => move |_,_| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - let canvas = appwindow.active_tab_wrapper().canvas(); - - if !canvas.engine_ref().nothing_selected() { - dialogs::export::dialog_export_selection_w_prefs(&appwindow, &appwindow.active_tab_wrapper().canvas()).await; - } else { - appwindow.overlays().dispatch_toast_error(&gettext("Exporting selection failed, nothing selected")); - } - })); - })); + action_export_selection.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + let canvas = appwindow.active_tab_wrapper().canvas(); + + if !canvas.engine_ref().nothing_selected() { + dialogs::export::dialog_export_selection_w_prefs( + &appwindow, + &appwindow.active_tab_wrapper().canvas(), + ) + .await; + } else { + appwindow.overlays().dispatch_toast_error(&gettext( + "Exporting selection failed, nothing selected", + )); + } + } + )); + } + )); // Clipboard copy - action_clipboard_copy.connect_activate(clone!(@weak self as appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { + action_clipboard_copy.connect_activate(clone!(#[weak(rename_to=appwindow)] self, move |_, _| { + glib::spawn_future_local(clone!(#[weak] appwindow, async move { let canvas = appwindow.active_tab_wrapper().canvas(); let receiver = canvas.engine_ref().fetch_clipboard_content(); let (content, widget_flags) = match receiver.await { @@ -704,8 +986,8 @@ impl RnAppWindow { })); // Clipboard cut - action_clipboard_cut.connect_activate(clone!(@weak self as appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { + action_clipboard_cut.connect_activate(clone!(#[weak(rename_to=appwindow)] self, move |_, _| { + glib::spawn_future_local(clone!(#[weak] appwindow, async move { let canvas = appwindow.active_tab_wrapper().canvas(); let receiver = canvas.engine_mut().cut_clipboard_content(); let (content, widget_flags) = match receiver.await { @@ -732,12 +1014,18 @@ impl RnAppWindow { })); // Clipboard paste - action_clipboard_paste.connect_activate(clone!(@weak self as appwindow => move |_, _| { - appwindow.clipboard_paste(None); - })); + action_clipboard_paste.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { + appwindow.clipboard_paste(None); + } + )); - action_clipboard_paste_contextmenu.connect_activate( - clone!(@weak self as appwindow => move |_, _| { + action_clipboard_paste_contextmenu.connect_activate(clone!( + #[weak(rename_to=appwindow)] + self, + move |_, _| { let canvas_wrapper = appwindow.active_tab_wrapper(); let canvas = canvas_wrapper.canvas(); @@ -749,8 +1037,8 @@ impl RnAppWindow { }); appwindow.clipboard_paste(last_contextmenu_pos); - }), - ); + } + )); } pub(crate) fn setup_action_accels(&self) { @@ -798,61 +1086,91 @@ impl RnAppWindow { // Order matters here, we want to go from specific -> generic, mostly because `text/plain` is contained in other text based formats if content_formats.contain_mime_type("text/uri-list") { - glib::spawn_future_local(clone!(@weak self as appwindow => async move { - debug!("Recognized clipboard content format: files list"); - - match appwindow.clipboard().read_text_future().await { - Ok(Some(text)) => { - let file_paths = text.lines().filter_map(|line| { - let file_path = if let Ok(path_uri) = url::Url::parse(line) { - path_uri.to_file_path().ok()? - } else { - PathBuf::from(&line) - }; + glib::spawn_future_local(clone!( + #[weak(rename_to=appwindow)] + self, + async move { + debug!("Recognized clipboard content format: files list"); + + match appwindow.clipboard().read_text_future().await { + Ok(Some(text)) => { + let file_paths = text + .lines() + .filter_map(|line| { + let file_path = if let Ok(path_uri) = url::Url::parse(line) { + path_uri.to_file_path().ok()? + } else { + PathBuf::from(&line) + }; - if file_path.exists() { - Some(file_path) - } else { - None + if file_path.exists() { + Some(file_path) + } else { + None + } + }) + .collect::>(); + + for file_path in file_paths { + appwindow + .open_file_w_dialogs( + gio::File::for_path(&file_path), + target_pos, + true, + ) + .await; } - }).collect::>(); - - for file_path in file_paths { - appwindow.open_file_w_dialogs(gio::File::for_path(&file_path), target_pos, true).await; } - } - Ok(None) => {} - Err(e) => { - error!("Reading clipboard text while pasting clipboard from path failed, Err: {e:?}"); - + Ok(None) => {} + Err(e) => { + error!("Reading clipboard text while pasting clipboard from path failed, Err: {e:?}"); + } } } - })); + )); } else if content_formats.contain_mime_type(StrokeContent::MIME_TYPE) { - glib::spawn_future_local(clone!(@weak canvas, @weak self as appwindow => async move { - debug!("Recognized clipboard content format: {}", StrokeContent::MIME_TYPE); - - match appwindow.clipboard().read_future(&[StrokeContent::MIME_TYPE], glib::source::Priority::DEFAULT).await { - Ok((input_stream, _)) => { - let mut acc = Vec::new(); - loop { - match input_stream.read_future(vec![0; CLIPBOARD_INPUT_STREAM_BUFSIZE], glib::source::Priority::DEFAULT).await { - Ok((mut bytes, n)) => { - if n == 0 { + glib::spawn_future_local(clone!( + #[weak] + canvas, + #[weak(rename_to=appwindow)] + self, + async move { + debug!( + "Recognized clipboard content format: {}", + StrokeContent::MIME_TYPE + ); + + match appwindow + .clipboard() + .read_future(&[StrokeContent::MIME_TYPE], glib::source::Priority::DEFAULT) + .await + { + Ok((input_stream, _)) => { + let mut acc = Vec::new(); + loop { + match input_stream + .read_future( + vec![0; CLIPBOARD_INPUT_STREAM_BUFSIZE], + glib::source::Priority::DEFAULT, + ) + .await + { + Ok((mut bytes, n)) => { + if n == 0 { + break; + } + acc.append(&mut bytes); + } + Err(e) => { + error!("Failed to read clipboard input stream, Err: {e:?}"); + acc.clear(); break; } - acc.append(&mut bytes); - } - Err(e) => { - error!("Failed to read clipboard input stream, Err: {e:?}"); - acc.clear(); - break; } } - } - if !acc.is_empty() { - match crate::utils::str_from_u8_nul_utf8(&acc) { + if !acc.is_empty() { + match crate::utils::str_from_u8_nul_utf8(&acc) { Ok(json_string) => { let resize_argument = ImageSizeOption::ResizeImage(Resize { width: canvas.engine_ref().document.format.width(), @@ -868,41 +1186,55 @@ impl RnAppWindow { } Err(e) => error!("Failed to read stroke content &str from clipboard data, Err: {e:?}"), } + } } - } - Err(e) => { - error!( - "Reading clipboard failed while pasting as `{}`, Err: {e:?}", - StrokeContent::MIME_TYPE - ); - } - }; - })); + Err(e) => { + error!( + "Reading clipboard failed while pasting as `{}`, Err: {e:?}", + StrokeContent::MIME_TYPE + ); + } + }; + } + )); } else if content_formats.contain_mime_type("image/svg+xml") { - glib::spawn_future_local(clone!(@weak self as appwindow => async move { - debug!("Recognized clipboard content: svg image"); - - match appwindow.clipboard().read_future(&["image/svg+xml"], glib::source::Priority::DEFAULT).await { - Ok((input_stream, _)) => { - let mut acc = Vec::new(); - loop { - match input_stream.read_future(vec![0; CLIPBOARD_INPUT_STREAM_BUFSIZE], glib::source::Priority::DEFAULT).await { - Ok((mut bytes, n)) => { - if n == 0 { + glib::spawn_future_local(clone!( + #[weak(rename_to=appwindow)] + self, + async move { + debug!("Recognized clipboard content: svg image"); + + match appwindow + .clipboard() + .read_future(&["image/svg+xml"], glib::source::Priority::DEFAULT) + .await + { + Ok((input_stream, _)) => { + let mut acc = Vec::new(); + loop { + match input_stream + .read_future( + vec![0; CLIPBOARD_INPUT_STREAM_BUFSIZE], + glib::source::Priority::DEFAULT, + ) + .await + { + Ok((mut bytes, n)) => { + if n == 0 { + break; + } + acc.append(&mut bytes); + } + Err(e) => { + error!("Failed to read clipboard input stream while pasting as Svg, Err: {e:?}"); + acc.clear(); break; } - acc.append(&mut bytes); - } - Err(e) => { - error!("Failed to read clipboard input stream while pasting as Svg, Err: {e:?}"); - acc.clear(); - break; } } - } - if !acc.is_empty() { - match crate::utils::str_from_u8_nul_utf8(&acc) { + if !acc.is_empty() { + match crate::utils::str_from_u8_nul_utf8(&acc) { Ok(text) => { if let Err(e) = canvas.load_in_vectorimage_bytes(text.as_bytes().to_vec(), target_pos, appwindow.respect_borders()).await { error!( @@ -912,13 +1244,16 @@ impl RnAppWindow { } Err(e) => error!("Failed to get string from clipboard data while pasting as Svg, Err: {e:?}"), } + } } - } - Err(e) => { - error!("Failed to read clipboard data while pasting as Svg, Err: {e:?}"); - } - }; - })); + Err(e) => { + error!( + "Failed to read clipboard data while pasting as Svg, Err: {e:?}" + ); + } + }; + } + )); } else if content_formats.contain_mime_type("image/png") || content_formats.contain_mime_type("image/jpeg") || content_formats.contain_mime_type("image/jpg") @@ -936,13 +1271,24 @@ impl RnAppWindow { .into_iter() .find(|&mime| content_formats.contain_mime_type(mime)) { - glib::spawn_future_local( - clone!(@weak canvas, @weak self as appwindow => async move { + glib::spawn_future_local(clone!( + #[weak] + canvas, + #[weak(rename_to=appwindow)] + self, + async move { debug!("Recognized clipboard content: bitmap image"); match appwindow.clipboard().read_texture_future().await { Ok(Some(texture)) => { - if let Err(e) = canvas.load_in_bitmapimage_bytes(texture.save_to_png_bytes().to_vec(), target_pos, appwindow.respect_borders()).await { + if let Err(e) = canvas + .load_in_bitmapimage_bytes( + texture.save_to_png_bytes().to_vec(), + target_pos, + appwindow.respect_borders(), + ) + .await + { error!( "Loading bitmap image bytes failed while pasting clipboard as {mime_type}, Err: {e:?}" ); @@ -955,29 +1301,35 @@ impl RnAppWindow { ); } }; - }), - ); + } + )); } } else if content_formats.contain_mime_type("text/plain") || content_formats.contain_mime_type("text/plain;charset=utf-8") { - glib::spawn_future_local(clone!(@weak canvas, @weak self as appwindow => async move { - debug!("Recognized clipboard content: plain text"); - - match appwindow.clipboard().read_text_future().await { - Ok(Some(text)) => { - if let Err(e) = canvas.load_in_text(text.to_string(), target_pos) { - error!("Failed to paste clipboard text, Err: {e:?}"); + glib::spawn_future_local(clone!( + #[weak] + canvas, + #[weak(rename_to=appwindow)] + self, + async move { + debug!("Recognized clipboard content: plain text"); + + match appwindow.clipboard().read_text_future().await { + Ok(Some(text)) => { + if let Err(e) = canvas.load_in_text(text.to_string(), target_pos) { + error!("Failed to paste clipboard text, Err: {e:?}"); + } } - } - Ok(None) => {} - Err(e) => { - error!( + Ok(None) => {} + Err(e) => { + error!( "Reading clipboard text failed while pasting clipboard as plain text, Err: {e:?}" ); + } } } - })); + )); } else { debug!( "Failed to paste clipboard, unsupported MIME-type(s): {:?}", diff --git a/crates/rnote-ui/src/appwindow/appsettings.rs b/crates/rnote-ui/src/appwindow/appsettings.rs index 3588acee84..49ba9596a0 100644 --- a/crates/rnote-ui/src/appwindow/appsettings.rs +++ b/crates/rnote-ui/src/appwindow/appsettings.rs @@ -12,8 +12,10 @@ impl RnAppWindow { .app_settings() .ok_or_else(|| anyhow::anyhow!("Settings schema not found."))?; - app.style_manager().connect_color_scheme_notify( - clone!(@weak app_settings, @weak app, @weak self as appwindow => move |style_manager| { + app.style_manager().connect_color_scheme_notify(clone!( + #[weak] + app_settings, + move |style_manager| { let color_scheme = match style_manager.color_scheme() { adw::ColorScheme::Default => String::from("default"), adw::ColorScheme::ForceLight => String::from("force-light"), @@ -21,12 +23,11 @@ impl RnAppWindow { _ => String::from("default"), }; - if let Err(e) = app_settings - .set_string("color-scheme", &color_scheme) { - error!("Failed to set setting `color-scheme`, Err: {e:?}"); - } - }), - ); + if let Err(e) = app_settings.set_string("color-scheme", &color_scheme) { + error!("Failed to set setting `color-scheme`, Err: {e:?}"); + } + } + )); app_settings .bind("sidebar-show", &self.split_view(), "show-sidebar") @@ -475,15 +476,35 @@ impl RnAppWindow { .app_settings() .ok_or_else(|| anyhow::anyhow!("Settings schema not found."))?; - if let Some(removed_id) = self.imp().periodic_configsave_source_id.borrow_mut().replace( - glib::source::timeout_add_seconds_local( - Self::PERIODIC_CONFIGSAVE_INTERVAL, clone!(@weak app_settings, @weak self as appwindow => @default-return glib::ControlFlow::Break, move || { - if let Err(e) = appwindow.active_tab_wrapper().canvas().save_engine_config(&app_settings) { - error!("Saving engine config in periodic save task failed , Err: {e:?}"); + if let Some(removed_id) = self + .imp() + .periodic_configsave_source_id + .borrow_mut() + .replace(glib::source::timeout_add_seconds_local( + Self::PERIODIC_CONFIGSAVE_INTERVAL, + clone!( + #[weak] + app_settings, + #[weak(rename_to=appwindow)] + self, + #[upgrade_or] + glib::ControlFlow::Break, + move || { + if let Err(e) = appwindow + .active_tab_wrapper() + .canvas() + .save_engine_config(&app_settings) + { + error!( + "Saving engine config in periodic save task failed , Err: {e:?}" + ); + } + + glib::ControlFlow::Continue } - - glib::ControlFlow::Continue - }))) { + ), + )) + { removed_id.remove(); } diff --git a/crates/rnote-ui/src/appwindow/imp.rs b/crates/rnote-ui/src/appwindow/imp.rs index 2ce3676ac4..914516458c 100644 --- a/crates/rnote-ui/src/appwindow/imp.rs +++ b/crates/rnote-ui/src/appwindow/imp.rs @@ -254,9 +254,13 @@ impl WindowImpl for RnAppWindow { toast.dismiss(); } - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::dialog_close_window(&appwindow).await; - })); + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::dialog_close_window(&appwindow).await; + } + )); } else { appwindow.close_force(); } @@ -271,9 +275,13 @@ impl WindowImpl for RnAppWindow { &mut self.save_in_progress_toast.borrow_mut(), ); } else if obj.tabs_any_unsaved_changes() { - glib::spawn_future_local(clone!(@weak obj as appwindow => async move { - dialogs::dialog_close_window(&appwindow).await; - })); + glib::spawn_future_local(clone!( + #[weak(rename_to=appwindow)] + obj, + async move { + dialogs::dialog_close_window(&appwindow).await; + } + )); } else { obj.close_force(); } @@ -294,7 +302,7 @@ impl RnAppWindow { if let Some(removed_id) = self.autosave_source_id.borrow_mut().replace( glib::source::timeout_add_seconds_local( self.autosave_interval_secs.get(), - clone!(@weak obj as appwindow => @default-return glib::ControlFlow::Break, move || { + clone!(#[weak(rename_to=appwindow)] obj, #[upgrade_or] glib::ControlFlow::Break, move || { // save for all tabs opened in the current window that have unsaved changes let tabs = appwindow.get_all_tabs(); @@ -305,7 +313,7 @@ impl RnAppWindow { trace!( "there are unsaved changes on the tab {:?} with a file on disk, saving",i ); - glib::spawn_future_local(clone!(@weak canvas, @weak appwindow => async move { + glib::spawn_future_local(clone!(#[weak] canvas, #[weak] appwindow ,async move { if let Err(e) = canvas.save_document_to_file(&output_file).await { error!("Saving document failed, Err: `{e:?}`"); canvas.set_output_file(None); @@ -443,23 +451,33 @@ impl RnAppWindow { let sidebar_expanded_shown = Rc::new(Cell::new(false)); - self.split_view.connect_show_sidebar_notify( - clone!(@strong sidebar_expanded_shown, @weak obj as appwindow => move |split_view| { + self.split_view.connect_show_sidebar_notify(clone!( + #[strong] + sidebar_expanded_shown, + #[weak(rename_to=appwindow)] + obj, + move |split_view| { if !split_view.is_collapsed() { sidebar_expanded_shown.set(split_view.shows_sidebar()); } update_widgets(split_view, &appwindow); - }), - ); + } + )); - self.split_view.connect_sidebar_position_notify( - clone!(@weak obj as appwindow => move |split_view| { + self.split_view.connect_sidebar_position_notify(clone!( + #[weak(rename_to=appwindow)] + obj, + move |split_view| { update_widgets(split_view, &appwindow); - }), - ); - - self.split_view.connect_collapsed_notify( - clone!(@strong sidebar_expanded_shown, @weak obj as appwindow => move |split_view| { + } + )); + + self.split_view.connect_collapsed_notify(clone!( + #[strong] + sidebar_expanded_shown, + #[weak(rename_to=appwindow)] + obj, + move |split_view| { if split_view.is_collapsed() { // Always hide sidebar when transitioning from non-collapsed to collapsed. split_view.set_show_sidebar(false); @@ -472,8 +490,8 @@ impl RnAppWindow { sidebar_expanded_shown.set(split_view.shows_sidebar()); } update_widgets(split_view, &appwindow); - }), - ); + } + )); } fn handle_righthanded_property(&self, righthanded: bool) { diff --git a/crates/rnote-ui/src/canvas/mod.rs b/crates/rnote-ui/src/canvas/mod.rs index ea504b0f60..40cb0ec03d 100644 --- a/crates/rnote-ui/src/canvas/mod.rs +++ b/crates/rnote-ui/src/canvas/mod.rs @@ -218,10 +218,14 @@ mod imp { obj.add_controller(self.drop_target.clone()); // receive and handle engine tasks - let engine_task_handler_handle = glib::spawn_future_local( - clone!(@weak obj as canvas => async move { + let engine_task_handler_handle = glib::spawn_future_local(clone!( + #[weak(rename_to=canvas)] + obj, + async move { let Some(mut task_rx) = canvas.engine_mut().take_engine_tasks_rx() else { - error!("Installing the engine task handler failed, taken tasks_rx is None."); + error!( + "Installing the engine task handler failed, taken tasks_rx is None." + ); return; }; @@ -235,8 +239,8 @@ mod imp { } } } - }), - ); + } + )); *self.engine_task_handler_handle.borrow_mut() = Some(engine_task_handler_handle); @@ -468,29 +472,51 @@ mod imp { // Pointer controller let pen_state = Cell::new(PenState::Up); - self.pointer_controller.connect_event(clone!(@strong pen_state, @weak obj as canvas => @default-return glib::Propagation::Proceed, move |_, event| { - let (propagation, new_state) = super::input::handle_pointer_controller_event(&canvas, event, pen_state.get()); - pen_state.set(new_state); - propagation - })); + self.pointer_controller.connect_event(clone!( + #[strong] + pen_state, + #[weak(rename_to=canvas)] + obj, + #[upgrade_or] + glib::Propagation::Proceed, + move |_, event| { + let (propagation, new_state) = super::input::handle_pointer_controller_event( + &canvas, + event, + pen_state.get(), + ); + pen_state.set(new_state); + propagation + } + )); // For unicode text the input is committed from the IM context, and won't trigger the key_pressed signal - self.key_controller_im_context.connect_commit( - clone!(@weak obj as canvas => move |_cx, text| { + self.key_controller_im_context.connect_commit(clone!( + #[weak(rename_to=canvas)] + obj, + move |_cx, text| { super::input::handle_imcontext_text_commit(&canvas, text); - }), - ); + } + )); // Key controller - self.key_controller.connect_key_pressed(clone!(@weak obj as canvas => @default-return glib::Propagation::Proceed, move |_, key, _raw, modifier| { - super::input::handle_key_controller_key_pressed(&canvas, key, modifier) - })); + self.key_controller.connect_key_pressed(clone!( + #[weak(rename_to=canvas)] + obj, + #[upgrade_or] + glib::Propagation::Proceed, + move |_, key, _raw, modifier| { + super::input::handle_key_controller_key_pressed(&canvas, key, modifier) + } + )); - self.key_controller.connect_key_released( - clone!(@weak obj as canvas => move |_key_controller, key, _raw, modifier| { + self.key_controller.connect_key_released(clone!( + #[weak(rename_to=canvas)] + obj, + move |_key_controller, key, _raw, modifier| { super::input::handle_key_controller_key_released(&canvas, key, modifier) - }), - ); + } + )); } fn set_hadjustment_prop(&self, hadj: Option) { @@ -517,12 +543,15 @@ mod imp { } if let Some(ref hadj) = hadj { - let signal_id = - hadj.connect_value_changed(clone!(@weak obj as canvas => move |_| { + let signal_id = hadj.connect_value_changed(clone!( + #[weak(rename_to=canvas)] + obj, + move |_| { // this triggers a canvaslayout allocate() call, // where the camera and content rendering is updated based on some conditions canvas.queue_resize(); - })); + } + )); self.connections.borrow_mut().hadjustment.replace(signal_id); } @@ -559,12 +588,15 @@ mod imp { } if let Some(ref vadj) = vadj { - let signal_id = - vadj.connect_value_changed(clone!(@weak obj as canvas => move |_| { + let signal_id = vadj.connect_value_changed(clone!( + #[weak(rename_to=canvas)] + obj, + move |_| { // this triggers a canvaslayout allocate() call, // where the camera and content rendering is updated based on some conditions canvas.queue_resize(); - })); + } + )); self.connections.borrow_mut().vadjustment.replace(signal_id); } @@ -895,23 +927,36 @@ impl RnCanvas { canvas.set_unsaved_changes(true); appwindow.overlays().dispatch_toast_w_button_singleton( - &gettext("Opened file was modified on disk"), - &gettext("Reload"), - clone!(@weak canvas, @weak appwindow => move |_reload_toast| { - glib::spawn_future_local(clone!(@weak appwindow => async move { + &gettext("Opened file was modified on disk"), + &gettext("Reload"), + clone!( + #[weak] + canvas, + #[weak] + appwindow, + move |_reload_toast| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { appwindow.overlays().progressbar_start_pulsing(); if let Err(e) = canvas.reload_from_disk().await { error!("Failed to reload current output file, Err: {e:?}"); - appwindow.overlays().dispatch_toast_error(&gettext("Reloading .rnote file from disk failed")); + appwindow.overlays().dispatch_toast_error(&gettext( + "Reloading .rnote file from disk failed", + )); appwindow.overlays().progressbar_abort(); } else { appwindow.overlays().progressbar_finish(); } - })); - }), - None, - &canvas.imp().output_file_modified_toast_singleton); + } + )); + } + ), + None, + &canvas.imp().output_file_modified_toast_singleton, + ); }; let event_handler = move |appwindow: &RnAppWindow, @@ -1000,8 +1045,14 @@ impl RnCanvas { } }; - let new_watcher_task = glib::spawn_future_local( - glib::clone!(@strong file, @weak self as canvas, @weak appwindow => async move { + let new_watcher_task = glib::spawn_future_local(glib::clone!( + #[strong] + file, + #[weak(rename_to=canvas)] + self, + #[weak] + appwindow, + async move { let (tx, mut rx) = futures::channel::mpsc::unbounded(); let Some(file_path) = file.path() else { warn!("Can't create watcher for file that has no path"); @@ -1012,23 +1063,33 @@ impl RnCanvas { return; }; - let mut debouncer = match notify_debouncer_full::new_debouncer(Duration::from_millis(1000), None, move |res| { - if let Err(e) = tx.unbounded_send(res) { - error!("File watcher reported change, but failed to send it through channel. Err: {e:?}"); - } - }) { - Ok(w) => { - w + let mut debouncer = match notify_debouncer_full::new_debouncer( + Duration::from_millis(1000), + None, + move |res| { + if let Err(e) = tx.unbounded_send(res) { + error!("File watcher reported change, but failed to send it through channel. Err: {e:?}"); + } }, + ) { + Ok(w) => w, Err(e) => { error!("Failed to create file watcher, Err: {e:?}"); return; } }; - if let Err(e) = debouncer.watcher().watch(parent_path, notify::RecursiveMode::NonRecursive) { - error!("Failed to start watching directory '{}', Err: {e:?}", parent_path.display()); + if let Err(e) = debouncer + .watcher() + .watch(parent_path, notify::RecursiveMode::NonRecursive) + { + error!( + "Failed to start watching directory '{}', Err: {e:?}", + parent_path.display() + ); } - debouncer.cache().add_root(parent_path, notify::RecursiveMode::NonRecursive); + debouncer + .cache() + .add_root(parent_path, notify::RecursiveMode::NonRecursive); while let Some(res) = rx.next().await { match res { Ok(events) => { @@ -1039,8 +1100,8 @@ impl RnCanvas { Err(e) => error!("File watcher sent error message, Err: {e:?}"), } } - }), - ); + } + )); if let Some(old_watcher_task) = self .imp() @@ -1069,16 +1130,20 @@ impl RnCanvas { let appwindow_output_file = self.connect_notify_local( Some("output-file"), - clone!(@weak appwindow => move |canvas, _pspec| { - if let Some(output_file) = canvas.output_file(){ - canvas.create_output_file_watcher(&output_file, &appwindow); - } else { - canvas.clear_output_file_watcher(); - canvas.dismiss_output_file_modified_toast(); - } + clone!( + #[weak] + appwindow, + move |canvas, _pspec| { + if let Some(output_file) = canvas.output_file() { + canvas.create_output_file_watcher(&output_file, &appwindow); + } else { + canvas.clear_output_file_watcher(); + canvas.dismiss_output_file_modified_toast(); + } - appwindow.refresh_titles(&appwindow.active_tab_wrapper()); - }), + appwindow.refresh_titles(&appwindow.active_tab_wrapper()); + } + ), ); // set scale factor initially @@ -1097,21 +1162,29 @@ impl RnCanvas { // Reset let appwindow_save_in_progress = self.connect_notify_local( Some("save-in-progress"), - clone!(@weak appwindow => move |canvas, _| { - if canvas.save_in_progress() { - appwindow.set_save_in_progress(true); - } else if !appwindow.tabs_any_saves_in_progress() { - appwindow.set_save_in_progress(false); + clone!( + #[weak] + appwindow, + move |canvas, _| { + if canvas.save_in_progress() { + appwindow.set_save_in_progress(true); + } else if !appwindow.tabs_any_saves_in_progress() { + appwindow.set_save_in_progress(false); + } } - }), + ), ); // Update titles when there are changes let appwindow_unsaved_changes = self.connect_notify_local( Some("unsaved-changes"), - clone!(@weak appwindow => move |_, _| { - appwindow.refresh_titles(&appwindow.active_tab_wrapper()); - }), + clone!( + #[weak] + appwindow, + move |_, _| { + appwindow.refresh_titles(&appwindow.active_tab_wrapper()); + } + ), ); // one per-appwindow property for touch-drawing @@ -1149,53 +1222,75 @@ impl RnCanvas { .build(); // Drop Target - let appwindow_drop_target = self.imp().drop_target.connect_drop( - clone!(@weak self as canvas, @weak appwindow => @default-return false, move |_, value, x, y| { - let pos = (canvas.engine_ref().camera.transform().inverse() * - na::point![x,y]).coords; + let appwindow_drop_target = self.imp().drop_target.connect_drop(clone!( + #[weak(rename_to=canvas)] + self, + #[weak] + appwindow, + #[upgrade_or] + false, + move |_, value, x, y| { + let pos = + (canvas.engine_ref().camera.transform().inverse() * na::point![x, y]).coords; let mut accept_drop = false; if value.is::() { // In some scenarios, get() can fail with `UnexpectedNone` even though is() returned true, e.g. when dealing with trashed files. match value.get::() { Ok(file) => { - glib::spawn_future_local(clone!(@weak appwindow => async move { - appwindow.open_file_w_dialogs(file, Some(pos), true).await; - })); + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + appwindow.open_file_w_dialogs(file, Some(pos), true).await; + } + )); accept_drop = true; - }, + } Err(e) => { error!("Failed to get dropped in file, Err: {e:?}"); - appwindow.overlays().dispatch_toast_error(&gettext("Inserting file failed")); - }, + appwindow + .overlays() + .dispatch_toast_error(&gettext("Inserting file failed")); + } }; } else if value.is::() { match canvas.load_in_text(value.get::().unwrap(), Some(pos)) { Ok(_) => { accept_drop = true; - }, + } Err(e) => { error!("Failed to insert dropped in text, Err: {e:?}"); - appwindow.overlays().dispatch_toast_error(&gettext("Inserting text failed")); + appwindow + .overlays() + .dispatch_toast_error(&gettext("Inserting text failed")); } }; } accept_drop - }), - ); + } + )); // handle widget flags let appwindow_handle_widget_flags = self.connect_local( "handle-widget-flags", false, - clone!(@weak self as canvas, @weak appwindow => @default-return None, move |args| { - // first argument is the widget, second is widget flags - let widget_flags = args[1].get::().unwrap().inner(); - - appwindow.handle_widget_flags(widget_flags, &canvas); - None - }), + clone!( + #[weak(rename_to=canvas)] + self, + #[weak] + appwindow, + #[upgrade_or] + None, + move |args| { + // first argument is the widget, second is widget flags + let widget_flags = args[1].get::().unwrap().inner(); + + appwindow.handle_widget_flags(widget_flags, &canvas); + None + } + ), ); // Replace connections diff --git a/crates/rnote-ui/src/canvaswrapper.rs b/crates/rnote-ui/src/canvaswrapper.rs index a2fcddfaa3..a860f336f8 100644 --- a/crates/rnote-ui/src/canvaswrapper.rs +++ b/crates/rnote-ui/src/canvaswrapper.rs @@ -192,11 +192,15 @@ mod imp { let canvas_touch_drawing_handler = self.canvas.connect_notify_local( Some("touch-drawing"), - clone!(@weak obj as canvaswrapper => move |_canvas, _pspec| { - // Disable the zoom gesture and kinetic scrolling when touch drawing is enabled. - canvaswrapper.imp().canvas_kinetic_scrolling_update(); - canvaswrapper.imp().canvas_zoom_gesture_update(); - }), + clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_canvas, _pspec| { + // Disable the zoom gesture and kinetic scrolling when touch drawing is enabled. + canvaswrapper.imp().canvas_kinetic_scrolling_update(); + canvaswrapper.imp().canvas_zoom_gesture_update(); + } + ), ); self.canvas_touch_drawing_handler @@ -300,68 +304,92 @@ mod imp { let obj = self.obj(); { - self.pointer_motion_controller.connect_motion( - clone!(@weak obj as canvaswrapper => move |_, x, y| { + self.pointer_motion_controller.connect_motion(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_, x, y| { canvaswrapper.imp().pointer_pos.set(Some(na::vector![x, y])); - }), - ); + } + )); - self.pointer_motion_controller.connect_leave( - clone!(@weak obj as canvaswrapper => move |_| { + self.pointer_motion_controller.connect_leave(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_| { canvaswrapper.imp().pointer_pos.set(None); - }), - ); + } + )); } // Actions when moving view with controls provided by the scroller ScrolledWindow. // e.g. touch scrolling when inertial-scrolling is enabled. { - self.scroller.connect_edge_overshot( - clone!(@weak obj as canvaswrapper => move |_, _| { + self.scroller.connect_edge_overshot(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_, _| { let canvas = canvaswrapper.canvas(); let widget_flags = canvas.engine_mut().doc_expand_autoexpand(); canvas.emit_handle_widget_flags(widget_flags); - }), - ); + } + )); } // zoom scrolling with + scroll { - self.canvas_zoom_scroll_controller.connect_scroll( - clone!(@weak obj as canvaswrapper => @default-return glib::Propagation::Proceed, move |controller, _, dy| { - if controller.current_event_state() != gdk::ModifierType::CONTROL_MASK { - return glib::Propagation::Proceed; - } - let canvas = canvaswrapper.canvas(); - let old_zoom = canvas.engine_ref().camera.total_zoom(); - let new_zoom = old_zoom * (1.0 - dy * RnCanvas::ZOOM_SCROLL_STEP); - - if (Camera::ZOOM_MIN..=Camera::ZOOM_MAX).contains(&new_zoom) { - let camera_offset = canvas.engine_ref().camera.offset(); - let camera_size = canvas.engine_ref().camera.size(); - let screen_offset = canvaswrapper.imp().pointer_pos.get() - .map(|p| { - let p = canvaswrapper.compute_point(&canvas, &graphene::Point::from_na_vec(p)).unwrap(); - p.to_na_vec() - }) - .unwrap_or_else(|| camera_size * 0.5); - let new_camera_offset = (((camera_offset + screen_offset) / old_zoom) * new_zoom) - screen_offset; - - let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); - widget_flags |= canvas.engine_mut().camera_set_offset_expand(new_camera_offset); - canvas.emit_handle_widget_flags(widget_flags); - } + self.canvas_zoom_scroll_controller.connect_scroll(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + #[upgrade_or] + glib::Propagation::Proceed, + move |controller, _, dy| { + if controller.current_event_state() != gdk::ModifierType::CONTROL_MASK { + return glib::Propagation::Proceed; + } + let canvas = canvaswrapper.canvas(); + let old_zoom = canvas.engine_ref().camera.total_zoom(); + let new_zoom = old_zoom * (1.0 - dy * RnCanvas::ZOOM_SCROLL_STEP); + + if (Camera::ZOOM_MIN..=Camera::ZOOM_MAX).contains(&new_zoom) { + let camera_offset = canvas.engine_ref().camera.offset(); + let camera_size = canvas.engine_ref().camera.size(); + let screen_offset = canvaswrapper + .imp() + .pointer_pos + .get() + .map(|p| { + let p = canvaswrapper + .compute_point(&canvas, &graphene::Point::from_na_vec(p)) + .unwrap(); + p.to_na_vec() + }) + .unwrap_or_else(|| camera_size * 0.5); + let new_camera_offset = (((camera_offset + screen_offset) / old_zoom) + * new_zoom) + - screen_offset; - glib::Propagation::Stop - })); + let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); + widget_flags |= canvas + .engine_mut() + .camera_set_offset_expand(new_camera_offset); + canvas.emit_handle_widget_flags(widget_flags); + } + + glib::Propagation::Stop + } + )); } // Drag canvas gesture { let touch_drag_start = Rc::new(Cell::new(na::vector![0.0, 0.0])); - self.canvas_drag_gesture.connect_drag_begin( - clone!(@strong touch_drag_start, @weak obj as canvaswrapper => move |_, _, _| { + self.canvas_drag_gesture.connect_drag_begin(clone!( + #[strong] + touch_drag_start, + #[weak(rename_to=canvaswrapper)] + obj, + move |_, _, _| { // We don't claim the sequence, because we we want to allow touch zooming. // When the zoom gesture is recognized, it claims it and denies this touch drag gesture. @@ -369,47 +397,78 @@ mod imp { canvaswrapper.canvas().hadjustment().unwrap().value(), canvaswrapper.canvas().vadjustment().unwrap().value() ]); - }), - ); - self.canvas_drag_gesture.connect_drag_update( - clone!(@strong touch_drag_start, @weak obj as canvaswrapper => move |_, x, y| { + } + )); + self.canvas_drag_gesture.connect_drag_update(clone!( + #[strong] + touch_drag_start, + #[weak(rename_to=canvaswrapper)] + obj, + move |_, x, y| { let canvas = canvaswrapper.canvas(); - let new_offset = touch_drag_start.get() - na::vector![x,y]; + let new_offset = touch_drag_start.get() - na::vector![x, y]; let widget_flags = canvas.engine_mut().camera_set_offset_expand(new_offset); canvas.emit_handle_widget_flags(widget_flags); - }), - ); - self.canvas_drag_gesture.connect_drag_end( - clone!(@weak obj as canvaswrapper => move |_, _, _| { - let widget_flags = canvaswrapper.canvas().engine_mut().update_rendering_current_viewport(); - canvaswrapper.canvas().emit_handle_widget_flags(widget_flags); - }), - ); + } + )); + self.canvas_drag_gesture.connect_drag_end(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_, _, _| { + let widget_flags = canvaswrapper + .canvas() + .engine_mut() + .update_rendering_current_viewport(); + canvaswrapper + .canvas() + .emit_handle_widget_flags(widget_flags); + } + )); } // Move Canvas with middle mouse button { let mouse_drag_start = Rc::new(Cell::new(na::vector![0.0, 0.0])); - self.canvas_mouse_drag_middle_gesture.connect_drag_begin( - clone!(@strong mouse_drag_start, @weak obj as canvaswrapper => move |_, _, _| { - mouse_drag_start.set(canvaswrapper.canvas().engine_ref().camera.offset()); - }), - ); - self.canvas_mouse_drag_middle_gesture.connect_drag_update( - clone!(@strong mouse_drag_start, @weak obj as canvaswrapper => move |_, x, y| { - let canvas = canvaswrapper.canvas(); - let new_offset = mouse_drag_start.get() - na::vector![x,y]; - let widget_flags = canvas.engine_mut().camera_set_offset_expand(new_offset); - canvas.emit_handle_widget_flags(widget_flags); - }), - ); - self.canvas_mouse_drag_middle_gesture.connect_drag_end( - clone!(@weak obj as canvaswrapper => move |_, _, _| { - let widget_flags = canvaswrapper.canvas().engine_mut().update_rendering_current_viewport(); - canvaswrapper.canvas().emit_handle_widget_flags(widget_flags); - }), - ); + self.canvas_mouse_drag_middle_gesture + .connect_drag_begin(clone!( + #[strong] + mouse_drag_start, + #[weak(rename_to=canvaswrapper)] + obj, + move |_, _, _| { + mouse_drag_start + .set(canvaswrapper.canvas().engine_ref().camera.offset()); + } + )); + self.canvas_mouse_drag_middle_gesture + .connect_drag_update(clone!( + #[strong] + mouse_drag_start, + #[weak(rename_to=canvaswrapper)] + obj, + move |_, x, y| { + let canvas = canvaswrapper.canvas(); + let new_offset = mouse_drag_start.get() - na::vector![x, y]; + let widget_flags = + canvas.engine_mut().camera_set_offset_expand(new_offset); + canvas.emit_handle_widget_flags(widget_flags); + } + )); + self.canvas_mouse_drag_middle_gesture + .connect_drag_end(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_, _, _| { + let widget_flags = canvaswrapper + .canvas() + .engine_mut() + .update_rendering_current_viewport(); + canvaswrapper + .canvas() + .emit_handle_widget_flags(widget_flags); + } + )); } // Canvas gesture zooming with dragging @@ -421,12 +480,19 @@ mod imp { let offset_begin = Rc::new(Cell::new(na::vector![0.0, 0.0])); self.canvas_zoom_gesture.connect_begin(clone!( - @strong zoom_begin, - @strong new_zoom, - @strong prev_scale, - @strong bbcenter_begin, - @strong offset_begin, - @weak obj as canvaswrapper => move |gesture, _| { + #[strong] + zoom_begin, + #[strong] + new_zoom, + #[strong] + prev_scale, + #[strong] + bbcenter_begin, + #[strong] + offset_begin, + #[weak(rename_to=canvaswrapper)] + obj, + move |gesture, _| { gesture.set_state(EventSequenceState::Claimed); let current_zoom = canvaswrapper.canvas().engine_ref().camera.total_zoom(); @@ -434,59 +500,92 @@ mod imp { new_zoom.set(current_zoom); prev_scale.set(1.0); - bbcenter_begin.set(gesture.bounding_box_center().map(|coords| na::vector![coords.0, coords.1])); + bbcenter_begin.set( + gesture + .bounding_box_center() + .map(|coords| na::vector![coords.0, coords.1]), + ); offset_begin.set(canvaswrapper.canvas().engine_ref().camera.offset()); - }) - ); + } + )); self.canvas_zoom_gesture.connect_scale_changed(clone!( - @strong zoom_begin, - @strong new_zoom, - @strong prev_scale, - @strong bbcenter_begin, - @strong offset_begin, - @weak obj as canvaswrapper => move |gesture, scale| { + #[strong] + zoom_begin, + #[strong] + new_zoom, + #[strong] + prev_scale, + #[strong] + bbcenter_begin, + #[strong] + offset_begin, + #[weak(rename_to=canvaswrapper)] + obj, + move |gesture, scale| { let canvas = canvaswrapper.canvas(); - if (Camera::ZOOM_MIN..=Camera::ZOOM_MAX).contains(&(zoom_begin.get() * scale)) { + if (Camera::ZOOM_MIN..=Camera::ZOOM_MAX) + .contains(&(zoom_begin.get() * scale)) + { new_zoom.set(zoom_begin.get() * scale); prev_scale.set(scale); } let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom.get()); - if let Some(bbcenter_current) = gesture.bounding_box_center().map(|coords| na::vector![coords.0, coords.1]) { - let bbcenter_begin = if let Some(bbcenter_begin) = bbcenter_begin.get() { + if let Some(bbcenter_current) = gesture + .bounding_box_center() + .map(|coords| na::vector![coords.0, coords.1]) + { + let bbcenter_begin = if let Some(bbcenter_begin) = bbcenter_begin.get() + { bbcenter_begin } else { // Set the center if not set by gesture begin handler bbcenter_begin.set(Some(bbcenter_current)); bbcenter_current }; - let bbcenter_delta = bbcenter_current - bbcenter_begin * prev_scale.get(); + let bbcenter_delta = + bbcenter_current - bbcenter_begin * prev_scale.get(); let new_offset = offset_begin.get() * prev_scale.get() - bbcenter_delta; - widget_flags |= canvas.engine_mut().camera_set_offset_expand(new_offset); + widget_flags |= + canvas.engine_mut().camera_set_offset_expand(new_offset); } canvas.emit_handle_widget_flags(widget_flags); - }) - ); + } + )); - self.canvas_zoom_gesture.connect_end( - clone!(@weak obj as canvaswrapper => move |gesture, _event_sequence| { + self.canvas_zoom_gesture.connect_end(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |gesture, _event_sequence| { gesture.set_state(EventSequenceState::Denied); - let widget_flags = canvaswrapper.canvas().engine_mut().update_rendering_current_viewport(); - canvaswrapper.canvas().emit_handle_widget_flags(widget_flags); - }), - ); + let widget_flags = canvaswrapper + .canvas() + .engine_mut() + .update_rendering_current_viewport(); + canvaswrapper + .canvas() + .emit_handle_widget_flags(widget_flags); + } + )); - self.canvas_zoom_gesture.connect_cancel( - clone!(@weak obj as canvaswrapper => move |gesture, _event_sequence| { + self.canvas_zoom_gesture.connect_cancel(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |gesture, _event_sequence| { gesture.set_state(EventSequenceState::Denied); - let widget_flags = canvaswrapper.canvas().engine_mut().update_rendering_current_viewport(); - canvaswrapper.canvas().emit_handle_widget_flags(widget_flags); - }), - ); + let widget_flags = canvaswrapper + .canvas() + .engine_mut() + .update_rendering_current_viewport(); + canvaswrapper + .canvas() + .emit_handle_widget_flags(widget_flags); + } + )); } // Pan with alt + drag @@ -494,8 +593,11 @@ mod imp { let offset_start = Rc::new(Cell::new(na::Vector2::::zeros())); self.canvas_alt_drag_gesture.connect_drag_begin(clone!( - @strong offset_start, - @weak obj as canvaswrapper => move |gesture, _, _| { + #[strong] + offset_start, + #[weak(rename_to=canvaswrapper)] + obj, + move |gesture, _, _| { let modifiers = gesture.current_event_state(); // At the start BUTTON1_MASK is not included @@ -505,23 +607,35 @@ mod imp { } else { gesture.set_state(EventSequenceState::Denied); } - })); - - self.canvas_alt_drag_gesture.connect_drag_update( - clone!(@strong offset_start, @weak obj as canvaswrapper => move |_, offset_x, offset_y| { + } + )); + + self.canvas_alt_drag_gesture.connect_drag_update(clone!( + #[strong] + offset_start, + #[weak(rename_to=canvaswrapper)] + obj, + move |_, offset_x, offset_y| { let canvas = canvaswrapper.canvas(); let new_offset = offset_start.get() - na::vector![offset_x, offset_y]; let widget_flags = canvas.engine_mut().camera_set_offset_expand(new_offset); canvas.emit_handle_widget_flags(widget_flags); - }) - ); - - self.canvas_alt_drag_gesture.connect_drag_end( - clone!(@weak obj as canvaswrapper => move |_, _, _| { - let widget_flags = canvaswrapper.canvas().engine_mut().update_rendering_current_viewport(); - canvaswrapper.canvas().emit_handle_widget_flags(widget_flags); - }), - ); + } + )); + + self.canvas_alt_drag_gesture.connect_drag_end(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_, _, _| { + let widget_flags = canvaswrapper + .canvas() + .engine_mut() + .update_rendering_current_viewport(); + canvaswrapper + .canvas() + .emit_handle_widget_flags(widget_flags); + } + )); } // Zoom with alt + shift + drag @@ -529,78 +643,117 @@ mod imp { let zoom_begin = Rc::new(Cell::new(1_f64)); let prev_offset = Rc::new(Cell::new(na::Vector2::::zeros())); - self - .canvas_alt_shift_drag_gesture - .connect_drag_begin(clone!( - @strong zoom_begin, - @strong prev_offset, - @weak obj as canvaswrapper => move |gesture, _, _| { - let modifiers = gesture.current_event_state(); - - // At the start BUTTON1_MASK is not included - if modifiers == (gdk::ModifierType::SHIFT_MASK | gdk::ModifierType::ALT_MASK) { - gesture.set_state(EventSequenceState::Claimed); - let current_zoom = canvaswrapper.canvas().engine_ref().camera.total_zoom(); - zoom_begin.set(current_zoom); - prev_offset.set(na::Vector2::::zeros()); - } else { - gesture.set_state(EventSequenceState::Denied); + self.canvas_alt_shift_drag_gesture + .connect_drag_begin(clone!( + #[strong] + zoom_begin, + #[strong] + prev_offset, + #[weak(rename_to=canvaswrapper)] + obj, + move |gesture, _, _| { + let modifiers = gesture.current_event_state(); + + // At the start BUTTON1_MASK is not included + if modifiers + == (gdk::ModifierType::SHIFT_MASK | gdk::ModifierType::ALT_MASK) + { + gesture.set_state(EventSequenceState::Claimed); + let current_zoom = + canvaswrapper.canvas().engine_ref().camera.total_zoom(); + zoom_begin.set(current_zoom); + prev_offset.set(na::Vector2::::zeros()); + } else { + gesture.set_state(EventSequenceState::Denied); + } } - }) - ); - - self.canvas_alt_shift_drag_gesture.connect_drag_update(clone!( - @strong zoom_begin, - @strong prev_offset, - @weak obj as canvaswrapper => move |_, offset_x, offset_y| { - let canvas = canvaswrapper.canvas(); - let new_offset = na::vector![offset_x, offset_y]; - let current_total_zoom = canvaswrapper.canvas().engine_ref().camera.total_zoom(); - // drag down zooms out, drag up zooms in - let new_zoom = current_total_zoom - * (1.0 - (new_offset[1] - prev_offset.get()[1]) * Camera::DRAG_ZOOM_MAGN_ZOOM_FACTOR); - - if (Camera::ZOOM_MIN..=Camera::ZOOM_MAX).contains(&new_zoom) { - let viewport_center = canvas.engine_ref().camera.viewport_center(); - - let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); - widget_flags |= canvas.engine_mut().camera.set_viewport_center(viewport_center); - widget_flags |= canvas.engine_mut().doc_expand_autoexpand(); - canvas.emit_handle_widget_flags(widget_flags); + )); + + self.canvas_alt_shift_drag_gesture + .connect_drag_update(clone!( + #[strong] + prev_offset, + #[weak(rename_to=canvaswrapper)] + obj, + move |_, offset_x, offset_y| { + let canvas = canvaswrapper.canvas(); + let new_offset = na::vector![offset_x, offset_y]; + let current_total_zoom = + canvaswrapper.canvas().engine_ref().camera.total_zoom(); + // drag down zooms out, drag up zooms in + let new_zoom = current_total_zoom + * (1.0 + - (new_offset[1] - prev_offset.get()[1]) + * Camera::DRAG_ZOOM_MAGN_ZOOM_FACTOR); + + if (Camera::ZOOM_MIN..=Camera::ZOOM_MAX).contains(&new_zoom) { + let viewport_center = canvas.engine_ref().camera.viewport_center(); + + let mut widget_flags = canvas.engine_mut().zoom_w_timeout(new_zoom); + widget_flags |= canvas + .engine_mut() + .camera + .set_viewport_center(viewport_center); + widget_flags |= canvas.engine_mut().doc_expand_autoexpand(); + canvas.emit_handle_widget_flags(widget_flags); + } + + prev_offset.set(new_offset); } - - prev_offset.set(new_offset); - }) - ); - - self.canvas_alt_shift_drag_gesture.connect_drag_end( - clone!(@weak obj as canvaswrapper => move |_, _, _| { - let widget_flags = canvaswrapper.canvas().engine_mut().update_rendering_current_viewport(); - canvaswrapper.canvas().emit_handle_widget_flags(widget_flags); - }), - ); + )); + + self.canvas_alt_shift_drag_gesture.connect_drag_end(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_, _, _| { + let widget_flags = canvaswrapper + .canvas() + .engine_mut() + .update_rendering_current_viewport(); + canvaswrapper + .canvas() + .emit_handle_widget_flags(widget_flags); + } + )); } { // Shortcut with touch two-finger long-press. - self.touch_two_finger_long_press_gesture.connect_pressed(clone!(@weak obj as canvaswrapper => move |_gesture, _, _| { - let (_, widget_flags) = canvaswrapper.canvas() - .engine_mut() - .handle_pressed_shortcut_key(ShortcutKey::TouchTwoFingerLongPress, Instant::now()); - canvaswrapper.canvas().emit_handle_widget_flags(widget_flags); - })); + self.touch_two_finger_long_press_gesture + .connect_pressed(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_gesture, _, _| { + let (_, widget_flags) = canvaswrapper + .canvas() + .engine_mut() + .handle_pressed_shortcut_key( + ShortcutKey::TouchTwoFingerLongPress, + Instant::now(), + ); + canvaswrapper + .canvas() + .emit_handle_widget_flags(widget_flags); + } + )); } { // Context menu - self.touch_long_press_gesture.connect_pressed( - clone!(@weak obj as canvaswrapper => move |_gesture, x, y| { + self.touch_long_press_gesture.connect_pressed(clone!( + #[weak(rename_to=canvaswrapper)] + obj, + move |_gesture, x, y| { let popover = canvaswrapper.contextmenu().popover(); - canvaswrapper.imp().last_contextmenu_pos.set(Some(na::vector![x, y])); - popover.set_pointing_to(Some(&gdk::Rectangle::new(x as i32, y as i32, 4, 4))); + canvaswrapper + .imp() + .last_contextmenu_pos + .set(Some(na::vector![x, y])); + popover + .set_pointing_to(Some(&gdk::Rectangle::new(x as i32, y as i32, 4, 4))); popover.popup(); - }), - ); + } + )); } } } diff --git a/crates/rnote-ui/src/colorpicker/mod.rs b/crates/rnote-ui/src/colorpicker/mod.rs index 17283f324d..91bda9085b 100644 --- a/crates/rnote-ui/src/colorpicker/mod.rs +++ b/crates/rnote-ui/src/colorpicker/mod.rs @@ -116,14 +116,16 @@ mod imp { .bidirectional() .build(); - self.stroke_color_pad.connect_active_notify( - clone!(@weak obj as colorpicker => move |_| { + self.stroke_color_pad.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |_| { colorpicker.deselect_setters(); colorpicker .imp() .update_color_label_string(colorpicker.stroke_color().into_compose_color()); - }), - ); + } + )); self.fill_color_pad .bind_property("color", &*obj, "fill-color") @@ -131,14 +133,16 @@ mod imp { .bidirectional() .build(); - self.fill_color_pad.connect_active_notify( - clone!(@weak obj as colorpicker => move |_| { + self.fill_color_pad.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |_| { colorpicker.deselect_setters(); colorpicker .imp() .update_color_label_string(colorpicker.fill_color().into_compose_color()); - }), - ); + } + )); } fn dispose(&self) { @@ -203,8 +207,10 @@ mod imp { self.setter_8.set_color(Self::default_color(7)); self.setter_9.set_color(Self::default_color(8)); - self.setter_1 - .connect_active_notify(clone!(@weak obj as colorpicker => move |setter| { + self.setter_1.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |setter| { if setter.is_active() { colorpicker.setter_2().set_active(false); colorpicker.setter_3().set_active(false); @@ -217,10 +223,13 @@ mod imp { // Must come after setting the other setters inactive colorpicker.set_color_active_pad(setter.color()); } - })); + } + )); - self.setter_2 - .connect_active_notify(clone!(@weak obj as colorpicker => move |setter| { + self.setter_2.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |setter| { if setter.is_active() { colorpicker.setter_1().set_active(false); colorpicker.setter_3().set_active(false); @@ -232,10 +241,13 @@ mod imp { colorpicker.setter_9().set_active(false); colorpicker.set_color_active_pad(setter.color()); } - })); + } + )); - self.setter_3 - .connect_active_notify(clone!(@weak obj as colorpicker => move |setter| { + self.setter_3.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |setter| { if setter.is_active() { colorpicker.setter_1().set_active(false); colorpicker.setter_2().set_active(false); @@ -247,10 +259,13 @@ mod imp { colorpicker.setter_9().set_active(false); colorpicker.set_color_active_pad(setter.color()); } - })); + } + )); - self.setter_4 - .connect_active_notify(clone!(@weak obj as colorpicker => move |setter| { + self.setter_4.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |setter| { if setter.is_active() { colorpicker.setter_1().set_active(false); colorpicker.setter_2().set_active(false); @@ -262,10 +277,13 @@ mod imp { colorpicker.setter_9().set_active(false); colorpicker.set_color_active_pad(setter.color()); } - })); + } + )); - self.setter_5 - .connect_active_notify(clone!(@weak obj as colorpicker => move |setter| { + self.setter_5.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |setter| { if setter.is_active() { colorpicker.setter_1().set_active(false); colorpicker.setter_2().set_active(false); @@ -277,10 +295,13 @@ mod imp { colorpicker.setter_9().set_active(false); colorpicker.set_color_active_pad(setter.color()); } - })); + } + )); - self.setter_6 - .connect_active_notify(clone!(@weak obj as colorpicker => move |setter| { + self.setter_6.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |setter| { if setter.is_active() { colorpicker.setter_1().set_active(false); colorpicker.setter_2().set_active(false); @@ -292,10 +313,13 @@ mod imp { colorpicker.setter_9().set_active(false); colorpicker.set_color_active_pad(setter.color()); } - })); + } + )); - self.setter_7 - .connect_active_notify(clone!(@weak obj as colorpicker => move |setter| { + self.setter_7.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |setter| { if setter.is_active() { colorpicker.setter_1().set_active(false); colorpicker.setter_2().set_active(false); @@ -306,10 +330,13 @@ mod imp { colorpicker.setter_8().set_active(false); colorpicker.set_color_active_pad(setter.color()); } - })); + } + )); - self.setter_8 - .connect_active_notify(clone!(@weak obj as colorpicker => move |setter| { + self.setter_8.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |setter| { if setter.is_active() { colorpicker.setter_1().set_active(false); colorpicker.setter_2().set_active(false); @@ -321,10 +348,13 @@ mod imp { colorpicker.setter_9().set_active(false); colorpicker.set_color_active_pad(setter.color()); } - })); + } + )); - self.setter_9 - .connect_active_notify(clone!(@weak obj as colorpicker => move |setter| { + self.setter_9.connect_active_notify(clone!( + #[weak(rename_to=colorpicker)] + obj, + move |setter| { if setter.is_active() { colorpicker.setter_1().set_active(false); colorpicker.setter_2().set_active(false); @@ -336,7 +366,8 @@ mod imp { colorpicker.setter_8().set_active(false); colorpicker.set_color_active_pad(setter.color()); } - })); + } + )); obj.connect_notify_local(Some("stroke-color"), move |colorpicker, _| { if colorpicker.stroke_color_pad_active() { @@ -461,11 +492,11 @@ impl RnColorPicker { pub(crate) fn init(&self, appwindow: &RnAppWindow) { self.imp().colordialog_button.connect_clicked( - clone!(@weak self as colorpicker, @weak appwindow => move |_| { + clone!(#[weak(rename_to=colorpicker)] self, #[weak] appwindow , move |_| { if colorpicker.imp().color_dialog.upgrade().is_some() { // Unfortunately Gtk currently does not have API to make the dialog the active window. } else { - glib::spawn_future_local(clone!(@weak colorpicker, @weak appwindow => async move { + glib::spawn_future_local(clone!(#[weak] colorpicker, #[weak] appwindow , async move { let dialog = ColorDialog::builder().modal(false).with_alpha(true).build(); colorpicker.imp().color_dialog.set(Some(&dialog)); diff --git a/crates/rnote-ui/src/dialogs/export.rs b/crates/rnote-ui/src/dialogs/export.rs index a8aa8fc386..592de47347 100644 --- a/crates/rnote-ui/src/dialogs/export.rs +++ b/crates/rnote-ui/src/dialogs/export.rs @@ -137,8 +137,8 @@ pub(crate) async fn dialog_export_doc_w_prefs(appwindow: &RnAppWindow, canvas: & // Update prefs export_file_button.connect_clicked( - clone!(@strong selected_file, @weak export_file_label, @weak button_confirm, @weak dialog, @weak canvas, @weak appwindow => move |_| { - glib::spawn_future_local(clone!(@strong selected_file, @weak export_file_label, @weak button_confirm, @weak dialog, @weak canvas, @weak appwindow => async move { + clone!(#[strong] selected_file, #[weak] export_file_label, #[weak] button_confirm, #[weak] dialog, #[weak] canvas, #[weak] appwindow , move |_| { + glib::spawn_future_local(clone!(#[strong] selected_file, #[weak] export_file_label, #[weak] button_confirm, #[weak] dialog, #[weak] canvas, #[weak] appwindow, async move { dialog.set_sensitive(false); let doc_export_prefs = canvas.engine_mut().export_prefs.doc_export_prefs; @@ -174,63 +174,105 @@ pub(crate) async fn dialog_export_doc_w_prefs(appwindow: &RnAppWindow, canvas: & .sync_create() .build(); - with_background_row.connect_active_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |with_background_row| { + with_background_row.connect_active_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |with_background_row| { let active = with_background_row.is_active(); - canvas.engine_mut().export_prefs.doc_export_prefs.with_background = active; + canvas + .engine_mut() + .export_prefs + .doc_export_prefs + .with_background = active; preview.set_draw_background(active); - }), - ); - - with_pattern_row.connect_active_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |with_pattern_row| { + } + )); + + with_pattern_row.connect_active_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |with_pattern_row| { let active = with_pattern_row.is_active(); - canvas.engine_mut().export_prefs.doc_export_prefs.with_pattern = active; + canvas + .engine_mut() + .export_prefs + .doc_export_prefs + .with_pattern = active; preview.set_draw_pattern(active); - }), - ); - - optimize_printing_row.connect_active_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |optimize_printing_row| { + } + )); + + optimize_printing_row.connect_active_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |optimize_printing_row| { let active = optimize_printing_row.is_active(); - canvas.engine_mut().export_prefs.doc_export_prefs.optimize_printing = active; + canvas + .engine_mut() + .export_prefs + .doc_export_prefs + .optimize_printing = active; preview.set_optimize_printing(active); - }), - ); - - export_format_row.connect_selected_notify(clone!(@strong selected_file, @weak export_file_label, @weak page_order_row, @weak button_confirm, @weak canvas, @weak appwindow => move |row| { - let export_format = DocExportFormat::try_from(row.selected()).unwrap(); - canvas.engine_mut().export_prefs.doc_export_prefs.export_format = export_format; + } + )); - // force the user to pick another file - export_file_label.set_label(&gettext("- no file selected -")); - button_confirm.set_sensitive(false); - selected_file.replace(None); - })); + export_format_row.connect_selected_notify(clone!( + #[strong] + selected_file, + #[weak] + export_file_label, + #[weak] + button_confirm, + #[weak] + canvas, + move |row| { + let export_format = DocExportFormat::try_from(row.selected()).unwrap(); + canvas + .engine_mut() + .export_prefs + .doc_export_prefs + .export_format = export_format; - page_order_row.connect_selected_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |row| { + // force the user to pick another file + export_file_label.set_label(&gettext("- no file selected -")); + button_confirm.set_sensitive(false); + selected_file.replace(None); + } + )); + + page_order_row.connect_selected_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |row| { let page_order = SplitOrder::try_from(row.selected()).unwrap(); canvas.engine_mut().export_prefs.doc_export_prefs.page_order = page_order; - preview.set_contents( - canvas - .engine_ref() - .extract_pages_content(page_order), - ); - }), - ); + preview.set_contents(canvas.engine_ref().extract_pages_content(page_order)); + } + )); // Listen to responses - export_doc_button_cancel.connect_clicked(clone!(@weak dialog => move |_| { - dialog.close(); - })); + export_doc_button_cancel.connect_clicked(clone!( + #[weak] + dialog, + move |_| { + dialog.close(); + } + )); - export_doc_button_confirm.connect_clicked(clone!(@weak dialog, @weak canvas, @weak appwindow => move |_| { + export_doc_button_confirm.connect_clicked(clone!(#[weak] dialog, #[weak] canvas, #[weak] appwindow , move |_| { dialog.close(); if let Some(file) = selected_file.take() { - glib::spawn_future_local(clone!(@weak canvas, @weak appwindow => async move { + glib::spawn_future_local(clone!(#[weak] canvas, #[weak] appwindow , async move { appwindow.overlays().progressbar_start_pulsing(); let file_title = crate::utils::default_file_title_for_export( @@ -247,7 +289,7 @@ pub(crate) async fn dialog_export_doc_w_prefs(appwindow: &RnAppWindow, canvas: & appwindow.overlays().dispatch_toast_w_button( &gettext("Exported document successfully"), &gettext("View in file manager"), - clone!(@weak canvas, @weak appwindow => move |_reload_toast| { + clone!(#[weak] appwindow , move |_reload_toast| { let Some(folder_path_string) = file .parent() .and_then(|p| @@ -435,8 +477,8 @@ pub(crate) async fn dialog_export_doc_pages_w_prefs(appwindow: &RnAppWindow, can // Update prefs export_dir_button.connect_clicked( - clone!(@strong selected_file, @weak export_dir_label, @weak button_confirm, @weak dialog, @weak canvas, @weak appwindow => move |_| { - glib::spawn_future_local(clone!(@strong selected_file, @weak export_dir_label, @weak button_confirm, @weak dialog, @weak canvas, @weak appwindow => async move { + clone!(#[strong] selected_file, #[weak] export_dir_label, #[weak] button_confirm, #[weak] dialog, #[weak] canvas, #[weak] appwindow, move |_| { + glib::spawn_future_local(clone!(#[strong] selected_file, #[weak] export_dir_label, #[weak] button_confirm, #[weak] dialog, #[weak] canvas, #[weak] appwindow ,async move { dialog.set_sensitive(false); let doc_pages_export_prefs = canvas.engine_mut().export_prefs.doc_pages_export_prefs; @@ -476,99 +518,175 @@ pub(crate) async fn dialog_export_doc_pages_w_prefs(appwindow: &RnAppWindow, can .sync_create() .build(); - with_background_row.connect_active_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |with_background_row| { + with_background_row.connect_active_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |with_background_row| { let active = with_background_row.is_active(); - canvas.engine_mut().export_prefs.doc_pages_export_prefs.with_background = active; + canvas + .engine_mut() + .export_prefs + .doc_pages_export_prefs + .with_background = active; preview.set_draw_background(active); - }), - ); - - with_pattern_row.connect_active_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |row| { + } + )); + + with_pattern_row.connect_active_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |row| { let active = row.is_active(); - canvas.engine_mut().export_prefs.doc_pages_export_prefs.with_pattern = active; + canvas + .engine_mut() + .export_prefs + .doc_pages_export_prefs + .with_pattern = active; preview.set_draw_pattern(active); - }), - ); - - optimize_printing_row.connect_active_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |optimize_printing_row| { + } + )); + + optimize_printing_row.connect_active_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |optimize_printing_row| { let active = optimize_printing_row.is_active(); - canvas.engine_mut().export_prefs.doc_pages_export_prefs.optimize_printing = active; + canvas + .engine_mut() + .export_prefs + .doc_pages_export_prefs + .optimize_printing = active; preview.set_optimize_printing(active); - }), - ); + } + )); export_format_row.connect_selected_notify(clone!( - @strong selected_file, - @weak page_files_naming_info_label, - @weak export_files_stemname_entryrow, - @weak bitmap_scalefactor_row, - @weak jpeg_quality_row, - @weak export_dir_label, - @weak button_confirm, - @weak canvas, - @weak appwindow => move |row| { + #[weak] + page_files_naming_info_label, + #[weak] + export_files_stemname_entryrow, + #[weak] + bitmap_scalefactor_row, + #[weak] + jpeg_quality_row, + #[weak] + canvas, + move |row| { let export_format = DocPagesExportFormat::try_from(row.selected()).unwrap(); - canvas.engine_mut().export_prefs.doc_pages_export_prefs.export_format = export_format; + canvas + .engine_mut() + .export_prefs + .doc_pages_export_prefs + .export_format = export_format; // Set the bitmap scalefactor sensitive only when exporting to a bitmap image - bitmap_scalefactor_row.set_sensitive(export_format == DocPagesExportFormat::Png || export_format == DocPagesExportFormat::Jpeg); + bitmap_scalefactor_row.set_sensitive( + export_format == DocPagesExportFormat::Png + || export_format == DocPagesExportFormat::Jpeg, + ); // Set the jpeg quality pref only sensitive when jpeg is actually selected jpeg_quality_row.set_sensitive(export_format == DocPagesExportFormat::Jpeg); // update file naming preview - page_files_naming_info_label.set_text(&( - rnote_engine::utils::doc_pages_files_names(export_files_stemname_entryrow.text().to_string(), 1) - + "." - + &canvas.engine_mut().export_prefs.doc_pages_export_prefs.export_format.file_ext() - )); - })); - - page_order_row.connect_selected_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |row| { - let page_order = SplitOrder::try_from(row.selected()).unwrap(); - canvas.engine_mut().export_prefs.doc_pages_export_prefs.page_order = page_order; - preview.set_contents( - canvas - .engine_ref() - .extract_pages_content(page_order), + page_files_naming_info_label.set_text( + &(rnote_engine::utils::doc_pages_files_names( + export_files_stemname_entryrow.text().to_string(), + 1, + ) + "." + + &canvas + .engine_mut() + .export_prefs + .doc_pages_export_prefs + .export_format + .file_ext()), ); - }), - ); - - bitmap_scalefactor_row.connect_changed(clone!(@weak canvas, @weak appwindow => move |bitmap_scalefactor_row| { - canvas.engine_mut().export_prefs.doc_pages_export_prefs.bitmap_scalefactor = bitmap_scalefactor_row.value(); - })); - - jpeg_quality_row.connect_changed(clone!(@weak canvas, @weak appwindow => move |jpeg_quality_row| { - canvas.engine_mut().export_prefs.doc_pages_export_prefs.jpeg_quality = jpeg_quality_row.value().clamp(1.0, 100.0) as u8; - })); - - export_files_stemname_entryrow.connect_changed( - clone!(@weak page_files_naming_info_label, @weak button_confirm, @weak dialog, @weak canvas, @weak appwindow => move |entryrow| { + } + )); + + page_order_row.connect_selected_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |row| { + let page_order = SplitOrder::try_from(row.selected()).unwrap(); + canvas + .engine_mut() + .export_prefs + .doc_pages_export_prefs + .page_order = page_order; + preview.set_contents(canvas.engine_ref().extract_pages_content(page_order)); + } + )); + + bitmap_scalefactor_row.connect_changed(clone!( + #[weak] + canvas, + move |bitmap_scalefactor_row| { + canvas + .engine_mut() + .export_prefs + .doc_pages_export_prefs + .bitmap_scalefactor = bitmap_scalefactor_row.value(); + } + )); + + jpeg_quality_row.connect_changed(clone!( + #[weak] + canvas, + move |jpeg_quality_row| { + canvas + .engine_mut() + .export_prefs + .doc_pages_export_prefs + .jpeg_quality = jpeg_quality_row.value().clamp(1.0, 100.0) as u8; + } + )); + + export_files_stemname_entryrow.connect_changed(clone!( + #[weak] + page_files_naming_info_label, + #[weak] + button_confirm, + #[weak] + canvas, + move |entryrow| { button_confirm.set_sensitive(!entryrow.text().is_empty()); // update file naming preview - page_files_naming_info_label.set_text(&( - rnote_engine::utils::doc_pages_files_names(entryrow.text().to_string(), 1) + page_files_naming_info_label.set_text( + &(rnote_engine::utils::doc_pages_files_names(entryrow.text().to_string(), 1) + "." - + &canvas.engine_mut().export_prefs.doc_pages_export_prefs.export_format.file_ext() - )); - }), - ); + + &canvas + .engine_mut() + .export_prefs + .doc_pages_export_prefs + .export_format + .file_ext()), + ); + } + )); // Listen to responses - export_doc_pages_button_cancel.connect_clicked(clone!(@weak dialog => move |_| { - dialog.close(); - })); + export_doc_pages_button_cancel.connect_clicked(clone!( + #[weak] + dialog, + move |_| { + dialog.close(); + } + )); - export_doc_pages_button_confirm.connect_clicked(clone!(@weak export_files_stemname_entryrow, @weak dialog, @weak canvas, @weak appwindow => move |_| { + export_doc_pages_button_confirm.connect_clicked(clone!(#[weak] export_files_stemname_entryrow, #[weak] dialog, #[weak] canvas, #[weak] appwindow, move |_| { dialog.close(); if let Some(dir) = selected_file.take() { - glib::spawn_future_local(clone!(@weak export_files_stemname_entryrow, @weak canvas, @weak appwindow => async move { + glib::spawn_future_local(clone!(#[weak] export_files_stemname_entryrow, #[weak] canvas, #[weak] appwindow, async move { appwindow.overlays().progressbar_start_pulsing(); let file_stem_name = export_files_stemname_entryrow.text().to_string(); @@ -581,7 +699,7 @@ pub(crate) async fn dialog_export_doc_pages_w_prefs(appwindow: &RnAppWindow, can appwindow.overlays().dispatch_toast_w_button( &gettext("Exported document pages successfully"), &gettext("View in file manager"), - clone!(@weak canvas, @weak appwindow => move |_reload_toast| { + clone!(#[weak] appwindow, move |_reload_toast| { let Some(folder_path_string) = dir.path().and_then(|p| p.into_os_string().into_string().ok()) else { error!("Failed to get the path of the parent folder"); appwindow.overlays().dispatch_toast_error(&gettext("Exporting document failed")); @@ -740,8 +858,8 @@ pub(crate) async fn dialog_export_selection_w_prefs(appwindow: &RnAppWindow, can // Update prefs export_file_button.connect_clicked( - clone!(@strong selected_file, @weak export_file_label, @weak button_confirm, @weak dialog, @weak canvas, @weak appwindow => move |_| { - glib::spawn_future_local(clone!(@strong selected_file, @weak export_file_label, @weak button_confirm, @weak dialog, @weak canvas, @weak appwindow => async move { + clone!(#[strong] selected_file, #[weak] export_file_label, #[weak] button_confirm, #[weak] dialog, #[weak] canvas, #[weak] appwindow , move |_| { + glib::spawn_future_local(clone!(#[strong] selected_file, #[weak] export_file_label, #[weak] button_confirm, #[weak] dialog, #[weak] canvas, #[weak] appwindow , async move { dialog.set_sensitive(false); let selection_export_prefs = canvas @@ -783,39 +901,72 @@ pub(crate) async fn dialog_export_selection_w_prefs(appwindow: &RnAppWindow, can .sync_create() .build(); - with_background_row.connect_active_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |row| { + with_background_row.connect_active_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |row| { let active = row.is_active(); - canvas.engine_mut().export_prefs.selection_export_prefs.with_background = active; + canvas + .engine_mut() + .export_prefs + .selection_export_prefs + .with_background = active; preview.set_draw_background(active); - }), - ); - - with_pattern_row.connect_active_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |row| { + } + )); + + with_pattern_row.connect_active_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |row| { let active = row.is_active(); - canvas.engine_mut().export_prefs.selection_export_prefs.with_pattern = active; + canvas + .engine_mut() + .export_prefs + .selection_export_prefs + .with_pattern = active; preview.set_draw_pattern(active); - }), - ); - - optimize_printing_row.connect_active_notify( - clone!(@weak preview, @weak canvas, @weak appwindow => move |optimize_printing_row| { + } + )); + + optimize_printing_row.connect_active_notify(clone!( + #[weak] + preview, + #[weak] + canvas, + move |optimize_printing_row| { let active = optimize_printing_row.is_active(); - canvas.engine_mut().export_prefs.selection_export_prefs.optimize_printing = active; + canvas + .engine_mut() + .export_prefs + .selection_export_prefs + .optimize_printing = active; preview.set_optimize_printing(active); - }), - ); + } + )); export_format_row.connect_selected_notify(clone!( - @strong selected_file, - @weak bitmap_scalefactor_row, - @weak jpeg_quality_row, - @weak export_file_label, - @weak canvas, - @weak appwindow => move |row| { + #[strong] + selected_file, + #[weak] + bitmap_scalefactor_row, + #[weak] + jpeg_quality_row, + #[weak] + export_file_label, + #[weak] + canvas, + move |row| { let export_format = SelectionExportFormat::try_from(row.selected()).unwrap(); - canvas.engine_mut().export_prefs.selection_export_prefs.export_format = export_format; + canvas + .engine_mut() + .export_prefs + .selection_export_prefs + .export_format = export_format; // force the user to pick another file export_file_label.set_label(&gettext("- no file selected -")); @@ -823,37 +974,69 @@ pub(crate) async fn dialog_export_selection_w_prefs(appwindow: &RnAppWindow, can selected_file.replace(None); // Set the bitmap scalefactor sensitive only when exporting to a bitmap image - bitmap_scalefactor_row.set_sensitive(export_format == SelectionExportFormat::Png || export_format == SelectionExportFormat::Jpeg); + bitmap_scalefactor_row.set_sensitive( + export_format == SelectionExportFormat::Png + || export_format == SelectionExportFormat::Jpeg, + ); // Set the jpeg quality pref only sensitive when jpeg is actually selected jpeg_quality_row.set_sensitive(export_format == SelectionExportFormat::Jpeg); - })); - - bitmap_scalefactor_row.connect_changed(clone!(@weak canvas, @weak appwindow => move |bitmap_scalefactor_row| { - canvas.engine_mut().export_prefs.selection_export_prefs.bitmap_scalefactor = bitmap_scalefactor_row.value(); - })); - - jpeg_quality_row.connect_changed(clone!(@weak canvas, @weak appwindow => move |jpeg_quality_row| { - canvas.engine_mut().export_prefs.selection_export_prefs.jpeg_quality = jpeg_quality_row.value().clamp(1.0, 100.0) as u8; - })); - - margin_row.connect_changed( - clone!(@weak preview, @weak canvas, @weak appwindow => move |margin_row| { + } + )); + + bitmap_scalefactor_row.connect_changed(clone!( + #[weak] + canvas, + move |bitmap_scalefactor_row| { + canvas + .engine_mut() + .export_prefs + .selection_export_prefs + .bitmap_scalefactor = bitmap_scalefactor_row.value(); + } + )); + + jpeg_quality_row.connect_changed(clone!( + #[weak] + canvas, + move |jpeg_quality_row| { + canvas + .engine_mut() + .export_prefs + .selection_export_prefs + .jpeg_quality = jpeg_quality_row.value().clamp(1.0, 100.0) as u8; + } + )); + + margin_row.connect_changed(clone!( + #[weak] + preview, + #[weak] + canvas, + move |margin_row| { let value = margin_row.value(); - canvas.engine_mut().export_prefs.selection_export_prefs.margin = value; + canvas + .engine_mut() + .export_prefs + .selection_export_prefs + .margin = value; preview.set_margin(value); - }), - ); + } + )); // Listen to responses - export_selection_button_cancel.connect_clicked(clone!(@weak dialog => move |_| { - dialog.close(); - })); + export_selection_button_cancel.connect_clicked(clone!( + #[weak] + dialog, + move |_| { + dialog.close(); + } + )); - export_selection_button_confirm.connect_clicked(clone!(@weak selected_file, @weak dialog, @weak canvas, @weak appwindow => move |_| { + export_selection_button_confirm.connect_clicked(clone!(#[weak] selected_file, #[weak] dialog, #[weak] canvas, #[weak] appwindow , move |_| { dialog.close(); - glib::spawn_future_local(clone!(@weak selected_file, @weak canvas, @weak appwindow => async move { + glib::spawn_future_local(clone!(#[weak] selected_file, #[weak] canvas, #[weak] appwindow , async move { let Some(file) = selected_file.take() else { appwindow .overlays() @@ -873,7 +1056,7 @@ pub(crate) async fn dialog_export_selection_w_prefs(appwindow: &RnAppWindow, can appwindow.overlays().dispatch_toast_w_button( &gettext("Exported selection successfully"), &gettext("View in file manager"), - clone!(@weak canvas, @weak appwindow => move |_reload_toast| { + clone!(#[weak] appwindow , move |_reload_toast| { let Some(folder_path_string) = file .parent() .and_then(|p| diff --git a/crates/rnote-ui/src/dialogs/import.rs b/crates/rnote-ui/src/dialogs/import.rs index e4fd8be5e5..6f003ff6b2 100644 --- a/crates/rnote-ui/src/dialogs/import.rs +++ b/crates/rnote-ui/src/dialogs/import.rs @@ -183,53 +183,95 @@ pub(crate) async fn dialog_import_pdf_w_prefs( .build(); // Update preferences - pdf_import_as_vector_toggle.connect_toggled( - clone!(@weak pdf_import_bitmap_scalefactor_row, @weak canvas, @weak appwindow => move |toggle| { + pdf_import_as_vector_toggle.connect_toggled(clone!( + #[weak] + pdf_import_bitmap_scalefactor_row, + #[weak] + canvas, + move |toggle| { if toggle.is_active() { - canvas.engine_mut().import_prefs.pdf_import_prefs.pages_type = PdfImportPagesType::Vector; + canvas.engine_mut().import_prefs.pdf_import_prefs.pages_type = + PdfImportPagesType::Vector; pdf_import_bitmap_scalefactor_row.set_sensitive(false); } - }), - ); + } + )); - pdf_import_as_bitmap_toggle.connect_toggled( - clone!(@weak pdf_import_bitmap_scalefactor_row, @weak canvas, @weak appwindow => move |toggle| { + pdf_import_as_bitmap_toggle.connect_toggled(clone!( + #[weak] + pdf_import_bitmap_scalefactor_row, + #[weak] + canvas, + move |toggle| { if toggle.is_active() { - canvas.engine_mut().import_prefs.pdf_import_prefs.pages_type = PdfImportPagesType::Bitmap; + canvas.engine_mut().import_prefs.pdf_import_prefs.pages_type = + PdfImportPagesType::Bitmap; pdf_import_bitmap_scalefactor_row.set_sensitive(true); } - }), - ); + } + )); - pdf_import_bitmap_scalefactor_row.connect_changed( - clone!(@weak canvas, @weak appwindow => move |row| { - canvas.engine_mut().import_prefs.pdf_import_prefs.bitmap_scalefactor = row.value(); - }), - ); + pdf_import_bitmap_scalefactor_row.connect_changed(clone!( + #[weak] + canvas, + move |row| { + canvas + .engine_mut() + .import_prefs + .pdf_import_prefs + .bitmap_scalefactor = row.value(); + } + )); - pdf_import_page_spacing_row.connect_selected_notify( - clone!(@weak canvas, @weak appwindow => move |row| { + pdf_import_page_spacing_row.connect_selected_notify(clone!( + #[weak] + canvas, + move |row| { let page_spacing = PdfImportPageSpacing::try_from(row.selected()).unwrap(); - canvas.engine_mut().import_prefs.pdf_import_prefs.page_spacing = page_spacing; - }), - ); + canvas + .engine_mut() + .import_prefs + .pdf_import_prefs + .page_spacing = page_spacing; + } + )); - pdf_import_width_row.connect_changed(clone!(@weak canvas, @weak appwindow => move |row| { - canvas.engine_mut().import_prefs.pdf_import_prefs.page_width_perc = row.value(); - })); + pdf_import_width_row.connect_changed(clone!( + #[weak] + canvas, + move |row| { + canvas + .engine_mut() + .import_prefs + .pdf_import_prefs + .page_width_perc = row.value(); + } + )); - pdf_import_page_borders_row.connect_active_notify( - clone!(@weak canvas, @weak appwindow => move |row| { - canvas.engine_mut().import_prefs.pdf_import_prefs.page_borders = row.is_active(); - }), - ); + pdf_import_page_borders_row.connect_active_notify(clone!( + #[weak] + canvas, + move |row| { + canvas + .engine_mut() + .import_prefs + .pdf_import_prefs + .page_borders = row.is_active(); + } + )); - pdf_import_adjust_document_row.connect_active_notify( - clone!(@weak canvas, @weak appwindow => move |row| { - canvas.engine_mut().import_prefs.pdf_import_prefs.adjust_document = row.is_active(); - }), - ); + pdf_import_adjust_document_row.connect_active_notify(clone!( + #[weak] + canvas, + move |row| { + canvas + .engine_mut() + .import_prefs + .pdf_import_prefs + .adjust_document = row.is_active(); + } + )); if let Ok(poppler_doc) = poppler::Document::from_gfile(&input_file, None, None::<&gio::Cancellable>) @@ -290,22 +332,26 @@ pub(crate) async fn dialog_import_pdf_w_prefs( let tx_cancel = tx.clone(); let tx_confirm = tx.clone(); - import_pdf_button_cancel.connect_clicked(clone!(@weak dialog => move |_| { - dialog.close(); + import_pdf_button_cancel.connect_clicked(clone!( + #[weak] + dialog, + move |_| { + dialog.close(); - if let Err(e) = tx_cancel.unbounded_send(Ok(false)) { - error!( + if let Err(e) = tx_cancel.unbounded_send(Ok(false)) { + error!( "PDF import dialog closed, but failed to send signal through channel. Err: {e:?}" ); + } } - })); + )); - import_pdf_button_confirm.connect_clicked(clone!(@weak pdf_page_start_row, @weak pdf_page_end_row, @weak input_file, @weak dialog, @weak canvas => move |_| { + import_pdf_button_confirm.connect_clicked(clone!(#[weak] pdf_page_start_row, #[weak] pdf_page_end_row, #[weak] input_file, #[weak] dialog, #[weak] canvas , move |_| { dialog.close(); let inner_tx_confirm = tx_confirm.clone(); - glib::spawn_future_local(clone!(@weak pdf_page_start_row, @weak pdf_page_end_row, @weak input_file, @weak canvas => async move { + glib::spawn_future_local(clone!(#[weak] pdf_page_start_row, #[weak] pdf_page_end_row, #[weak] input_file, #[weak] canvas , async move { let page_range = (pdf_page_start_row.value() as u32 - 1)..pdf_page_end_row.value() as u32; @@ -334,12 +380,18 @@ pub(crate) async fn dialog_import_pdf_w_prefs( // Overwrite builtin close shortcut let controller = ShortcutController::new(); controller.add_shortcut(Shortcut::new( - Some(ShortcutTrigger:: parse_string("Escape").unwrap()), - Some(CallbackAction::new(clone!(@weak import_pdf_button_cancel => @default-return glib::Propagation::Stop, move |_, _| { - import_pdf_button_cancel.emit_clicked(); - - glib::Propagation::Stop - }))), + Some(ShortcutTrigger::parse_string("Escape").unwrap()), + Some(CallbackAction::new(clone!( + #[weak] + import_pdf_button_cancel, + #[upgrade_or] + glib::Propagation::Stop, + move |_, _| { + import_pdf_button_cancel.emit_clicked(); + + glib::Propagation::Stop + } + ))), )); dialog.add_controller(controller); @@ -375,9 +427,13 @@ pub(crate) async fn dialog_import_xopp_w_prefs( dpi_row.set_value(xopp_import_prefs.dpi); // Update preferences - dpi_row.connect_changed(clone!(@weak canvas, @weak appwindow => move |row| { - canvas.engine_mut().import_prefs.xopp_import_prefs.dpi = row.value(); - })); + dpi_row.connect_changed(clone!( + #[weak] + canvas, + move |row| { + canvas.engine_mut().import_prefs.xopp_import_prefs.dpi = row.value(); + } + )); // Listen to responses @@ -385,22 +441,26 @@ pub(crate) async fn dialog_import_xopp_w_prefs( let tx_cancel = tx.clone(); let tx_confirm = tx.clone(); - import_xopp_button_cancel.connect_clicked(clone!(@weak dialog => move |_| { - dialog.close(); + import_xopp_button_cancel.connect_clicked(clone!( + #[weak] + dialog, + move |_| { + dialog.close(); - if let Err(e) = tx_cancel.unbounded_send(Ok(false)) { - error!( + if let Err(e) = tx_cancel.unbounded_send(Ok(false)) { + error!( "XOPP import dialog closed, but failed to send signal through channel. Err: {e:?}" ); + } } - })); + )); - import_xopp_button_confirm.connect_clicked(clone!(@weak input_file, @weak dialog, @weak canvas => move |_| { + import_xopp_button_confirm.connect_clicked(clone!(#[weak] input_file, #[weak] dialog, #[weak] canvas , move |_| { dialog.close(); let inner_tx_confirm = tx_confirm.clone(); - glib::spawn_future_local(clone!(@weak input_file, @weak canvas => async move { + glib::spawn_future_local(clone!(#[weak] input_file, #[weak] canvas , async move { let (bytes, _) = match input_file.load_bytes_future().await { Ok(res) => {res} Err(err) => { @@ -427,11 +487,17 @@ pub(crate) async fn dialog_import_xopp_w_prefs( let controller = ShortcutController::new(); controller.add_shortcut(Shortcut::new( Some(ShortcutTrigger::parse_string("Escape").unwrap()), - Some(CallbackAction::new(clone!(@weak import_xopp_button_cancel => @default-return glib::Propagation::Stop, move |_, _| { - import_xopp_button_cancel.emit_clicked(); - - glib::Propagation::Stop - }))), + Some(CallbackAction::new(clone!( + #[weak] + import_xopp_button_cancel, + #[upgrade_or] + glib::Propagation::Stop, + move |_, _| { + import_xopp_button_cancel.emit_clicked(); + + glib::Propagation::Stop + } + ))), )); dialog.add_controller(controller); diff --git a/crates/rnote-ui/src/dialogs/mod.rs b/crates/rnote-ui/src/dialogs/mod.rs index cf4cdd40af..86bcd3f84d 100644 --- a/crates/rnote-ui/src/dialogs/mod.rs +++ b/crates/rnote-ui/src/dialogs/mod.rs @@ -105,29 +105,39 @@ pub(crate) async fn dialog_new_doc(appwindow: &RnAppWindow, canvas: &RnCanvas) { new_doc(appwindow, canvas); } "save" => { - glib::spawn_future_local(clone!(@weak canvas, @weak appwindow => async move { - if let Some(output_file) = canvas.output_file() { - appwindow.overlays().progressbar_start_pulsing(); - - if let Err(e) = canvas.save_document_to_file(&output_file).await { - error!("Saving document failed before creating new document, Err: {e:?}"); - canvas.set_output_file(None); - appwindow.overlays().dispatch_toast_error(&gettext("Saving document failed")); - appwindow.overlays().progressbar_abort(); - } else { - appwindow.overlays().progressbar_finish(); - } - // No success toast on saving without dialog, success is already indicated in the header title + glib::spawn_future_local(clone!( + #[weak] + canvas, + #[weak] + appwindow, + async move { + if let Some(output_file) = canvas.output_file() { + appwindow.overlays().progressbar_start_pulsing(); + + if let Err(e) = canvas.save_document_to_file(&output_file).await { + error!( + "Saving document failed before creating new document, Err: {e:?}" + ); + canvas.set_output_file(None); + appwindow + .overlays() + .dispatch_toast_error(&gettext("Saving document failed")); + appwindow.overlays().progressbar_abort(); + } else { + appwindow.overlays().progressbar_finish(); + } + // No success toast on saving without dialog, success is already indicated in the header title - // only create new document if saving was successful - if !canvas.unsaved_changes() { - new_doc(&appwindow, &canvas); + // only create new document if saving was successful + if !canvas.unsaved_changes() { + new_doc(&appwindow, &canvas); + } + } else { + // Open a dialog to choose a save location + export::dialog_save_doc_as(&appwindow, &canvas).await; } - } else { - // Open a dialog to choose a save location - export::dialog_save_doc_as(&appwindow, &canvas).await; } - })); + )); } _ => { // Cancel @@ -466,29 +476,43 @@ pub(crate) async fn dialog_edit_selected_workspace(appwindow: &RnAppWindow) { color_button.set_rgba(&initial_entry.color()); dir_label.set_label(initial_entry.dir().as_str()); - name_entryrow.connect_changed(clone!(@weak preview_row => move |entry| { - let text = entry.text().to_string(); - preview_row.entry().set_name(text); - })); + name_entryrow.connect_changed(clone!( + #[weak] + preview_row, + move |entry| { + let text = entry.text().to_string(); + preview_row.entry().set_name(text); + } + )); icon_picker.connect_notify_local( Some("picked"), - clone!(@weak icon_menubutton, @weak preview_row, @weak appwindow => move |iconpicker, _| { - if let Some(picked) = iconpicker.picked() { - icon_menubutton.set_icon_name(&picked); - preview_row.entry().set_icon(picked); + clone!( + #[weak] + icon_menubutton, + #[weak] + preview_row, + move |iconpicker, _| { + if let Some(picked) = iconpicker.picked() { + icon_menubutton.set_icon_name(&picked); + preview_row.entry().set_icon(picked); + } } - }), + ), ); - color_button.connect_rgba_notify(clone!(@weak preview_row => move |button| { - let color = button.rgba(); - preview_row.entry().set_color(color); - })); + color_button.connect_rgba_notify(clone!( + #[weak] + preview_row, + move |button| { + let color = button.rgba(); + preview_row.entry().set_color(color); + } + )); dir_button.connect_clicked( - clone!(@weak preview_row, @weak dir_label, @weak name_entryrow, @weak dialog, @weak appwindow => move |_| { - glib::spawn_future_local(clone!(@weak preview_row, @weak dir_label, @weak name_entryrow, @weak dialog, @weak appwindow => async move { + clone!(#[weak] preview_row, #[weak] dir_label, #[weak] name_entryrow, #[weak] dialog, #[weak] appwindow , move |_| { + glib::spawn_future_local(clone!(#[weak] preview_row, #[weak] dir_label, #[weak] name_entryrow, #[weak] dialog, #[weak] appwindow , async move { dialog.set_sensitive(false); let filedialog = FileDialog::builder() @@ -527,12 +551,22 @@ pub(crate) async fn dialog_edit_selected_workspace(appwindow: &RnAppWindow) { // Listen to responses - edit_selected_workspace_button_cancel.connect_clicked(clone!(@weak dialog => move |_| { - dialog.close(); - })); - - edit_selected_workspace_button_apply.connect_clicked( - clone!(@weak preview_row, @weak dialog, @weak appwindow => move |_| { + edit_selected_workspace_button_cancel.connect_clicked(clone!( + #[weak] + dialog, + move |_| { + dialog.close(); + } + )); + + edit_selected_workspace_button_apply.connect_clicked(clone!( + #[weak] + preview_row, + #[weak] + dialog, + #[weak] + appwindow, + move |_| { dialog.close(); // update the actual selected entry @@ -546,8 +580,8 @@ pub(crate) async fn dialog_edit_selected_workspace(appwindow: &RnAppWindow) { .sidebar() .workspacebrowser() .refresh_dir_list_selected_workspace(); - }), - ); + } + )); dialog.present(appwindow.root().as_ref()); } diff --git a/crates/rnote-ui/src/groupediconpicker/group.rs b/crates/rnote-ui/src/groupediconpicker/group.rs index f8895874fc..70250ff449 100644 --- a/crates/rnote-ui/src/groupediconpicker/group.rs +++ b/crates/rnote-ui/src/groupediconpicker/group.rs @@ -160,7 +160,7 @@ impl RnGroupedIconPickerGroup { }); imp.flowbox.connect_child_activated( - clone!(@weak grouped_icon_picker => move |_flowbox: &FlowBox, flowbox_child: &FlowBoxChild| { + clone!(#[weak] grouped_icon_picker , move |_flowbox: &FlowBox, flowbox_child: &FlowBoxChild| { let icon_name = flowbox_child .child() .expect("GroupIconPickerFlowBox child activated signal callback failed, child has to exist") @@ -176,32 +176,37 @@ impl RnGroupedIconPickerGroup { // Icon has been picked, update selection and label text. grouped_icon_picker.connect_notify_local( Some("picked"), - clone!(@weak self as group => move |grouped_icon_picker, _| { - let flowbox = group.imp().flowbox.get(); - - if let Some(picked) = grouped_icon_picker.picked() { - let item = group - .icon_list() - .snapshot() - .into_iter() - .map(|o| o.downcast::().unwrap().string()) - .enumerate() - .find(|(_, s)| s == &picked); - - if let Some((i, _)) = item { - // Current group contains child, select it. - let child = flowbox.child_at_index(i as i32).unwrap(); - flowbox.select_child(&child); - grouped_icon_picker.set_selection_label_text(generate_display_name(picked.as_str())); + clone!( + #[weak(rename_to=group)] + self, + move |grouped_icon_picker, _| { + let flowbox = group.imp().flowbox.get(); + + if let Some(picked) = grouped_icon_picker.picked() { + let item = group + .icon_list() + .snapshot() + .into_iter() + .map(|o| o.downcast::().unwrap().string()) + .enumerate() + .find(|(_, s)| s == &picked); + + if let Some((i, _)) = item { + // Current group contains child, select it. + let child = flowbox.child_at_index(i as i32).unwrap(); + flowbox.select_child(&child); + grouped_icon_picker + .set_selection_label_text(generate_display_name(picked.as_str())); + } else { + // Current group does not contain child, unselect all children. + flowbox.unselect_all(); + } } else { - // Current group does not contain child, unselect all children. + // Selection is None, unselect all children. flowbox.unselect_all(); } - } else { - // Selection is None, unselect all children. - flowbox.unselect_all(); } - }), + ), ); } } diff --git a/crates/rnote-ui/src/groupediconpicker/mod.rs b/crates/rnote-ui/src/groupediconpicker/mod.rs index bf2244044b..07e23c2d6a 100644 --- a/crates/rnote-ui/src/groupediconpicker/mod.rs +++ b/crates/rnote-ui/src/groupediconpicker/mod.rs @@ -137,13 +137,30 @@ impl RnGroupedIconPicker { ) { let model = StringList::from_iter(groups.iter().map(|x| x.name.clone())); - self.imp().listbox.get().bind_model(Some(&model), clone!(@weak self as iconpicker => @default-panic, move |obj| { - let group_name = obj.downcast_ref::().expect( + self.imp().listbox.get().bind_model( + Some(&model), + clone!( + #[weak(rename_to=iconpicker)] + self, + #[upgrade_or_panic] + move |obj| { + let group_name = obj.downcast_ref::().expect( "Binding IconPickerListFactory model failed, item has to be of type `StringObject`", ).string(); - let icon_names = &groups.iter().find(|x| x.name.as_str() == group_name.as_str()).unwrap().icons; - let group = RnGroupedIconPickerGroup::new(&group_name.to_string(), icon_names, &iconpicker, generate_display_name); - group.upcast::() - })); + let icon_names = &groups + .iter() + .find(|x| x.name.as_str() == group_name.as_str()) + .unwrap() + .icons; + let group = RnGroupedIconPickerGroup::new( + &group_name.to_string(), + icon_names, + &iconpicker, + generate_display_name, + ); + group.upcast::() + } + ), + ); } } diff --git a/crates/rnote-ui/src/iconpicker.rs b/crates/rnote-ui/src/iconpicker.rs index 6f5a0e8298..212c0fc6ba 100644 --- a/crates/rnote-ui/src/iconpicker.rs +++ b/crates/rnote-ui/src/iconpicker.rs @@ -203,22 +203,26 @@ impl RnIconPicker { let generate_display_name = generate_display_name_option.unwrap_or(|_| String::new()); self.imp().selected_handlerid.borrow_mut().replace( - single_selection.connect_selected_item_notify( - clone!(@weak self as iconpicker => move |_| { + single_selection.connect_selected_item_notify(clone!( + #[weak(rename_to=iconpicker)] + self, + move |_| { let pick = iconpicker.picked_intern(); if show_display_name && show_selection_label { if let Some(icon_name) = &pick { iconpicker.set_selection_label_visible(true); - iconpicker.set_selection_label_text(generate_display_name(icon_name.as_str())); + iconpicker.set_selection_label_text(generate_display_name( + icon_name.as_str(), + )); } else { iconpicker.set_selection_label_visible(false); } } iconpicker.set_picked(pick); - }), - ), + } + )), ); // Factory diff --git a/crates/rnote-ui/src/overlays.rs b/crates/rnote-ui/src/overlays.rs index d5538fa684..e6d5fd46f0 100644 --- a/crates/rnote-ui/src/overlays.rs +++ b/crates/rnote-ui/src/overlays.rs @@ -156,11 +156,15 @@ impl RnOverlays { let imp = self.imp(); imp.colorpicker.connect_notify_local( - Some("stroke-color"), - clone!(@weak appwindow => move |colorpicker, _paramspec| { + Some("stroke-color"), + clone!( + #[weak] + appwindow, + move |colorpicker, _paramspec| { let stroke_color = colorpicker.stroke_color().into_compose_color(); let canvas = appwindow.active_tab_wrapper().canvas(); - let current_pen_style = canvas.engine_ref().penholder.current_pen_style_w_override(); + let current_pen_style = + canvas.engine_ref().penholder.current_pen_style_w_override(); match current_pen_style { PenStyle::Typewriter => { @@ -168,120 +172,185 @@ impl RnOverlays { appwindow.handle_widget_flags(widget_flags, &canvas); } PenStyle::Selector => { - let widget_flags = canvas.engine_mut().change_selection_stroke_colors(stroke_color); + let widget_flags = canvas + .engine_mut() + .change_selection_stroke_colors(stroke_color); appwindow.handle_widget_flags(widget_flags, &canvas); } - PenStyle::Brush | PenStyle::Shaper | PenStyle::Eraser | PenStyle::Tools => {} + PenStyle::Brush | PenStyle::Shaper | PenStyle::Eraser | PenStyle::Tools => { + } } // We have a global colorpicker, so we apply it to all styles - canvas.engine_mut().pens_config.set_all_stroke_colors(stroke_color); - }), - ); + canvas + .engine_mut() + .pens_config + .set_all_stroke_colors(stroke_color); + } + ), + ); imp.colorpicker.connect_notify_local( Some("fill-color"), - clone!(@weak appwindow => move |colorpicker, _paramspec| { - let fill_color = colorpicker.fill_color().into_compose_color(); - let canvas = appwindow.active_tab_wrapper().canvas(); - let stroke_style = canvas.engine_ref().penholder.current_pen_style_w_override(); - - match stroke_style { - PenStyle::Selector => { - let widget_flags = canvas.engine_mut().change_selection_fill_colors(fill_color); - appwindow.handle_widget_flags(widget_flags, &canvas); + clone!( + #[weak] + appwindow, + move |colorpicker, _paramspec| { + let fill_color = colorpicker.fill_color().into_compose_color(); + let canvas = appwindow.active_tab_wrapper().canvas(); + let stroke_style = canvas.engine_ref().penholder.current_pen_style_w_override(); + + match stroke_style { + PenStyle::Selector => { + let widget_flags = + canvas.engine_mut().change_selection_fill_colors(fill_color); + appwindow.handle_widget_flags(widget_flags, &canvas); + } + PenStyle::Typewriter + | PenStyle::Brush + | PenStyle::Shaper + | PenStyle::Eraser + | PenStyle::Tools => {} } - PenStyle::Typewriter | PenStyle::Brush | PenStyle::Shaper | PenStyle::Eraser | PenStyle::Tools => {} - } - // We have a global colorpicker, so we apply it to all styles - canvas.engine_mut().pens_config.set_all_fill_colors(fill_color); - }), + // We have a global colorpicker, so we apply it to all styles + canvas + .engine_mut() + .pens_config + .set_all_fill_colors(fill_color); + } + ), ); } fn setup_tabview(&self, appwindow: &RnAppWindow) { let imp = self.imp(); - imp.tabview - .connect_selected_page_notify(clone!(@weak self as overlays, @weak appwindow => move |_| { + imp.tabview.connect_selected_page_notify(clone!( + #[weak(rename_to=overlays)] + self, + #[weak] + appwindow, + move |_| { let active_tab_page = appwindow.active_tab_page(); - let active_canvaswrapper = active_tab_page.child().downcast::().unwrap(); + let active_canvaswrapper = active_tab_page + .child() + .downcast::() + .unwrap(); appwindow.tabs_set_unselected_inactive(); if let Some(prev_active_tab_page) = overlays.imp().prev_active_tab_page.upgrade() { - if prev_active_tab_page != active_tab_page { - appwindow.sync_state_between_tabs(&prev_active_tab_page, &active_tab_page); - } + if prev_active_tab_page != active_tab_page { + appwindow.sync_state_between_tabs(&prev_active_tab_page, &active_tab_page); + } } - overlays.imp().prev_active_tab_page.set(Some(&active_tab_page)); + overlays + .imp() + .prev_active_tab_page + .set(Some(&active_tab_page)); let widget_flags = active_canvaswrapper.canvas().engine_mut().set_active(true); appwindow.handle_widget_flags(widget_flags, &active_canvaswrapper.canvas()); appwindow.refresh_ui_from_engine(&active_canvaswrapper); - })); + } + )); - imp.tabview.connect_page_attached( - clone!(@weak self as overlays, @weak appwindow => move |_tabview, page, _| { + imp.tabview.connect_page_attached(clone!( + #[weak] + appwindow, + move |_, page, _| { let canvaswrapper = page.child().downcast::().unwrap(); canvaswrapper.init_reconnect(&appwindow); canvaswrapper.connect_to_tab_page(page); let widget_flags = canvaswrapper.canvas().engine_mut().set_active(true); appwindow.handle_widget_flags(widget_flags, &canvaswrapper.canvas()); - }), - ); + } + )); - imp.tabview.connect_page_detached( - clone!(@weak self as overlays, @weak appwindow => move |_, page, _| { + imp.tabview.connect_page_detached(clone!( + #[weak(rename_to=overlays)] + self, + move |_, page, _| { let canvaswrapper = page.child().downcast::().unwrap(); // if the to be detached page was the active (selected), remove it. - if overlays.imp().prev_active_tab_page.upgrade().map_or(true, |prev| prev == *page) { + if overlays + .imp() + .prev_active_tab_page + .upgrade() + .map_or(true, |prev| prev == *page) + { overlays.imp().prev_active_tab_page.set(None); } let _ = canvaswrapper.canvas().engine_mut().set_active(false); canvaswrapper.disconnect_connections(); - }), - ); - - imp.tabview.connect_close_page( - clone!(@weak self as overlays, @weak appwindow => @default-return glib::Propagation::Proceed, move |_, page| { - glib::spawn_future_local(clone!(@weak overlays, @weak appwindow, @weak page => async move { - let close_finish_confirm = if page - .child() - .downcast::() - .unwrap() - .canvas() - .unsaved_changes() - { - dialogs::dialog_close_tab(&appwindow, &page).await - } else { - true - }; - - appwindow.close_tab_finish(&page, close_finish_confirm); - })); + } + )); + + imp.tabview.connect_close_page(clone!( + #[weak] + appwindow, + #[upgrade_or] + glib::Propagation::Proceed, + move |_, page| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + #[weak] + page, + async move { + let close_finish_confirm = if page + .child() + .downcast::() + .unwrap() + .canvas() + .unsaved_changes() + { + dialogs::dialog_close_tab(&appwindow, &page).await + } else { + true + }; + + appwindow.close_tab_finish(&page, close_finish_confirm); + } + )); glib::Propagation::Proceed - }), - ); - - imp.tabview.connect_setup_menu(clone!(@weak appwindow => move |tabview, page| { - if let Some(page) = page { - let action_active_tab_move_left = appwindow.lookup_action("active-tab-move-left").unwrap().downcast::().unwrap(); - let action_active_tab_move_right = appwindow.lookup_action("active-tab-move-right").unwrap().downcast::().unwrap(); - let action_active_tab_close = appwindow.lookup_action("active-tab-close").unwrap().downcast::().unwrap(); + } + )); + + imp.tabview.connect_setup_menu(clone!( + #[weak] + appwindow, + move |tabview, page| { + if let Some(page) = page { + let action_active_tab_move_left = appwindow + .lookup_action("active-tab-move-left") + .unwrap() + .downcast::() + .unwrap(); + let action_active_tab_move_right = appwindow + .lookup_action("active-tab-move-right") + .unwrap() + .downcast::() + .unwrap(); + let action_active_tab_close = appwindow + .lookup_action("active-tab-close") + .unwrap() + .downcast::() + .unwrap(); - tabview.set_selected_page(page); + tabview.set_selected_page(page); - let n_pages = tabview.n_pages(); - let pos = tabview.page_position(page); - action_active_tab_move_left.set_enabled(pos > 0); - action_active_tab_move_right.set_enabled(pos + 1 < n_pages); - action_active_tab_close.set_enabled(n_pages > 1); + let n_pages = tabview.n_pages(); + let pos = tabview.page_position(page); + action_active_tab_move_left.set_enabled(pos > 0); + action_active_tab_move_right.set_enabled(pos + 1 < n_pages); + action_active_tab_close.set_enabled(n_pages > 1); + } } - })); + )); } pub(crate) fn progressbar_start_pulsing(&self) { @@ -291,14 +360,24 @@ impl RnOverlays { .progresspulses_active .set(self.imp().progresspulses_active.get().saturating_add(1)); - if let Some(src) = self.imp().progresspulse_id.replace(Some(glib::source::timeout_add_local( - PULSE_INTERVAL, - clone!(@weak self as appwindow => @default-return glib::ControlFlow::Break, move || { - appwindow.progressbar().pulse(); - - glib::ControlFlow::Continue - })), - )) { + if let Some(src) = + self.imp() + .progresspulse_id + .replace(Some(glib::source::timeout_add_local( + PULSE_INTERVAL, + clone!( + #[weak(rename_to=appwindow)] + self, + #[upgrade_or] + glib::ControlFlow::Break, + move || { + appwindow.progressbar().pulse(); + + glib::ControlFlow::Continue + } + ), + ))) + { src.remove(); } } @@ -317,9 +396,13 @@ impl RnOverlays { } glib::source::timeout_add_local_once( FINISH_TIMEOUT, - clone!(@weak self as appwindow => move || { - appwindow.progressbar().set_fraction(0.); - }), + clone!( + #[weak(rename_to=appwindow)] + self, + move || { + appwindow.progressbar().set_fraction(0.); + } + ), ); } } diff --git a/crates/rnote-ui/src/penpicker.rs b/crates/rnote-ui/src/penpicker.rs index 35b82650fd..a051442fd4 100644 --- a/crates/rnote-ui/src/penpicker.rs +++ b/crates/rnote-ui/src/penpicker.rs @@ -108,55 +108,88 @@ impl RnPenPicker { pub(crate) fn init(&self, appwindow: &RnAppWindow) { let imp = self.imp(); - imp.brush_toggle - .connect_toggled(clone!(@weak appwindow => move |brush_toggle| { + imp.brush_toggle.connect_toggled(clone!( + #[weak] + appwindow, + move |brush_toggle| { if brush_toggle.is_active() { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Brush.to_string().to_variant())); + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Brush.to_string().to_variant()), + ); } - })); + } + )); - imp.shaper_toggle - .connect_toggled(clone!(@weak appwindow => move |shaper_toggle| { + imp.shaper_toggle.connect_toggled(clone!( + #[weak] + appwindow, + move |shaper_toggle| { if shaper_toggle.is_active() { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Shaper.to_string().to_variant())); + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Shaper.to_string().to_variant()), + ); } - })); + } + )); - imp.typewriter_toggle - .connect_toggled(clone!(@weak appwindow => move |typewriter_toggle| { + imp.typewriter_toggle.connect_toggled(clone!( + #[weak] + appwindow, + move |typewriter_toggle| { if typewriter_toggle.is_active() { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Typewriter.to_string().to_variant())); + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Typewriter.to_string().to_variant()), + ); } - })); + } + )); - imp.eraser_toggle - .get() - .connect_toggled(clone!(@weak appwindow => move |eraser_toggle| { + imp.eraser_toggle.get().connect_toggled(clone!( + #[weak] + appwindow, + move |eraser_toggle| { if eraser_toggle.is_active() { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Eraser.to_string().to_variant())); + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Eraser.to_string().to_variant()), + ); } - })); + } + )); - imp.selector_toggle.get().connect_toggled( - clone!(@weak appwindow => move |selector_toggle| { + imp.selector_toggle.get().connect_toggled(clone!( + #[weak] + appwindow, + move |selector_toggle| { if selector_toggle.is_active() { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Selector.to_string().to_variant())); + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Selector.to_string().to_variant()), + ); } - }), - ); + } + )); - imp.tools_toggle - .get() - .connect_toggled(clone!(@weak appwindow => move |tools_toggle| { + imp.tools_toggle.get().connect_toggled(clone!( + #[weak] + appwindow, + move |tools_toggle| { if tools_toggle.is_active() { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Tools.to_string().to_variant())); + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Tools.to_string().to_variant()), + ); } - })); + } + )); } } diff --git a/crates/rnote-ui/src/penssidebar/brushpage.rs b/crates/rnote-ui/src/penssidebar/brushpage.rs index 8e58c6ff85..4baed671b3 100644 --- a/crates/rnote-ui/src/penssidebar/brushpage.rs +++ b/crates/rnote-ui/src/penssidebar/brushpage.rs @@ -198,16 +198,20 @@ impl RnBrushPage { let brushconfig_popover = imp.brushconfig_popover.get(); // Popovers - imp.brushstyle_popover_close_button.connect_clicked( - clone!(@weak brushstyle_popover => move |_| { + imp.brushstyle_popover_close_button.connect_clicked(clone!( + #[weak] + brushstyle_popover, + move |_| { brushstyle_popover.popdown(); - }), - ); - imp.brushconfig_popover_close_button.connect_clicked( - clone!(@weak brushconfig_popover => move |_| { + } + )); + imp.brushconfig_popover_close_button.connect_clicked(clone!( + #[weak] + brushconfig_popover, + move |_| { brushconfig_popover.popdown(); - }), - ); + } + )); // Stroke width imp.stroke_width_picker @@ -219,67 +223,160 @@ impl RnBrushPage { imp.stroke_width_picker.connect_notify_local( Some("stroke-width"), - clone!(@weak self as brushpage, @weak appwindow => move |picker, _| { - let stroke_width = picker.stroke_width(); - let canvas = appwindow.active_tab_wrapper().canvas(); - let brush_style = canvas.engine_ref().pens_config.brush_config.style; - - match brush_style { - BrushStyle::Marker => { - canvas.engine_mut().pens_config.brush_config.marker_options.stroke_width = stroke_width; - }, - BrushStyle::Solid => { - canvas.engine_mut().pens_config.brush_config.solid_options.stroke_width = stroke_width; - }, - BrushStyle::Textured => { - canvas.engine_mut().pens_config.brush_config.textured_options.stroke_width = stroke_width; - }, + clone!( + #[weak] + appwindow, + move |picker, _| { + let stroke_width = picker.stroke_width(); + let canvas = appwindow.active_tab_wrapper().canvas(); + let brush_style = canvas.engine_ref().pens_config.brush_config.style; + + match brush_style { + BrushStyle::Marker => { + canvas + .engine_mut() + .pens_config + .brush_config + .marker_options + .stroke_width = stroke_width; + } + BrushStyle::Solid => { + canvas + .engine_mut() + .pens_config + .brush_config + .solid_options + .stroke_width = stroke_width; + } + BrushStyle::Textured => { + canvas + .engine_mut() + .pens_config + .brush_config + .textured_options + .stroke_width = stroke_width; + } + } } - }), + ), ); // Style - imp.brushstyle_listbox.connect_row_selected( - clone!(@weak self as brushpage, @weak appwindow => move |_, _| { + imp.brushstyle_listbox.connect_row_selected(clone!( + #[weak(rename_to=brushpage)] + self, + #[weak] + appwindow, + move |_, _| { if let Some(brush_style) = brushpage.brush_style() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.brush_config.style = brush_style; + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .brush_config + .style = brush_style; brushpage.stroke_width_picker().deselect_setters(); match brush_style { BrushStyle::Marker => { - let stroke_width = appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.brush_config.marker_options.stroke_width; - brushpage.imp().stroke_width_picker.set_stroke_width(stroke_width); - brushpage.imp().brushstyle_menubutton.set_icon_name("pen-brush-style-marker-symbolic"); - }, + let stroke_width = appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .brush_config + .marker_options + .stroke_width; + brushpage + .imp() + .stroke_width_picker + .set_stroke_width(stroke_width); + brushpage + .imp() + .brushstyle_menubutton + .set_icon_name("pen-brush-style-marker-symbolic"); + } BrushStyle::Solid => { - let stroke_width = appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.brush_config.solid_options.stroke_width; - brushpage.imp().stroke_width_picker.set_stroke_width(stroke_width); - brushpage.imp().brushstyle_menubutton.set_icon_name("pen-brush-style-solid-symbolic"); - }, + let stroke_width = appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .brush_config + .solid_options + .stroke_width; + brushpage + .imp() + .stroke_width_picker + .set_stroke_width(stroke_width); + brushpage + .imp() + .brushstyle_menubutton + .set_icon_name("pen-brush-style-solid-symbolic"); + } BrushStyle::Textured => { - let stroke_width = appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.brush_config.textured_options.stroke_width; - brushpage.imp().stroke_width_picker.set_stroke_width(stroke_width); - brushpage.imp().brushstyle_menubutton.set_icon_name("pen-brush-style-textured-symbolic"); - }, + let stroke_width = appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .brush_config + .textured_options + .stroke_width; + brushpage + .imp() + .stroke_width_picker + .set_stroke_width(stroke_width); + brushpage + .imp() + .brushstyle_menubutton + .set_icon_name("pen-brush-style-textured-symbolic"); + } } } - }), - ); + } + )); // Builder type - imp.brush_buildertype_listbox.connect_row_selected( - clone!(@weak self as brushpage, @weak appwindow => move |_, _| { + imp.brush_buildertype_listbox.connect_row_selected(clone!( + #[weak(rename_to=brushpage)] + self, + #[weak] + appwindow, + move |_, _| { if let Some(buildertype) = brushpage.buildertype() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.brush_config.builder_type = buildertype; + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .brush_config + .builder_type = buildertype; } - }), - ); + } + )); // Solid style // Pressure curve - imp.solidstyle_pressure_curves_row.get().connect_selected_notify(clone!(@weak self as brushpage, @weak appwindow => move |_smoothstyle_pressure_curves_row| { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.brush_config.solid_options.pressure_curve = brushpage.solidstyle_pressure_curve(); - })); + imp.solidstyle_pressure_curves_row + .get() + .connect_selected_notify(clone!( + #[weak(rename_to=brushpage)] + self, + #[weak] + appwindow, + move |_smoothstyle_pressure_curves_row| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .brush_config + .solid_options + .pressure_curve = brushpage.solidstyle_pressure_curve(); + } + )); // Textured style // Density @@ -291,16 +388,40 @@ impl RnBrushPage { .get() .set_value(TexturedOptions::default().density); - imp.texturedstyle_density_row.get().connect_changed( - clone!(@weak appwindow => move |row| { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.brush_config.textured_options.density = row.value(); - }), - ); + imp.texturedstyle_density_row.get().connect_changed(clone!( + #[weak] + appwindow, + move |row| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .brush_config + .textured_options + .density = row.value(); + } + )); // dots distribution - imp.texturedstyle_distribution_row.get().connect_selected_notify(clone!(@weak self as brushpage, @weak appwindow => move |_texturedstyle_distribution_row| { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.brush_config.textured_options.distribution = brushpage.texturedstyle_dots_distribution(); - })); + imp.texturedstyle_distribution_row + .get() + .connect_selected_notify(clone!( + #[weak(rename_to=brushpage)] + self, + #[weak] + appwindow, + move |_texturedstyle_distribution_row| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .brush_config + .textured_options + .distribution = brushpage.texturedstyle_dots_distribution(); + } + )); } pub(crate) fn refresh_ui(&self, active_tab: &RnCanvasWrapper) { diff --git a/crates/rnote-ui/src/penssidebar/eraserpage.rs b/crates/rnote-ui/src/penssidebar/eraserpage.rs index 5793558086..70f29e19ad 100644 --- a/crates/rnote-ui/src/penssidebar/eraserpage.rs +++ b/crates/rnote-ui/src/penssidebar/eraserpage.rs @@ -107,17 +107,39 @@ impl RnEraserPage { pub(crate) fn init(&self, appwindow: &RnAppWindow) { let imp = self.imp(); - imp.eraserstyle_trash_colliding_strokes_toggle.connect_toggled(clone!(@weak appwindow => move |eraserstyle_trash_colliding_strokes_toggle| { - if eraserstyle_trash_colliding_strokes_toggle.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.eraser_config.style = EraserStyle::TrashCollidingStrokes; - } - })); - - imp.eraserstyle_split_colliding_strokes_toggle.connect_toggled(clone!(@weak appwindow => move |eraserstyle_split_colliding_strokes_toggle| { - if eraserstyle_split_colliding_strokes_toggle.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.eraser_config.style = EraserStyle::SplitCollidingStrokes; - } - })); + imp.eraserstyle_trash_colliding_strokes_toggle + .connect_toggled(clone!( + #[weak] + appwindow, + move |eraserstyle_trash_colliding_strokes_toggle| { + if eraserstyle_trash_colliding_strokes_toggle.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .eraser_config + .style = EraserStyle::TrashCollidingStrokes; + } + } + )); + + imp.eraserstyle_split_colliding_strokes_toggle + .connect_toggled(clone!( + #[weak] + appwindow, + move |eraserstyle_split_colliding_strokes_toggle| { + if eraserstyle_split_colliding_strokes_toggle.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .eraser_config + .style = EraserStyle::SplitCollidingStrokes; + } + } + )); // width imp.stroke_width_picker.spinbutton().set_digits(0); @@ -133,10 +155,20 @@ impl RnEraserPage { imp.stroke_width_picker.connect_notify_local( Some("stroke-width"), - clone!(@weak appwindow => move |picker, _| { - let stroke_width = picker.stroke_width(); - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.eraser_config.width = stroke_width; - }), + clone!( + #[weak] + appwindow, + move |picker, _| { + let stroke_width = picker.stroke_width(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .eraser_config + .width = stroke_width; + } + ), ); } diff --git a/crates/rnote-ui/src/penssidebar/mod.rs b/crates/rnote-ui/src/penssidebar/mod.rs index aba32440db..cf5fe34cbc 100644 --- a/crates/rnote-ui/src/penssidebar/mod.rs +++ b/crates/rnote-ui/src/penssidebar/mod.rs @@ -134,36 +134,58 @@ impl RnPensSideBar { self.imp() .sidebar_stack .get() - .connect_visible_child_name_notify(clone!(@weak appwindow => move |sidebar_stack| { - if let Some(child_name) = sidebar_stack.visible_child_name() { - match child_name.to_value().get::().unwrap().as_str() { - "brush_page" => { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Brush.to_string().to_variant())); - }, - "shaper_page" => { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Shaper.to_string().to_variant())); - }, - "typewriter_page" => { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Typewriter.to_string().to_variant())); - }, - "eraser_page" => { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Eraser.to_string().to_variant())); - } - "selector_page" => { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Selector.to_string().to_variant())); - } - "tools_page" => { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-style", - Some(&PenStyle::Tools.to_string().to_variant())); - } - _ => {} + .connect_visible_child_name_notify(clone!( + #[weak] + appwindow, + move |sidebar_stack| { + if let Some(child_name) = sidebar_stack.visible_child_name() { + match child_name.to_value().get::().unwrap().as_str() { + "brush_page" => { + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Brush.to_string().to_variant()), + ); + } + "shaper_page" => { + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Shaper.to_string().to_variant()), + ); + } + "typewriter_page" => { + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Typewriter.to_string().to_variant()), + ); + } + "eraser_page" => { + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Eraser.to_string().to_variant()), + ); + } + "selector_page" => { + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Selector.to_string().to_variant()), + ); + } + "tools_page" => { + adw::prelude::ActionGroupExt::activate_action( + &appwindow, + "pen-style", + Some(&PenStyle::Tools.to_string().to_variant()), + ); + } + _ => {} + }; }; - }; - })); + } + )); } } diff --git a/crates/rnote-ui/src/penssidebar/selectorpage.rs b/crates/rnote-ui/src/penssidebar/selectorpage.rs index b09942b73a..68cf478845 100644 --- a/crates/rnote-ui/src/penssidebar/selectorpage.rs +++ b/crates/rnote-ui/src/penssidebar/selectorpage.rs @@ -99,33 +99,85 @@ impl RnSelectorPage { pub(crate) fn init(&self, appwindow: &RnAppWindow) { let imp = self.imp(); - imp.selectorstyle_polygon_toggle.connect_toggled(clone!(@weak appwindow => move |selectorstyle_polygon_toggle| { - if selectorstyle_polygon_toggle.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.selector_config.style = SelectorStyle::Polygon; + imp.selectorstyle_polygon_toggle.connect_toggled(clone!( + #[weak] + appwindow, + move |selectorstyle_polygon_toggle| { + if selectorstyle_polygon_toggle.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .selector_config + .style = SelectorStyle::Polygon; + } } - })); - - imp.selectorstyle_rect_toggle.connect_toggled(clone!(@weak appwindow => move |selectorstyle_rect_toggle| { - if selectorstyle_rect_toggle.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.selector_config.style = SelectorStyle::Rectangle; + )); + + imp.selectorstyle_rect_toggle.connect_toggled(clone!( + #[weak] + appwindow, + move |selectorstyle_rect_toggle| { + if selectorstyle_rect_toggle.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .selector_config + .style = SelectorStyle::Rectangle; + } } - })); - - imp.selectorstyle_single_toggle.connect_toggled(clone!(@weak appwindow => move |selectorstyle_single_toggle| { - if selectorstyle_single_toggle.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.selector_config.style = SelectorStyle::Single; + )); + + imp.selectorstyle_single_toggle.connect_toggled(clone!( + #[weak] + appwindow, + move |selectorstyle_single_toggle| { + if selectorstyle_single_toggle.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .selector_config + .style = SelectorStyle::Single; + } } - })); + )); + + imp.selectorstyle_intersectingpath_toggle + .connect_toggled(clone!( + #[weak] + appwindow, + move |selectorstyle_intersectingpath_toggle| { + if selectorstyle_intersectingpath_toggle.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .selector_config + .style = SelectorStyle::IntersectingPath; + } + } + )); - imp.selectorstyle_intersectingpath_toggle.connect_toggled(clone!(@weak appwindow => move |selectorstyle_intersectingpath_toggle| { - if selectorstyle_intersectingpath_toggle.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.selector_config.style = SelectorStyle::IntersectingPath; - } - })); - - imp.resize_lock_aspectratio_togglebutton.connect_toggled(clone!(@weak appwindow = > move |resize_lock_aspectratio_togglebutton| { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.selector_config.resize_lock_aspectratio = resize_lock_aspectratio_togglebutton.is_active(); - })); + imp.resize_lock_aspectratio_togglebutton + .connect_toggled(clone!( + #[weak] + appwindow, + move |resize_lock_aspectratio_togglebutton| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .selector_config + .resize_lock_aspectratio = resize_lock_aspectratio_togglebutton.is_active(); + } + )); } pub(crate) fn refresh_ui(&self, active_tab: &RnCanvasWrapper) { diff --git a/crates/rnote-ui/src/penssidebar/shaperpage.rs b/crates/rnote-ui/src/penssidebar/shaperpage.rs index 3a152f1d40..8655e43108 100644 --- a/crates/rnote-ui/src/penssidebar/shaperpage.rs +++ b/crates/rnote-ui/src/penssidebar/shaperpage.rs @@ -186,26 +186,35 @@ impl RnShaperPage { let constraint_popover = imp.constraint_popover.get(); // Popovers - imp.shaperstyle_popover_close_button.connect_clicked( - clone!(@weak shaperstyle_popover => move |_| { + imp.shaperstyle_popover_close_button.connect_clicked(clone!( + #[weak] + shaperstyle_popover, + move |_| { shaperstyle_popover.popdown(); - }), - ); - imp.shapeconfig_popover_close_button.connect_clicked( - clone!(@weak shapeconfig_popover => move |_| { + } + )); + imp.shapeconfig_popover_close_button.connect_clicked(clone!( + #[weak] + shapeconfig_popover, + move |_| { shapeconfig_popover.popdown(); - }), - ); - imp.shapebuildertype_popover_close_button.connect_clicked( - clone!(@weak shapebuildertype_popover => move |_| { - shapebuildertype_popover.popdown(); - }), - ); - imp.constraint_popover_close_button.connect_clicked( - clone!(@weak constraint_popover => move |_| { + } + )); + imp.shapebuildertype_popover_close_button + .connect_clicked(clone!( + #[weak] + shapebuildertype_popover, + move |_| { + shapebuildertype_popover.popdown(); + } + )); + imp.constraint_popover_close_button.connect_clicked(clone!( + #[weak] + constraint_popover, + move |_| { constraint_popover.popdown(); - }), - ); + } + )); // Stroke width imp.stroke_width_picker.spinbutton().set_range( @@ -218,55 +227,137 @@ impl RnShaperPage { imp.stroke_width_picker.connect_notify_local( Some("stroke-width"), - clone!(@weak self as shaperpage, @weak appwindow => move |picker, _| { - let stroke_width = picker.stroke_width(); - let canvas = appwindow.active_tab_wrapper().canvas(); - let shaper_style = canvas.engine_ref().pens_config.shaper_config.style; - - match shaper_style { - ShaperStyle::Smooth => { - canvas.engine_mut().pens_config.shaper_config.smooth_options.stroke_width = stroke_width; - }, - ShaperStyle::Rough => { - canvas.engine_mut().pens_config.shaper_config.rough_options.stroke_width = stroke_width; - }, + clone!( + #[weak] + appwindow, + move |picker, _| { + let stroke_width = picker.stroke_width(); + let canvas = appwindow.active_tab_wrapper().canvas(); + let shaper_style = canvas.engine_ref().pens_config.shaper_config.style; + + match shaper_style { + ShaperStyle::Smooth => { + canvas + .engine_mut() + .pens_config + .shaper_config + .smooth_options + .stroke_width = stroke_width; + } + ShaperStyle::Rough => { + canvas + .engine_mut() + .pens_config + .shaper_config + .rough_options + .stroke_width = stroke_width; + } + } } - }), + ), ); // Shaper style - imp.shaperstyle_listbox.connect_row_selected( - clone!(@weak self as shaperpage, @weak appwindow => move |_, _| { + imp.shaperstyle_listbox.connect_row_selected(clone!( + #[weak(rename_to=shaperpage)] + self, + #[weak] + appwindow, + move |_, _| { if let Some(shaper_style) = shaperpage.shaper_style() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.style = shaper_style; + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .style = shaper_style; shaperpage.stroke_width_picker().deselect_setters(); match shaper_style { ShaperStyle::Smooth => { - let stroke_width = appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.smooth_options.stroke_width; - shaperpage.imp().stroke_width_picker.set_stroke_width(stroke_width); - shaperpage.imp().shaperstyle_menubutton.set_icon_name("pen-shaper-style-smooth-symbolic"); - }, + let stroke_width = appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .smooth_options + .stroke_width; + shaperpage + .imp() + .stroke_width_picker + .set_stroke_width(stroke_width); + shaperpage + .imp() + .shaperstyle_menubutton + .set_icon_name("pen-shaper-style-smooth-symbolic"); + } ShaperStyle::Rough => { - let stroke_width = appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.rough_options.stroke_width; - shaperpage.imp().stroke_width_picker.set_stroke_width(stroke_width); - shaperpage.imp().shaperstyle_menubutton.set_icon_name("pen-shaper-style-rough-symbolic"); - }, + let stroke_width = appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .rough_options + .stroke_width; + shaperpage + .imp() + .stroke_width_picker + .set_stroke_width(stroke_width); + shaperpage + .imp() + .shaperstyle_menubutton + .set_icon_name("pen-shaper-style-rough-symbolic"); + } } } - }), - ); + } + )); // Rough style // Fill style - imp.roughstyle_fillstyle_row.get().connect_selected_notify(clone!(@weak self as shaperpage, @weak appwindow => move |_roughstyle_fillstyle_row| { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.rough_options.fill_style = shaperpage.roughstyle_fillstyle(); - })); + imp.roughstyle_fillstyle_row + .get() + .connect_selected_notify(clone!( + #[weak(rename_to=shaperpage)] + self, + #[weak] + appwindow, + move |_| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .rough_options + .fill_style = shaperpage.roughstyle_fillstyle(); + } + )); // Hachure angle - imp.roughstyle_hachure_angle_row.get().connect_changed(clone!(@weak self as shaperpage, @weak appwindow => move |row| { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.rough_options.hachure_angle = row.value().round().to_radians().clamp(-std::f64::consts::PI, std::f64::consts::PI); - })); + imp.roughstyle_hachure_angle_row + .get() + .connect_changed(clone!( + #[weak] + appwindow, + move |row| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .rough_options + .hachure_angle = row + .value() + .round() + .to_radians() + .clamp(-std::f64::consts::PI, std::f64::consts::PI); + } + )); // shape builder type imp.shapebuildertype_picker.set_groups( @@ -276,54 +367,138 @@ impl RnShaperPage { imp.shapebuildertype_picker.connect_notify_local( Some("picked"), - clone!(@weak self as shaperpage, @weak appwindow => move |picker, _| { - if let (Some(buildertype), Some(icon_name)) = (shaperpage.shapebuildertype(), picker.picked()) { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.builder_type = buildertype; - shaperpage.imp().shapebuildertype_menubutton.set_icon_name(&icon_name); + clone!( + #[weak(rename_to=shaperpage)] + self, + #[weak] + appwindow, + move |picker, _| { + if let (Some(buildertype), Some(icon_name)) = + (shaperpage.shapebuildertype(), picker.picked()) + { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .builder_type = buildertype; + shaperpage + .imp() + .shapebuildertype_menubutton + .set_icon_name(&icon_name); + } } - }), + ), ); // Constraints - imp - .constraint_enabled_row + imp.constraint_enabled_row .get() - .connect_active_notify(clone!(@weak appwindow => move |row| { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.constraints.enabled = row.is_active(); - })); + .connect_active_notify(clone!( + #[weak] + appwindow, + move |row| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .constraints + .enabled = row.is_active(); + } + )); - imp - .constraint_one_to_one_row + imp.constraint_one_to_one_row .get() - .connect_active_notify(clone!(@weak appwindow => move |row| { - if row.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.constraints.ratios.insert(ConstraintRatio::OneToOne); - } else { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.constraints.ratios.remove(&ConstraintRatio::OneToOne); + .connect_active_notify(clone!( + #[weak] + appwindow, + move |row| { + if row.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .constraints + .ratios + .insert(ConstraintRatio::OneToOne); + } else { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .constraints + .ratios + .remove(&ConstraintRatio::OneToOne); + } } - })); + )); - imp - .constraint_three_to_two_row + imp.constraint_three_to_two_row .get() - .connect_active_notify(clone!(@weak appwindow => move |row| { - if row.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.constraints.ratios.insert(ConstraintRatio::ThreeToTwo); - } else { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.constraints.ratios.remove(&ConstraintRatio::ThreeToTwo); + .connect_active_notify(clone!( + #[weak] + appwindow, + move |row| { + if row.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .constraints + .ratios + .insert(ConstraintRatio::ThreeToTwo); + } else { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .constraints + .ratios + .remove(&ConstraintRatio::ThreeToTwo); + } } - })); + )); - imp - .constraint_golden_row + imp.constraint_golden_row .get() - .connect_active_notify(clone!(@weak appwindow => move |row| { - if row.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.constraints.ratios.insert(ConstraintRatio::Golden); - } else { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.shaper_config.constraints.ratios.remove(&ConstraintRatio::Golden); + .connect_active_notify(clone!( + #[weak] + appwindow, + move |row| { + if row.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .constraints + .ratios + .insert(ConstraintRatio::Golden); + } else { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .shaper_config + .constraints + .ratios + .remove(&ConstraintRatio::Golden); + } } - })); + )); } pub(crate) fn refresh_ui(&self, active_tab: &RnCanvasWrapper) { diff --git a/crates/rnote-ui/src/penssidebar/toolspage.rs b/crates/rnote-ui/src/penssidebar/toolspage.rs index 5c750f2827..ed8f31f1b3 100644 --- a/crates/rnote-ui/src/penssidebar/toolspage.rs +++ b/crates/rnote-ui/src/penssidebar/toolspage.rs @@ -114,48 +114,105 @@ impl RnToolsPage { // for now doesn't do anything but for the close button later let verticalspace_popover = imp.verticalspace_popover.get(); - imp.toolstyle_verticalspace_toggle.connect_toggled(clone!(@weak appwindow => move |toggle| { - if toggle.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.tools_config.style = ToolStyle::VerticalSpace; + imp.toolstyle_verticalspace_toggle.connect_toggled(clone!( + #[weak] + appwindow, + move |toggle| { + if toggle.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .tools_config + .style = ToolStyle::VerticalSpace; + } } - })); - - imp.toolstyle_offsetcamera_toggle.connect_toggled(clone!(@weak appwindow => move |toggle| { - if toggle.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.tools_config.style = ToolStyle::OffsetCamera; + )); + + imp.toolstyle_offsetcamera_toggle.connect_toggled(clone!( + #[weak] + appwindow, + move |toggle| { + if toggle.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .tools_config + .style = ToolStyle::OffsetCamera; + } } - })); - - imp.toolstyle_zoom_toggle.connect_toggled(clone!(@weak appwindow => move |toggle| { - if toggle.is_active() { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.tools_config.style = ToolStyle::Zoom; + )); + + imp.toolstyle_zoom_toggle.connect_toggled(clone!( + #[weak] + appwindow, + move |toggle| { + if toggle.is_active() { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .tools_config + .style = ToolStyle::Zoom; + } } - })); + )); - imp.verticalspace_menubutton.connect_active_notify( - clone!(@weak self as toolspage => move |menubutton| { + imp.verticalspace_menubutton.connect_active_notify(clone!( + #[weak(rename_to=toolspage)] + self, + move |menubutton| { if menubutton.is_active() { toolspage.set_tool_style(ToolStyle::VerticalSpace); } - }), - ); - - imp.verticalspace_popover_close_button.connect_clicked( - clone!(@weak verticalspace_popover => move |_| { - verticalspace_popover.popdown(); - }), - ); + } + )); + + imp.verticalspace_popover_close_button + .connect_clicked(clone!( + #[weak] + verticalspace_popover, + move |_| { + verticalspace_popover.popdown(); + } + )); imp.verticalspace_limit_movement_vertical_bordersrow .get() - .connect_active_notify(clone!(@weak appwindow => move |row| { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.tools_config.verticalspace_tool_config.limit_movement_vertical_borders = row.is_active(); - })); + .connect_active_notify(clone!( + #[weak] + appwindow, + move |row| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .tools_config + .verticalspace_tool_config + .limit_movement_vertical_borders = row.is_active(); + } + )); imp.verticalspace_limit_movement_horizontal_bordersrow .get() - .connect_active_notify(clone!(@weak appwindow => move |row| { - appwindow.active_tab_wrapper().canvas().engine_mut().pens_config.tools_config.verticalspace_tool_config.limit_movement_horizontal_borders = row.is_active(); - })); + .connect_active_notify(clone!( + #[weak] + appwindow, + move |row| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .pens_config + .tools_config + .verticalspace_tool_config + .limit_movement_horizontal_borders = row.is_active(); + } + )); } pub(crate) fn refresh_ui(&self, active_tab: &RnCanvasWrapper) { diff --git a/crates/rnote-ui/src/penssidebar/typewriterpage.rs b/crates/rnote-ui/src/penssidebar/typewriterpage.rs index 2df8c387f4..74d31cb1f5 100644 --- a/crates/rnote-ui/src/penssidebar/typewriterpage.rs +++ b/crates/rnote-ui/src/penssidebar/typewriterpage.rs @@ -122,8 +122,8 @@ impl RnTypewriterPage { pub(crate) fn init(&self, appwindow: &RnAppWindow) { let imp = self.imp(); - imp.fontdialog_button.connect_clicked(clone!(@weak self as typewriterpage, @weak appwindow => move |_| { - glib::spawn_future_local(clone!(@weak typewriterpage, @weak appwindow => async move { + imp.fontdialog_button.connect_clicked(clone!(#[weak(rename_to=typewriterpage)] self , #[weak] appwindow , move |_| { + glib::spawn_future_local(clone!(#[weak] typewriterpage, #[weak] appwindow , async move { let dialog = FontDialog::builder().modal(false).build(); let prev_picked_font_family = typewriterpage.imp().prev_picked_font_family.borrow().clone(); @@ -149,121 +149,191 @@ impl RnTypewriterPage { imp.font_size_spinbutton .set_value(TextStyle::FONT_SIZE_DEFAULT); - imp.font_size_spinbutton.connect_value_changed( - clone!(@weak appwindow => move |spinbutton| { + imp.font_size_spinbutton.connect_value_changed(clone!( + #[weak] + appwindow, + move |spinbutton| { let font_size = spinbutton.value(); let canvas = appwindow.active_tab_wrapper().canvas(); - canvas.engine_mut().pens_config.typewriter_config.text_style.font_size = font_size; - let widget_flags = canvas.engine_mut().text_selection_change_style(|style| {style.font_size = font_size}); + canvas + .engine_mut() + .pens_config + .typewriter_config + .text_style + .font_size = font_size; + let widget_flags = canvas + .engine_mut() + .text_selection_change_style(|style| style.font_size = font_size); appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); // Emojis - imp.emojichooser - .connect_emoji_picked(clone!(@weak appwindow => move |_, emoji_str| { + imp.emojichooser.connect_emoji_picked(clone!( + #[weak] + appwindow, + move |_, emoji_str| { let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().insert_text(emoji_str.to_string(), None); appwindow.handle_widget_flags(widget_flags, &canvas); - })); + } + )); // reset - imp.text_reset_button - .connect_clicked(clone!(@weak appwindow => move |_| { + imp.text_reset_button.connect_clicked(clone!( + #[weak] + appwindow, + move |_| { let canvas = appwindow.active_tab_wrapper().canvas(); let widget_flags = canvas.engine_mut().text_selection_remove_attributes(); appwindow.handle_widget_flags(widget_flags, &canvas); - })); + } + )); // Bold - imp.text_bold_button - .connect_clicked(clone!(@weak appwindow => move |_| { + imp.text_bold_button.connect_clicked(clone!( + #[weak] + appwindow, + move |_| { let canvas = appwindow.active_tab_wrapper().canvas(); - let widget_flags = canvas.engine_mut().text_selection_toggle_attribute( - TextAttribute::FontWeight(piet::FontWeight::BOLD.to_raw()) - ); + let widget_flags = + canvas + .engine_mut() + .text_selection_toggle_attribute(TextAttribute::FontWeight( + piet::FontWeight::BOLD.to_raw(), + )); appwindow.handle_widget_flags(widget_flags, &canvas); - })); + } + )); // Italic - imp.text_italic_button - .connect_clicked(clone!(@weak appwindow => move |_| { + imp.text_italic_button.connect_clicked(clone!( + #[weak] + appwindow, + move |_| { let canvas = appwindow.active_tab_wrapper().canvas(); - let widget_flags = canvas.engine_mut().text_selection_toggle_attribute( - TextAttribute::Style(FontStyle::Italic) - ); + let widget_flags = canvas + .engine_mut() + .text_selection_toggle_attribute(TextAttribute::Style(FontStyle::Italic)); appwindow.handle_widget_flags(widget_flags, &canvas); - })); + } + )); // Underline - imp.text_underline_button - .connect_clicked(clone!(@weak appwindow => move |_| { + imp.text_underline_button.connect_clicked(clone!( + #[weak] + appwindow, + move |_| { let canvas = appwindow.active_tab_wrapper().canvas(); - let widget_flags = canvas.engine_mut().text_selection_toggle_attribute( - TextAttribute::Underline(true) - ); + let widget_flags = canvas + .engine_mut() + .text_selection_toggle_attribute(TextAttribute::Underline(true)); appwindow.handle_widget_flags(widget_flags, &canvas); - })); + } + )); // Strikethrough - imp.text_strikethrough_button - .connect_clicked(clone!(@weak appwindow => move |_| { + imp.text_strikethrough_button.connect_clicked(clone!( + #[weak] + appwindow, + move |_| { let canvas = appwindow.active_tab_wrapper().canvas(); - let widget_flags = canvas.engine_mut().text_selection_toggle_attribute( - TextAttribute::Strikethrough(true) - ); + let widget_flags = canvas + .engine_mut() + .text_selection_toggle_attribute(TextAttribute::Strikethrough(true)); appwindow.handle_widget_flags(widget_flags, &canvas); - })); + } + )); // Alignment - imp.text_align_start_togglebutton.connect_active_notify( - clone!(@weak appwindow => move |togglebutton| { - if !togglebutton.is_active() { - return + imp.text_align_start_togglebutton + .connect_active_notify(clone!( + #[weak] + appwindow, + move |togglebutton| { + if !togglebutton.is_active() { + return; + } + let canvas = appwindow.active_tab_wrapper().canvas(); + canvas + .engine_mut() + .pens_config + .typewriter_config + .text_style + .alignment = TextAlignment::Start; + let widget_flags = canvas.engine_mut().text_selection_change_style(|style| { + style.alignment = TextAlignment::Start + }); + appwindow.handle_widget_flags(widget_flags, &canvas); } - let canvas = appwindow.active_tab_wrapper().canvas(); - canvas.engine_mut().pens_config.typewriter_config.text_style.alignment = TextAlignment::Start; - let widget_flags = canvas.engine_mut().text_selection_change_style(|style| {style.alignment = TextAlignment::Start}); - appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); - - imp.text_align_center_togglebutton.connect_active_notify( - clone!(@weak appwindow => move |togglebutton| { - if !togglebutton.is_active() { - return + )); + + imp.text_align_center_togglebutton + .connect_active_notify(clone!( + #[weak] + appwindow, + move |togglebutton| { + if !togglebutton.is_active() { + return; + } + let canvas = appwindow.active_tab_wrapper().canvas(); + canvas + .engine_mut() + .pens_config + .typewriter_config + .text_style + .alignment = TextAlignment::Center; + let widget_flags = canvas.engine_mut().text_selection_change_style(|style| { + style.alignment = TextAlignment::Center + }); + appwindow.handle_widget_flags(widget_flags, &canvas); } - let canvas = appwindow.active_tab_wrapper().canvas(); - canvas.engine_mut().pens_config.typewriter_config.text_style.alignment = TextAlignment::Center; - let widget_flags = canvas.engine_mut().text_selection_change_style(|style| {style.alignment = TextAlignment::Center}); - appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); - - imp.text_align_end_togglebutton.connect_active_notify( - clone!(@weak appwindow => move |togglebutton| { - if !togglebutton.is_active() { - return + )); + + imp.text_align_end_togglebutton + .connect_active_notify(clone!( + #[weak] + appwindow, + move |togglebutton| { + if !togglebutton.is_active() { + return; + } + let canvas = appwindow.active_tab_wrapper().canvas(); + canvas + .engine_mut() + .pens_config + .typewriter_config + .text_style + .alignment = TextAlignment::End; + let widget_flags = canvas + .engine_mut() + .text_selection_change_style(|style| style.alignment = TextAlignment::End); + appwindow.handle_widget_flags(widget_flags, &canvas); } - let canvas = appwindow.active_tab_wrapper().canvas(); - canvas.engine_mut().pens_config.typewriter_config.text_style.alignment = TextAlignment::End; - let widget_flags = canvas.engine_mut().text_selection_change_style(|style| {style.alignment = TextAlignment::End}); - appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); - - imp.text_align_fill_togglebutton.connect_active_notify( - clone!(@weak appwindow => move |togglebutton| { - if !togglebutton.is_active() { - return + )); + + imp.text_align_fill_togglebutton + .connect_active_notify(clone!( + #[weak] + appwindow, + move |togglebutton| { + if !togglebutton.is_active() { + return; + } + let canvas = appwindow.active_tab_wrapper().canvas(); + canvas + .engine_mut() + .pens_config + .typewriter_config + .text_style + .alignment = TextAlignment::Fill; + let widget_flags = canvas + .engine_mut() + .text_selection_change_style(|style| style.alignment = TextAlignment::Fill); + appwindow.handle_widget_flags(widget_flags, &canvas); } - let canvas = appwindow.active_tab_wrapper().canvas(); - canvas.engine_mut().pens_config.typewriter_config.text_style.alignment = TextAlignment::Fill; - let widget_flags = canvas.engine_mut().text_selection_change_style(|style| {style.alignment = TextAlignment::Fill}); - appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + )); } pub(crate) fn refresh_ui(&self, active_tab: &RnCanvasWrapper) { diff --git a/crates/rnote-ui/src/settingspanel/mod.rs b/crates/rnote-ui/src/settingspanel/mod.rs index f2a3a0923c..7a8a030980 100644 --- a/crates/rnote-ui/src/settingspanel/mod.rs +++ b/crates/rnote-ui/src/settingspanel/mod.rs @@ -136,56 +136,94 @@ mod imp { let obj = self.obj(); self.format_predefined_formats_row - .connect_selected_item_notify(clone!(@weak obj as settings_panel => move |_| { - settings_panel.imp().apply_predefined_format(); - })); - - self.format_orientation_portrait_toggle.connect_toggled( - clone!(@weak obj as settings_panel => move |toggle| { - if toggle.is_active() && settings_panel.format_orientation() != settings_panel.imp().temporary_format.borrow().orientation() { - settings_panel.imp().swap_width_height(); + .connect_selected_item_notify(clone!( + #[weak(rename_to=settings_panel)] + obj, + move |_| { + settings_panel.imp().apply_predefined_format(); } - }), - ); - - self.format_orientation_landscape_toggle.connect_toggled( - clone!(@weak obj as settings_panel => move |toggle| { - if toggle.is_active() && settings_panel.format_orientation() != settings_panel.imp().temporary_format.borrow().orientation() { - settings_panel.imp().swap_width_height(); + )); + + self.format_orientation_portrait_toggle + .connect_toggled(clone!( + #[weak(rename_to=settings_panel)] + obj, + move |toggle| { + if toggle.is_active() + && settings_panel.format_orientation() + != settings_panel.imp().temporary_format.borrow().orientation() + { + settings_panel.imp().swap_width_height(); + } } - }), - ); + )); + + self.format_orientation_landscape_toggle + .connect_toggled(clone!( + #[weak(rename_to=settings_panel)] + obj, + move |toggle| { + if toggle.is_active() + && settings_panel.format_orientation() + != settings_panel.imp().temporary_format.borrow().orientation() + { + settings_panel.imp().swap_width_height(); + } + } + )); self.format_width_unitentry.get().connect_notify_local( Some("value"), - clone!(@weak obj as settings_panel => move |entry, _| { - settings_panel.imp().temporary_format + clone!( + #[weak(rename_to=settings_panel)] + obj, + move |entry, _| { + settings_panel + .imp() + .temporary_format .borrow_mut() .set_width(entry.value_in_px()); settings_panel.imp().update_orientation_toggles(); - }), + } + ), ); self.format_height_unitentry.get().connect_notify_local( Some("value"), - clone!(@weak obj as settings_panel => move |entry, _| { - settings_panel.imp().temporary_format + clone!( + #[weak(rename_to=settings_panel)] + obj, + move |entry, _| { + settings_panel + .imp() + .temporary_format .borrow_mut() .set_height(entry.value_in_px()); settings_panel.imp().update_orientation_toggles(); - }), + } + ), ); - self.format_dpi_adj.connect_value_changed( - clone!(@weak obj as settings_panel => move |adj| { + self.format_dpi_adj.connect_value_changed(clone!( + #[weak(rename_to=settings_panel)] + obj, + move |adj| { let dpi = adj.value(); - settings_panel.imp().format_width_unitentry.set_dpi_keep_value(dpi); - settings_panel.imp().format_height_unitentry.set_dpi_keep_value(dpi); - settings_panel.imp().temporary_format + settings_panel + .imp() + .format_width_unitentry + .set_dpi_keep_value(dpi); + settings_panel + .imp() + .format_height_unitentry + .set_dpi_keep_value(dpi); + settings_panel + .imp() + .temporary_format .borrow_mut() .set_dpi(adj.value()); - }), - ); + } + )); } fn dispose(&self) { @@ -501,11 +539,14 @@ impl RnSettingsPanel { // set on init set_overlays_margins(appwindow, imp.general_show_scrollbars_row.is_active()); // and on change - imp.general_show_scrollbars_row.connect_active_notify( - clone!(@weak appwindow => move |row| { + imp.general_show_scrollbars_row + .connect_active_notify(clone!( + #[weak] + appwindow, + move |row| { set_overlays_margins(&appwindow, row.is_active()); - }), - ); + } + )); imp.general_optimize_epd_row .bind_property( @@ -516,11 +557,17 @@ impl RnSettingsPanel { .sync_create() .build(); - imp.general_optimize_epd_row.connect_active_notify( - clone!(@weak appwindow => move |row| { - appwindow.active_tab_wrapper().canvas().engine_mut().set_optimize_epd(row.is_active()); - }), - ); + imp.general_optimize_epd_row.connect_active_notify(clone!( + #[weak] + appwindow, + move |row| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .set_optimize_epd(row.is_active()); + } + )); // Regular cursor picker imp.general_regular_cursor_picker.set_list( @@ -564,75 +611,112 @@ impl RnSettingsPanel { .sync_create() .build(); - imp.general_inertial_scrolling_row.connect_active_notify( - clone!(@weak self as settingspanel, @weak appwindow => move |row| { - if !row.is_active() { - appwindow.overlays().dispatch_toast_text_singleton( - &gettext("Application restart is required"), - None, - &mut settingspanel.imp().app_restart_toast_singleton.borrow_mut() - ); + imp.general_inertial_scrolling_row + .connect_active_notify(clone!( + #[weak(rename_to=settingspanel)] + self, + #[weak] + appwindow, + move |row| { + if !row.is_active() { + appwindow.overlays().dispatch_toast_text_singleton( + &gettext("Application restart is required"), + None, + &mut settingspanel.imp().app_restart_toast_singleton.borrow_mut(), + ); + } } - }), - ); + )); } fn setup_format(&self, appwindow: &RnAppWindow) { let imp = self.imp(); // revert format - imp.format_revert_button.get().connect_clicked( - clone!(@weak self as settings_panel, @weak appwindow => move |_format_revert_button| { + imp.format_revert_button.get().connect_clicked(clone!( + #[weak(rename_to=settings_panel)] + self, + #[weak] + appwindow, + move |_format_revert_button| { settings_panel.revert_format(&appwindow); - }), - ); + } + )); // Apply format - imp.format_apply_button.get().connect_clicked( - clone!(@weak self as settingspanel, @weak appwindow => move |_| { + imp.format_apply_button.get().connect_clicked(clone!( + #[weak(rename_to=settingspanel)] + self, + #[weak] + appwindow, + move |_| { settingspanel.apply_format(&appwindow); - }), - ); + } + )); } fn setup_doc(&self, appwindow: &RnAppWindow) { let imp = self.imp(); - imp.doc_format_border_color_button.connect_rgba_notify(clone!(@weak self as settingspanel, @weak appwindow => move |button| { - let format_border_color = button.rgba().into_compose_color(); - let canvas = appwindow.active_tab_wrapper().canvas(); + imp.doc_format_border_color_button + .connect_rgba_notify(clone!( + #[weak(rename_to=settingspanel)] + self, + #[weak] + appwindow, + move |button| { + let format_border_color = button.rgba().into_compose_color(); + let canvas = appwindow.active_tab_wrapper().canvas(); - // Because the format border color is applied immediately to the engine, - // we need to update the temporary format too. - settingspanel.imp().temporary_format.borrow_mut().border_color = format_border_color; - let current_color = canvas.engine_ref().document.format.border_color; + // Because the format border color is applied immediately to the engine, + // we need to update the temporary format too. + settingspanel + .imp() + .temporary_format + .borrow_mut() + .border_color = format_border_color; + let current_color = canvas.engine_ref().document.format.border_color; - if !current_color.approx_eq_f32(format_border_color) { - canvas.engine_mut().document.format.border_color = format_border_color; - let mut widget_flags = canvas.engine_mut().update_rendering_current_viewport(); - widget_flags.store_modified = true; - appwindow.handle_widget_flags(widget_flags, &canvas); - } - })); + if !current_color.approx_eq_f32(format_border_color) { + canvas.engine_mut().document.format.border_color = format_border_color; + let mut widget_flags = + canvas.engine_mut().update_rendering_current_viewport(); + widget_flags.store_modified = true; + appwindow.handle_widget_flags(widget_flags, &canvas); + } + } + )); - imp.doc_background_color_button.connect_rgba_notify( - clone!(@weak appwindow => move |button| { + imp.doc_background_color_button.connect_rgba_notify(clone!( + #[weak] + appwindow, + move |button| { let background_color = button.rgba().into_compose_color(); let canvas = appwindow.active_tab_wrapper().canvas(); - if !canvas.engine_ref().document.background.color.approx_eq_f32(background_color) { + if !canvas + .engine_ref() + .document + .background + .color + .approx_eq_f32(background_color) + { canvas.engine_mut().document.background.color = background_color; let mut widget_flags = canvas.engine_mut().background_rendering_regenerate(); widget_flags.store_modified = true; appwindow.handle_widget_flags(widget_flags, &canvas); } - }), - ); + } + )); imp.doc_document_layout_row .get() - .connect_selected_item_notify( - clone!(@weak self as settings_panel, @weak appwindow => move |_| { + .connect_selected_item_notify(clone!( + #[weak(rename_to=settings_panel)] + self, + #[weak] + appwindow, + move |_| { let document_layout = settings_panel.document_layout(); let canvas = appwindow.active_tab_wrapper().canvas(); @@ -647,115 +731,208 @@ impl RnSettingsPanel { widget_flags.store_modified = true; appwindow.handle_widget_flags(widget_flags, &canvas); } - }), - ); + } + )); - imp.doc_background_patterns_row.get().connect_selected_item_notify(clone!(@weak self as settings_panel, @weak appwindow => move |_| { - let pattern = settings_panel.background_pattern(); - let canvas = appwindow.active_tab_wrapper().canvas(); - - match pattern { - PatternStyle::None => { - settings_panel.imp().doc_background_pattern_width_unitentry.set_sensitive(false); - settings_panel.imp().doc_background_pattern_height_unitentry.set_sensitive(false); - }, - PatternStyle::Lines => { - settings_panel.imp().doc_background_pattern_width_unitentry.set_sensitive(false); - settings_panel.imp().doc_background_pattern_height_unitentry.set_sensitive(true); - }, - PatternStyle::Grid => { - settings_panel.imp().doc_background_pattern_width_unitentry.set_sensitive(true); - settings_panel.imp().doc_background_pattern_height_unitentry.set_sensitive(true); - }, - PatternStyle::Dots => { - settings_panel.imp().doc_background_pattern_width_unitentry.set_sensitive(true); - settings_panel.imp().doc_background_pattern_height_unitentry.set_sensitive(true); - }, - PatternStyle::IsometricGrid => { - settings_panel.imp().doc_background_pattern_width_unitentry.set_sensitive(false); - settings_panel.imp().doc_background_pattern_height_unitentry.set_sensitive(true); - }, - PatternStyle::IsometricDots => { - settings_panel.imp().doc_background_pattern_width_unitentry.set_sensitive(false); - settings_panel.imp().doc_background_pattern_height_unitentry.set_sensitive(true); - }, - } + imp.doc_background_patterns_row + .get() + .connect_selected_item_notify(clone!( + #[weak(rename_to=settings_panel)] + self, + #[weak] + appwindow, + move |_| { + let pattern = settings_panel.background_pattern(); + let canvas = appwindow.active_tab_wrapper().canvas(); - if canvas.engine_ref().document.background.pattern != pattern { - canvas.engine_mut().document.background.pattern = pattern; - let mut widget_flags = canvas.engine_mut().background_rendering_regenerate(); - widget_flags.store_modified = true; - appwindow.handle_widget_flags(widget_flags, &canvas); - } - })); + match pattern { + PatternStyle::None => { + settings_panel + .imp() + .doc_background_pattern_width_unitentry + .set_sensitive(false); + settings_panel + .imp() + .doc_background_pattern_height_unitentry + .set_sensitive(false); + } + PatternStyle::Lines => { + settings_panel + .imp() + .doc_background_pattern_width_unitentry + .set_sensitive(false); + settings_panel + .imp() + .doc_background_pattern_height_unitentry + .set_sensitive(true); + } + PatternStyle::Grid => { + settings_panel + .imp() + .doc_background_pattern_width_unitentry + .set_sensitive(true); + settings_panel + .imp() + .doc_background_pattern_height_unitentry + .set_sensitive(true); + } + PatternStyle::Dots => { + settings_panel + .imp() + .doc_background_pattern_width_unitentry + .set_sensitive(true); + settings_panel + .imp() + .doc_background_pattern_height_unitentry + .set_sensitive(true); + } + PatternStyle::IsometricGrid => { + settings_panel + .imp() + .doc_background_pattern_width_unitentry + .set_sensitive(false); + settings_panel + .imp() + .doc_background_pattern_height_unitentry + .set_sensitive(true); + } + PatternStyle::IsometricDots => { + settings_panel + .imp() + .doc_background_pattern_width_unitentry + .set_sensitive(false); + settings_panel + .imp() + .doc_background_pattern_height_unitentry + .set_sensitive(true); + } + } - imp.doc_background_pattern_color_button.connect_rgba_notify( - clone!(@weak appwindow => move |button| { - let canvas = appwindow.active_tab_wrapper().canvas(); - let pattern_color = button.rgba().into_compose_color(); + if canvas.engine_ref().document.background.pattern != pattern { + canvas.engine_mut().document.background.pattern = pattern; + let mut widget_flags = + canvas.engine_mut().background_rendering_regenerate(); + widget_flags.store_modified = true; + appwindow.handle_widget_flags(widget_flags, &canvas); + } + } + )); - if !canvas.engine_ref().document.background.pattern_color.approx_eq_f32(pattern_color) { - canvas.engine_mut().document.background.pattern_color = pattern_color; - let mut widget_flags = canvas.engine_mut().background_rendering_regenerate(); - widget_flags.store_modified = true; - appwindow.handle_widget_flags(widget_flags, &canvas); + imp.doc_background_pattern_color_button + .connect_rgba_notify(clone!( + #[weak] + appwindow, + move |button| { + let canvas = appwindow.active_tab_wrapper().canvas(); + let pattern_color = button.rgba().into_compose_color(); + + if !canvas + .engine_ref() + .document + .background + .pattern_color + .approx_eq_f32(pattern_color) + { + canvas.engine_mut().document.background.pattern_color = pattern_color; + let mut widget_flags = + canvas.engine_mut().background_rendering_regenerate(); + widget_flags.store_modified = true; + appwindow.handle_widget_flags(widget_flags, &canvas); + } } - }), - ); + )); imp.doc_background_pattern_width_unitentry .get() .connect_notify_local( Some("value"), - clone!(@weak self as settings_panel, @weak appwindow => move |unit_entry, _| { + clone!( + #[weak] + appwindow, + move |unit_entry, _| { let canvas = appwindow.active_tab_wrapper().canvas(); let mut pattern_size = canvas.engine_ref().document.background.pattern_size; pattern_size[0] = unit_entry.value_in_px(); - if !canvas.engine_ref().document.background.pattern_size.approx_eq(&pattern_size) { + if !canvas + .engine_ref() + .document + .background + .pattern_size + .approx_eq(&pattern_size) + { canvas.engine_mut().document.background.pattern_size = pattern_size; - let mut widget_flags = canvas.engine_mut().background_rendering_regenerate(); + let mut widget_flags = + canvas.engine_mut().background_rendering_regenerate(); widget_flags.store_modified = true; appwindow.handle_widget_flags(widget_flags, &canvas); } - }), + } + ), ); imp.doc_background_pattern_height_unitentry .get() .connect_notify_local( Some("value"), - clone!(@weak self as settings_panel, @weak appwindow => move |unit_entry, _| { + clone!( + #[weak] + appwindow, + move |unit_entry, _| { let canvas = appwindow.active_tab_wrapper().canvas(); let mut pattern_size = canvas.engine_ref().document.background.pattern_size; pattern_size[1] = unit_entry.value_in_px(); - if !canvas.engine_ref().document.background.pattern_size.approx_eq(&pattern_size) { + if !canvas + .engine_ref() + .document + .background + .pattern_size + .approx_eq(&pattern_size) + { canvas.engine_mut().document.background.pattern_size = pattern_size; - let mut widget_flags = canvas.engine_mut().background_rendering_regenerate(); + let mut widget_flags = + canvas.engine_mut().background_rendering_regenerate(); widget_flags.store_modified = true; appwindow.handle_widget_flags(widget_flags, &canvas); } - }), + } + ), ); - imp.background_pattern_invert_color_button.get().connect_clicked( - clone!(@weak self as settings_panel, @weak appwindow => move |_| { + imp.background_pattern_invert_color_button + .get() + .connect_clicked(clone!( + #[weak] + appwindow, + move |_| { let canvas = appwindow.active_tab_wrapper().canvas(); let mut widget_flags = { let mut engine = canvas.engine_mut(); - engine.document.background.color = engine.document.background.color.to_inverted_brightness_color(); - engine.document.background.pattern_color = engine.document.background.pattern_color.to_inverted_brightness_color(); - engine.document.format.border_color = engine.document.format.border_color.to_inverted_brightness_color(); + engine.document.background.color = engine + .document + .background + .color + .to_inverted_brightness_color(); + engine.document.background.pattern_color = engine + .document + .background + .pattern_color + .to_inverted_brightness_color(); + engine.document.format.border_color = engine + .document + .format + .border_color + .to_inverted_brightness_color(); engine.background_rendering_regenerate() }; widget_flags.refresh_ui = true; widget_flags.store_modified = true; appwindow.handle_widget_flags(widget_flags, &canvas); - }), - ); + } + )); } fn setup_shortcuts(&self, appwindow: &RnAppWindow) { @@ -773,59 +950,213 @@ impl RnSettingsPanel { let penshortcut_drawing_pad_button_2 = imp.penshortcut_drawing_pad_button_2.get(); let penshortcut_drawing_pad_button_3 = imp.penshortcut_drawing_pad_button_3.get(); - imp.penshortcut_stylus_button_primary_row.connect_local("action-changed", false, clone!(@weak penshortcut_stylus_button_primary_row, @weak appwindow => @default-return None, move |_values| { - let action = penshortcut_stylus_button_primary_row.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::StylusPrimaryButton, action); - None - })); - - imp.penshortcut_stylus_button_secondary_row.connect_local("action-changed", false, clone!(@weak penshortcut_stylus_button_secondary_row, @weak appwindow => @default-return None, move |_values| { - let action = penshortcut_stylus_button_secondary_row.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::StylusSecondaryButton, action); - None - })); - - imp.penshortcut_mouse_button_secondary_row.connect_local("action-changed", false, clone!(@weak penshortcut_mouse_button_secondary_row, @weak appwindow => @default-return None, move |_values| { - let action = penshortcut_mouse_button_secondary_row.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::MouseSecondaryButton, action); - None - })); - - imp.penshortcut_touch_two_finger_long_press_row.connect_local("action-changed", false, clone!(@weak penshortcut_touch_two_finger_long_press_row, @weak appwindow => @default-return None, move |_values| { - let action = penshortcut_touch_two_finger_long_press_row.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::TouchTwoFingerLongPress, action); - None - })); - - imp.penshortcut_keyboard_ctrl_space_row.connect_local("action-changed", false, clone!(@weak penshortcut_keyboard_ctrl_space_row, @weak appwindow => @default-return None, move |_values| { - let action = penshortcut_keyboard_ctrl_space_row.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::KeyboardCtrlSpace, action); - None - })); - - imp.penshortcut_drawing_pad_button_0.connect_local("action-changed", false, clone!(@weak penshortcut_drawing_pad_button_0, @weak appwindow => @default-return None, move |_values| { - let action = penshortcut_drawing_pad_button_0.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::DrawingPadButton0, action); - None - })); - - imp.penshortcut_drawing_pad_button_1.connect_local("action-changed", false, clone!(@weak penshortcut_drawing_pad_button_1, @weak appwindow => @default-return None, move |_values| { - let action = penshortcut_drawing_pad_button_1.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::DrawingPadButton1, action); - None - })); - - imp.penshortcut_drawing_pad_button_2.connect_local("action-changed", false, clone!(@weak penshortcut_drawing_pad_button_2, @weak appwindow => @default-return None, move |_values| { - let action = penshortcut_drawing_pad_button_2.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::DrawingPadButton2, action); - None - })); - - imp.penshortcut_drawing_pad_button_3.connect_local("action-changed", false, clone!(@weak penshortcut_drawing_pad_button_3, @weak appwindow => @default-return None, move |_values| { - let action = penshortcut_drawing_pad_button_3.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::DrawingPadButton3, action); - None - })); + imp.penshortcut_stylus_button_primary_row.connect_local( + "action-changed", + false, + clone!( + #[weak] + penshortcut_stylus_button_primary_row, + #[weak] + appwindow, + #[upgrade_or] + None, + move |_values| { + let action = penshortcut_stylus_button_primary_row.action(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .register_shortcut(ShortcutKey::StylusPrimaryButton, action); + None + } + ), + ); + + imp.penshortcut_stylus_button_secondary_row.connect_local( + "action-changed", + false, + clone!( + #[weak] + penshortcut_stylus_button_secondary_row, + #[weak] + appwindow, + #[upgrade_or] + None, + move |_values| { + let action = penshortcut_stylus_button_secondary_row.action(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .register_shortcut(ShortcutKey::StylusSecondaryButton, action); + None + } + ), + ); + + imp.penshortcut_mouse_button_secondary_row.connect_local( + "action-changed", + false, + clone!( + #[weak] + penshortcut_mouse_button_secondary_row, + #[weak] + appwindow, + #[upgrade_or] + None, + move |_values| { + let action = penshortcut_mouse_button_secondary_row.action(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .register_shortcut(ShortcutKey::MouseSecondaryButton, action); + None + } + ), + ); + + imp.penshortcut_touch_two_finger_long_press_row + .connect_local( + "action-changed", + false, + clone!( + #[weak] + penshortcut_touch_two_finger_long_press_row, + #[weak] + appwindow, + #[upgrade_or] + None, + move |_values| { + let action = penshortcut_touch_two_finger_long_press_row.action(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .register_shortcut(ShortcutKey::TouchTwoFingerLongPress, action); + None + } + ), + ); + + imp.penshortcut_keyboard_ctrl_space_row.connect_local( + "action-changed", + false, + clone!( + #[weak] + penshortcut_keyboard_ctrl_space_row, + #[weak] + appwindow, + #[upgrade_or] + None, + move |_values| { + let action = penshortcut_keyboard_ctrl_space_row.action(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .register_shortcut(ShortcutKey::KeyboardCtrlSpace, action); + None + } + ), + ); + + imp.penshortcut_drawing_pad_button_0.connect_local( + "action-changed", + false, + clone!( + #[weak] + penshortcut_drawing_pad_button_0, + #[weak] + appwindow, + #[upgrade_or] + None, + move |_values| { + let action = penshortcut_drawing_pad_button_0.action(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .register_shortcut(ShortcutKey::DrawingPadButton0, action); + None + } + ), + ); + + imp.penshortcut_drawing_pad_button_1.connect_local( + "action-changed", + false, + clone!( + #[weak] + penshortcut_drawing_pad_button_1, + #[weak] + appwindow, + #[upgrade_or] + None, + move |_values| { + let action = penshortcut_drawing_pad_button_1.action(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .register_shortcut(ShortcutKey::DrawingPadButton1, action); + None + } + ), + ); + + imp.penshortcut_drawing_pad_button_2.connect_local( + "action-changed", + false, + clone!( + #[weak] + penshortcut_drawing_pad_button_2, + #[weak] + appwindow, + #[upgrade_or] + None, + move |_values| { + let action = penshortcut_drawing_pad_button_2.action(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .register_shortcut(ShortcutKey::DrawingPadButton2, action); + None + } + ), + ); + + imp.penshortcut_drawing_pad_button_3.connect_local( + "action-changed", + false, + clone!( + #[weak] + penshortcut_drawing_pad_button_3, + #[weak] + appwindow, + #[upgrade_or] + None, + move |_values| { + let action = penshortcut_drawing_pad_button_3.action(); + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .register_shortcut(ShortcutKey::DrawingPadButton3, action); + None + } + ), + ); } fn revert_format(&self, appwindow: &RnAppWindow) { diff --git a/crates/rnote-ui/src/settingspanel/penshortcutrow.rs b/crates/rnote-ui/src/settingspanel/penshortcutrow.rs index ad8b447f91..7cbebd22c4 100644 --- a/crates/rnote-ui/src/settingspanel/penshortcutrow.rs +++ b/crates/rnote-ui/src/settingspanel/penshortcutrow.rs @@ -77,24 +77,32 @@ mod imp { row.emit_by_name::<()>("action-changed", &[]); }); - self.mode_dropdown.get().connect_selected_notify( - clone!(@weak obj as penshortcutrow => move |_| { + self.mode_dropdown.get().connect_selected_notify(clone!( + #[weak(rename_to=penshortcutrow)] + obj, + move |_| { match &mut *penshortcutrow.imp().action.borrow_mut() { ShortcutAction::ChangePenStyle { mode, .. } => { *mode = penshortcutrow.shortcut_mode(); } } penshortcutrow.emit_by_name::<()>("action-changed", &[]); - }), - ); + } + )); obj.connect_local( "action-changed", false, - clone!(@weak obj as penshortcutrow => @default-return None, move |_values| { - penshortcutrow.update_ui(); - None - }), + clone!( + #[weak(rename_to=penshortcutrow)] + obj, + #[upgrade_or] + None, + move |_values| { + penshortcutrow.update_ui(); + None + } + ), ); } diff --git a/crates/rnote-ui/src/sidebar.rs b/crates/rnote-ui/src/sidebar.rs index b6cfd880c4..d435a95b0e 100644 --- a/crates/rnote-ui/src/sidebar.rs +++ b/crates/rnote-ui/src/sidebar.rs @@ -109,13 +109,19 @@ impl RnSidebar { imp.workspacebrowser.get().init(appwindow); imp.settings_panel.get().init(appwindow); - imp.left_close_button - .connect_clicked(clone!(@weak appwindow => move |_| { + imp.left_close_button.connect_clicked(clone!( + #[weak] + appwindow, + move |_| { appwindow.split_view().set_show_sidebar(false); - })); - imp.right_close_button - .connect_clicked(clone!(@weak appwindow => move |_| { + } + )); + imp.right_close_button.connect_clicked(clone!( + #[weak] + appwindow, + move |_| { appwindow.split_view().set_show_sidebar(false); - })); + } + )); } } diff --git a/crates/rnote-ui/src/strokecontentpaintable.rs b/crates/rnote-ui/src/strokecontentpaintable.rs index c305f325bc..7b3659db64 100644 --- a/crates/rnote-ui/src/strokecontentpaintable.rs +++ b/crates/rnote-ui/src/strokecontentpaintable.rs @@ -142,22 +142,32 @@ mod imp { let (tx, mut rx) = futures::channel::mpsc::unbounded::>(); self.paint_task_tx.set(tx).unwrap(); - let handler = glib::spawn_future_local(clone!(@weak obj as paintable => async move { - while let Some(res) = rx.next().await { - match res { - Ok(image) => { - paintable.imp().replace_paint_cache(image); - if paintable.imp().paint_tasks_in_progress.get() <= 1 { - paintable.imp().emit_repaint_in_progress(false); + let handler = glib::spawn_future_local(clone!( + #[weak(rename_to=paintable)] + obj, + async move { + while let Some(res) = rx.next().await { + match res { + Ok(image) => { + paintable.imp().replace_paint_cache(image); + if paintable.imp().paint_tasks_in_progress.get() <= 1 { + paintable.imp().emit_repaint_in_progress(false); + } + paintable.imp().paint_tasks_in_progress.set( + paintable + .imp() + .paint_tasks_in_progress + .get() + .saturating_sub(1), + ); + } + Err(e) => { + error!("StrokeContentPaintable repainting cache image in task failed, Err: {e:?}"); } - paintable.imp().paint_tasks_in_progress.set(paintable.imp().paint_tasks_in_progress.get().saturating_sub(1)); - } - Err(e) => { - error!("StrokeContentPaintable repainting cache image in task failed, Err: {e:?}"); } } } - })); + )); self.paint_task_handler.replace(Some(handler)); } diff --git a/crates/rnote-ui/src/strokecontentpreview.rs b/crates/rnote-ui/src/strokecontentpreview.rs index f00aad13b8..62ca723f5d 100644 --- a/crates/rnote-ui/src/strokecontentpreview.rs +++ b/crates/rnote-ui/src/strokecontentpreview.rs @@ -66,54 +66,78 @@ mod imp { self.paintable.connect_local( "repaint-in-progress", false, - clone!(@weak obj as strokecontentpreview => @default-return None, move |vals| { - let in_progress = vals[1].get::().unwrap(); - let current_page = strokecontentpreview.current_page(); - let n_pages = strokecontentpreview.n_pages(); - - if in_progress { - strokecontentpreview.progressbar_start_pulsing(); - strokecontentpreview.imp().prev_page_button.set_sensitive(false); - strokecontentpreview.imp().next_page_button.set_sensitive(false); - } else { - strokecontentpreview.progressbar_finish(); - strokecontentpreview.imp().prev_page_button.set_sensitive(current_page > 0); - strokecontentpreview.imp().next_page_button - .set_sensitive(current_page < n_pages.saturating_sub(1)); + clone!( + #[weak(rename_to=strokecontentpreview)] + obj, + #[upgrade_or] + None, + move |vals| { + let in_progress = vals[1].get::().unwrap(); + let current_page = strokecontentpreview.current_page(); + let n_pages = strokecontentpreview.n_pages(); + + if in_progress { + strokecontentpreview.progressbar_start_pulsing(); + strokecontentpreview + .imp() + .prev_page_button + .set_sensitive(false); + strokecontentpreview + .imp() + .next_page_button + .set_sensitive(false); + } else { + strokecontentpreview.progressbar_finish(); + strokecontentpreview + .imp() + .prev_page_button + .set_sensitive(current_page > 0); + strokecontentpreview + .imp() + .next_page_button + .set_sensitive(current_page < n_pages.saturating_sub(1)); + } + None } - None - }), + ), ); - self.page_entry.connect_changed( - clone!(@weak obj as stroke_content_preview => move |entry| { - let n_pages = stroke_content_preview.n_pages(); + self.page_entry.connect_changed(clone!( + #[weak(rename_to=strokecontentpreview)] + obj, + move |entry| { + let n_pages = strokecontentpreview.n_pages(); match parse_page_text(&entry.text(), n_pages) { Ok(page) => { entry.remove_css_class("error"); - stroke_content_preview.set_current_page(page); + strokecontentpreview.set_current_page(page); } _ => { entry.add_css_class("error"); } } - }), - ); + } + )); - self.prev_page_button.connect_clicked( - clone!(@weak obj as strokecontentpreview => move |_| { + self.prev_page_button.connect_clicked(clone!( + #[weak(rename_to=strokecontentpreview)] + obj, + move |_| { let current_page = strokecontentpreview.current_page(); strokecontentpreview.set_current_page(current_page.saturating_sub(1)); - }), - ); + } + )); - self.next_page_button.connect_clicked( - clone!(@weak obj as strokecontentpreview => move |_| { + self.next_page_button.connect_clicked(clone!( + #[weak(rename_to=strokecontentpreview)] + obj, + move |_| { let current_page = strokecontentpreview.current_page(); let n_pages = strokecontentpreview.n_pages(); - strokecontentpreview.set_current_page(current_page.saturating_add(1).min(n_pages - 1)); - }), - ); + strokecontentpreview + .set_current_page(current_page.saturating_add(1).min(n_pages - 1)); + } + )); } fn dispose(&self) { @@ -281,14 +305,24 @@ impl RnStrokeContentPreview { pub(crate) fn progressbar_start_pulsing(&self) { const PULSE_INTERVAL: std::time::Duration = std::time::Duration::from_millis(100); - if let Some(src) = self.imp().progresspulse_id.replace(Some(glib::source::timeout_add_local( - PULSE_INTERVAL, - clone!(@weak self as strokecontentpreview => @default-return glib::ControlFlow::Break, move || { - strokecontentpreview.imp().progressbar.pulse(); - - glib::ControlFlow::Continue - })), - )) { + if let Some(src) = + self.imp() + .progresspulse_id + .replace(Some(glib::source::timeout_add_local( + PULSE_INTERVAL, + clone!( + #[weak(rename_to=strokecontentpreview)] + self, + #[upgrade_or] + glib::ControlFlow::Break, + move || { + strokecontentpreview.imp().progressbar.pulse(); + + glib::ControlFlow::Continue + } + ), + ))) + { src.remove(); } } @@ -301,9 +335,13 @@ impl RnStrokeContentPreview { self.imp().progressbar.set_fraction(1.); glib::source::timeout_add_local_once( FINISH_TIMEOUT, - clone!(@weak self as strokecontentpreview => move || { - strokecontentpreview.imp().progressbar.set_fraction(0.); - }), + clone!( + #[weak(rename_to=strokecontentpreview)] + self, + move || { + strokecontentpreview.imp().progressbar.set_fraction(0.); + } + ), ); } diff --git a/crates/rnote-ui/src/strokewidthpicker/mod.rs b/crates/rnote-ui/src/strokewidthpicker/mod.rs index 4779436539..1581de7e49 100644 --- a/crates/rnote-ui/src/strokewidthpicker/mod.rs +++ b/crates/rnote-ui/src/strokewidthpicker/mod.rs @@ -94,42 +94,50 @@ mod imp { self.setter_2.set_stroke_width(8.0); self.setter_3.set_stroke_width(16.0); - self.setter_1.connect_active_notify( - clone!(@weak obj as strokewidthpicker => move |setter| { + self.setter_1.connect_active_notify(clone!( + #[weak(rename_to=strokewidthpicker)] + obj, + move |setter| { if setter.is_active() { strokewidthpicker.setter_2().set_active(false); strokewidthpicker.setter_3().set_active(false); // Must come after setting the other toggles inactive strokewidthpicker.set_stroke_width(setter.stroke_width()); } - }), - ); + } + )); - self.setter_2.connect_active_notify( - clone!(@weak obj as strokewidthpicker => move |setter| { + self.setter_2.connect_active_notify(clone!( + #[weak(rename_to=strokewidthpicker)] + obj, + move |setter| { if setter.is_active() { strokewidthpicker.setter_1().set_active(false); strokewidthpicker.setter_3().set_active(false); strokewidthpicker.set_stroke_width(setter.stroke_width()); } - }), - ); + } + )); - self.setter_3.connect_active_notify( - clone!(@weak obj as strokewidthpicker => move |setter| { + self.setter_3.connect_active_notify(clone!( + #[weak(rename_to=strokewidthpicker)] + obj, + move |setter| { if setter.is_active() { strokewidthpicker.setter_1().set_active(false); strokewidthpicker.setter_2().set_active(false); strokewidthpicker.set_stroke_width(setter.stroke_width()); } - }), - ); + } + )); - self.spinbutton.connect_value_changed( - clone!(@weak obj as strokewidthpicker => move |spinbutton| { + self.spinbutton.connect_value_changed(clone!( + #[weak(rename_to=strokewidthpicker)] + obj, + move |spinbutton| { strokewidthpicker.set_active_setter_stroke_width(spinbutton.value()); - }), - ); + } + )); } fn dispose(&self) { diff --git a/crates/rnote-ui/src/unitentry.rs b/crates/rnote-ui/src/unitentry.rs index 24740672b3..3ff1bfef3d 100644 --- a/crates/rnote-ui/src/unitentry.rs +++ b/crates/rnote-ui/src/unitentry.rs @@ -91,11 +91,13 @@ mod imp { .set_selected(unit_entry.unit().to_u32().unwrap()); }); - self.unit_dropdown.get().connect_selected_notify( - clone!(@weak obj as unit_entry => move |unit_dropdown| { + self.unit_dropdown.get().connect_selected_notify(clone!( + #[weak(rename_to=unit_entry)] + obj, + move |unit_dropdown| { unit_entry.set_unit(MeasureUnit::try_from(unit_dropdown.selected()).unwrap()); - }), - ); + } + )); } fn dispose(&self) { diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/actions/duplicate.rs b/crates/rnote-ui/src/workspacebrowser/filerow/actions/duplicate.rs index 055ff0ea50..fcd99e010b 100644 --- a/crates/rnote-ui/src/workspacebrowser/filerow/actions/duplicate.rs +++ b/crates/rnote-ui/src/workspacebrowser/filerow/actions/duplicate.rs @@ -30,8 +30,8 @@ static DUP_REGEX: Lazy = Lazy::new(|| { pub(crate) fn duplicate(filerow: &RnFileRow, appwindow: &RnAppWindow) -> gio::SimpleAction { let action = gio::SimpleAction::new("duplicate", None); - action.connect_activate(clone!(@weak filerow, @weak appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak filerow, @weak appwindow => async move { + action.connect_activate(clone!(#[weak] filerow, #[weak] appwindow , move |_, _| { + glib::spawn_future_local(clone!(#[weak] filerow, #[weak] appwindow , async move { let Some(current_path) = filerow.current_file().and_then(|f| f.path()) else { appwindow.overlays().dispatch_toast_error(&gettext("Can't duplicate an unsaved document")); debug!("Could not duplicate file, current file is None."); diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/actions/open.rs b/crates/rnote-ui/src/workspacebrowser/filerow/actions/open.rs index 2cf81b840c..13dbaf72d9 100644 --- a/crates/rnote-ui/src/workspacebrowser/filerow/actions/open.rs +++ b/crates/rnote-ui/src/workspacebrowser/filerow/actions/open.rs @@ -6,13 +6,25 @@ use gtk4::{gio, glib, glib::clone}; /// Create a new `open` action. pub(crate) fn open(filerow: &RnFileRow, appwindow: &RnAppWindow) -> gio::SimpleAction { let action = gio::SimpleAction::new("open-file", None); - action.connect_activate(clone!(@weak filerow, @weak appwindow => move |_, _| { - let Some(current_file) = filerow.current_file() else { - return - }; - glib::spawn_future_local(clone!(@weak appwindow => async move { - appwindow.open_file_w_dialogs(current_file, None, true).await; - })); - })); + action.connect_activate(clone!( + #[weak] + filerow, + #[weak] + appwindow, + move |_, _| { + let Some(current_file) = filerow.current_file() else { + return; + }; + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + appwindow + .open_file_w_dialogs(current_file, None, true) + .await; + } + )); + } + )); action } diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_default_app.rs b/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_default_app.rs index 7940e7a2c7..f2691ac197 100644 --- a/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_default_app.rs +++ b/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_default_app.rs @@ -11,15 +11,25 @@ pub(crate) fn open_in_default_app( appwindow: &RnAppWindow, ) -> gio::SimpleAction { let action = gio::SimpleAction::new("open-in-default-app", None); - action.connect_activate(clone!(@weak filerow, @weak appwindow => move |_, _| { + action.connect_activate(clone!( + #[weak] + filerow, + #[weak] + appwindow, + move |_, _| { let Some(current_file) = filerow.current_file() else { return; }; - if let Err(e) = open::that(current_file.uri()) { - appwindow.overlays().dispatch_toast_error(&gettext("Open the file in the default app failed")); - debug!("Opening file {} with default app failed, Err: {e:?}", current_file.uri()); + if let Err(e) = open::that(current_file.uri()) { + appwindow + .overlays() + .dispatch_toast_error(&gettext("Open the file in the default app failed")); + debug!( + "Opening file {} with default app failed, Err: {e:?}", + current_file.uri() + ); } - }), - ); + } + )); action } diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/actions/rename.rs b/crates/rnote-ui/src/workspacebrowser/filerow/actions/rename.rs index 113d52aa4c..535501222b 100644 --- a/crates/rnote-ui/src/workspacebrowser/filerow/actions/rename.rs +++ b/crates/rnote-ui/src/workspacebrowser/filerow/actions/rename.rs @@ -9,54 +9,92 @@ use tracing::{debug, error}; /// Create a new `rename` action. pub(crate) fn rename(filerow: &RnFileRow, appwindow: &RnAppWindow) -> gio::SimpleAction { let action = gio::SimpleAction::new("rename-file", None); - action.connect_activate(clone!(@weak filerow, @weak appwindow => move |_, _| { - let Some(current_file) = filerow.current_file() else { - return; - }; - let Some(current_file_path) = current_file.path() else { - return; - }; - let Some(parent_path) = current_file_path.parent().map(|p| p.to_path_buf()) else { - return; - }; - let entry = create_entry(¤t_file_path); - let label = create_label(); - let (apply_button, popover) = widgethelper::create_entry_dialog(&entry, &label); - filerow.menubutton_box().append(&popover); + action.connect_activate(clone!( + #[weak] + filerow, + #[weak] + appwindow, + move |_, _| { + let Some(current_file) = filerow.current_file() else { + return; + }; + let Some(current_file_path) = current_file.path() else { + return; + }; + let Some(parent_path) = current_file_path.parent().map(|p| p.to_path_buf()) else { + return; + }; + let entry = create_entry(¤t_file_path); + let label = create_label(); + let (apply_button, popover) = widgethelper::create_entry_dialog(&entry, &label); + filerow.menubutton_box().append(&popover); - // Initially the file name is set to the same file name, so set the apply button insensitive first. - apply_button.set_sensitive(false); + // Initially the file name is set to the same file name, so set the apply button insensitive first. + apply_button.set_sensitive(false); - entry.connect_text_notify(clone!(@strong parent_path, @weak apply_button => move |entry2| { - let new_file_path = parent_path.join(entry2.text()); - // Disable apply button to prevent overwrites when file already exists - apply_button.set_sensitive(!new_file_path.exists()); - })); + entry.connect_text_notify(clone!( + #[strong] + parent_path, + #[weak] + apply_button, + move |entry2| { + let new_file_path = parent_path.join(entry2.text()); + // Disable apply button to prevent overwrites when file already exists + apply_button.set_sensitive(!new_file_path.exists()); + } + )); - apply_button.connect_clicked(clone!(@weak popover, @weak entry, @weak appwindow => move |_| { - let new_file_path = parent_path.join(entry.text()); + apply_button.connect_clicked(clone!( + #[weak] + popover, + #[weak] + entry, + #[weak] + appwindow, + move |_| { + let new_file_path = parent_path.join(entry.text()); - if new_file_path.exists() { - appwindow.overlays().dispatch_toast_error(&gettext("Renaming file failed, target file already exists")); - debug!("Renaming file with path '{}' failed, target file already exists", new_file_path.display()); - } else { - glib::spawn_future_local(clone!(@strong current_file_path, @weak appwindow => async move { - appwindow.overlays().progressbar_start_pulsing(); - if let Err(e) = async_fs::rename(¤t_file_path, &new_file_path).await { - error!("Renaming file with path `{}` failed, Err: {e:?}", new_file_path.display()); - appwindow.overlays().dispatch_toast_error(&gettext("Renaming file failed")); - appwindow.overlays().progressbar_abort(); + if new_file_path.exists() { + appwindow.overlays().dispatch_toast_error(&gettext( + "Renaming file failed, target file already exists", + )); + debug!( + "Renaming file with path '{}' failed, target file already exists", + new_file_path.display() + ); } else { - appwindow.overlays().progressbar_finish(); + glib::spawn_future_local(clone!( + #[strong] + current_file_path, + #[weak] + appwindow, + async move { + appwindow.overlays().progressbar_start_pulsing(); + if let Err(e) = + async_fs::rename(¤t_file_path, &new_file_path).await + { + error!( + "Renaming file with path `{}` failed, Err: {e:?}", + new_file_path.display() + ); + appwindow + .overlays() + .dispatch_toast_error(&gettext("Renaming file failed")); + appwindow.overlays().progressbar_abort(); + } else { + appwindow.overlays().progressbar_finish(); + } + } + )); } - })); - } - popover.popdown(); - })); + popover.popdown(); + } + )); - popover.popup(); - entry_text_select_stem(&entry); - })); + popover.popup(); + entry_text_select_stem(&entry); + } + )); action } diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/actions/trash.rs b/crates/rnote-ui/src/workspacebrowser/filerow/actions/trash.rs index 79e94c3ad6..aa8d9df682 100644 --- a/crates/rnote-ui/src/workspacebrowser/filerow/actions/trash.rs +++ b/crates/rnote-ui/src/workspacebrowser/filerow/actions/trash.rs @@ -8,23 +8,36 @@ use tracing::debug; /// Create a new `trash` action. pub(crate) fn trash(filerow: &RnFileRow, appwindow: &RnAppWindow) -> gio::SimpleAction { let action = gio::SimpleAction::new("trash-file", None); - action.connect_activate( - clone!(@weak filerow, @weak appwindow => move |_action_trash_file, _| { + action.connect_activate(clone!( + #[weak] + filerow, + #[weak] + appwindow, + move |_action_trash_file, _| { let Some(current_file) = filerow.current_file() else { return; }; current_file.trash_async( glib::source::Priority::DEFAULT, None::<&gio::Cancellable>, - clone!(@weak filerow, @strong current_file => move |res| { - if let Err(e) = res { - appwindow.overlays().dispatch_toast_error(&gettext("Trashing file failed")); - debug!("Trash filerow file `{current_file:?}` failed , Err: {e:?}"); - return; - } - filerow.set_current_file(None); - })); - }), - ); + clone!( + #[weak] + filerow, + #[strong] + current_file, + move |res| { + if let Err(e) = res { + appwindow + .overlays() + .dispatch_toast_error(&gettext("Trashing file failed")); + debug!("Trash filerow file `{current_file:?}` failed , Err: {e:?}"); + return; + } + filerow.set_current_file(None); + } + ), + ); + } + )); action } diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/mod.rs b/crates/rnote-ui/src/workspacebrowser/filerow/mod.rs index 9e9bd30c5e..15c474e9ae 100644 --- a/crates/rnote-ui/src/workspacebrowser/filerow/mod.rs +++ b/crates/rnote-ui/src/workspacebrowser/filerow/mod.rs @@ -135,11 +135,13 @@ mod imp { .button(gdk::BUTTON_SECONDARY) .build(); obj.add_controller(rightclick_gesture.clone()); - rightclick_gesture.connect_pressed( - clone!(@weak obj as filerow => move |_rightclick_gesture, _n_press, _x, _y| { + rightclick_gesture.connect_pressed(clone!( + #[weak(rename_to=filerow)] + obj, + move |_rightclick_gesture, _n_press, _x, _y| { filerow.imp().popovermenu.popup(); - }), - ); + } + )); let longpress_gesture = GestureLongPress::builder() .name("longpress_gesture") @@ -148,11 +150,13 @@ mod imp { obj.add_controller(longpress_gesture.clone()); longpress_gesture.group_with(&rightclick_gesture); - longpress_gesture.connect_pressed( - clone!(@weak obj as filerow => move |_rightclick_gesture, _x, _y| { + longpress_gesture.connect_pressed(clone!( + #[weak(rename_to=filerow)] + obj, + move |_rightclick_gesture, _x, _y| { filerow.imp().popovermenu.popup(); - }), - ); + } + )); } } } @@ -212,13 +216,20 @@ impl RnFileRow { pub(crate) fn init(&self, appwindow: &RnAppWindow) { self.setup_actions(appwindow); - self.imp().popovermenu.connect_visible_notify( - clone!(@weak self as filerow, @weak appwindow => move |w| { + self.imp().popovermenu.connect_visible_notify(clone!( + #[weak(rename_to=filerow)] + self, + #[weak] + appwindow, + move |w| { if w.get_visible() { - appwindow.sidebar().workspacebrowser().files_list_set_selected(Some(filerow.position())); + appwindow + .sidebar() + .workspacebrowser() + .files_list_set_selected(Some(filerow.position())); } - }), - ); + } + )); } fn setup_actions(&self, appwindow: &RnAppWindow) { diff --git a/crates/rnote-ui/src/workspacebrowser/mod.rs b/crates/rnote-ui/src/workspacebrowser/mod.rs index a86f342f39..b35ea1ef62 100644 --- a/crates/rnote-ui/src/workspacebrowser/mod.rs +++ b/crates/rnote-ui/src/workspacebrowser/mod.rs @@ -197,8 +197,8 @@ impl RnWorkspaceBrowser { .add_action(&workspaceactions::create_folder(self, appwindow)); } - fn setup_dir_controls(&self, appwindow: &RnAppWindow) { - self.imp().dir_controls_dir_up_button.connect_clicked(clone!(@weak self as workspacebrowser, @weak appwindow => move |_| { + fn setup_dir_controls(&self, _appwindow: &RnAppWindow) { + self.imp().dir_controls_dir_up_button.connect_clicked(clone!(#[weak(rename_to=workspacebrowser)] self , move |_| { if let Some(mut dir) = workspacebrowser.workspacesbar().selected_workspacelistentry().map(|e| PathBuf::from(e.dir())) { // don't canonicalize on windows, because that would convert the path to one with extended length syntax if !cfg!(target_os = "windows") { @@ -271,36 +271,65 @@ impl RnWorkspaceBrowser { .set_header_factory(Some(&create_files_list_header_factory(appwindow))); self.imp().dir_list.connect_items_changed(clone!( - @weak self as workspacebrowser, - @weak folders_filter, - @weak folders_sorter, - @weak notes_filter, - @weak notes_sorter, - @weak files_filter, - @weak files_sorter - => move |_, _, _, _| { + #[weak] + folders_filter, + #[weak] + folders_sorter, + #[weak] + notes_filter, + #[weak] + notes_sorter, + #[weak] + files_filter, + #[weak] + files_sorter, + move |_, _, _, _| { folders_filter.changed(FilterChange::Different); folders_sorter.changed(SorterChange::Different); notes_filter.changed(FilterChange::Different); notes_sorter.changed(SorterChange::Different); files_filter.changed(FilterChange::Different); files_sorter.changed(SorterChange::Different); - })); - - imp.files_listview.get().connect_activate(clone!(@weak self as workspacebrowser, - @weak appwindow, - @weak folders_filter, - @weak folders_sorter, - @weak notes_filter, - @weak notes_sorter, - @weak files_filter, - @weak files_sorter - => move |listview, position| { - let file_info = listview.model().unwrap().item(position).unwrap().downcast::().unwrap(); + } + )); + + imp.files_listview.get().connect_activate(clone!( + #[weak] + appwindow, + #[weak] + folders_filter, + #[weak] + folders_sorter, + #[weak] + notes_filter, + #[weak] + notes_sorter, + #[weak] + files_filter, + #[weak] + files_sorter, + move |listview, position| { + let file_info = listview + .model() + .unwrap() + .item(position) + .unwrap() + .downcast::() + .unwrap(); if let Some(input_file) = file_info.attribute_object("standard::file") { - glib::spawn_future_local(clone!(@weak appwindow => async move { - appwindow.open_file_w_dialogs(input_file.downcast::().unwrap(), None, true).await; - })); + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + appwindow + .open_file_w_dialogs( + input_file.downcast::().unwrap(), + None, + true, + ) + .await; + } + )); }; folders_filter.changed(FilterChange::Different); folders_sorter.changed(SorterChange::Different); @@ -308,17 +337,20 @@ impl RnWorkspaceBrowser { notes_sorter.changed(SorterChange::Different); files_filter.changed(FilterChange::Different); files_sorter.changed(SorterChange::Different); - })); + } + )); - self.imp().dir_list.connect_file_notify( - clone!(@weak self as workspacebrowser => move |dir_list| { + self.imp().dir_list.connect_file_notify(clone!( + #[weak(rename_to=workspacebrowser)] + self, + move |dir_list| { // Disable the dir up row when no file is set or has no parent. workspacebrowser .imp() .dir_controls_dir_up_button .set_sensitive(dir_list.file().and_then(|f| f.parent()).is_some()); - }), - ); + } + )); } /// Set the selected file in the files list with its position. @@ -332,7 +364,10 @@ impl RnWorkspaceBrowser { fn create_files_list_row_factory(appwindow: &RnAppWindow) -> SignalListItemFactory { let factory = SignalListItemFactory::new(); - factory.connect_setup(clone!(@weak appwindow => move |_, list_item| { + factory.connect_setup(clone!( + #[weak] + appwindow, + move |_, list_item| { let list_item = list_item.downcast_ref::().unwrap(); let filerow = RnFileRow::new(); @@ -380,7 +415,12 @@ fn create_files_list_row_factory(appwindow: &RnAppWindow) -> SignalListItemFacto )); let icon_name_expr = - fileinfo_expr.chain_closure::(closure!(|_: Option, fileinfo_obj: Option| { + fileinfo_expr.chain_closure::(closure!(|_: Option< + glib::Object, + >, + fileinfo_obj: Option< + glib::Object, + >| { if let Some(fileinfo_obj) = fileinfo_obj { if let Some(themed_icon) = fileinfo_obj .downcast::() @@ -398,7 +438,10 @@ fn create_files_list_row_factory(appwindow: &RnAppWindow) -> SignalListItemFacto })); let basename_expr = - fileinfo_expr.chain_closure::(closure!(|_: Option, fileinfo_obj: Option| { + fileinfo_expr.chain_closure::(closure!(|_: Option, + fileinfo_obj: Option< + glib::Object, + >| { if let Some(fileinfo_obj) = fileinfo_obj { if let Some(file) = fileinfo_obj .downcast::() @@ -422,15 +465,16 @@ fn create_files_list_row_factory(appwindow: &RnAppWindow) -> SignalListItemFacto basename_expr.bind(&filerow.file_label(), "label", Widget::NONE); icon_name_expr.bind(&filerow.file_image(), "gicon", Widget::NONE); content_provider_expr.bind(&filerow.drag_source(), "content", Widget::NONE); - })); + } + )); factory } -fn create_files_list_header_factory(appwindow: &RnAppWindow) -> SignalListItemFactory { +fn create_files_list_header_factory(_appwindow: &RnAppWindow) -> SignalListItemFactory { let factory = SignalListItemFactory::new(); - factory.connect_setup(clone!(@weak appwindow => move |_, list_header| { + factory.connect_setup(clone!(move |_, list_header| { let list_header = list_header.downcast_ref::().unwrap(); let separator = Separator::builder() .orientation(gtk4::Orientation::Horizontal) diff --git a/crates/rnote-ui/src/workspacebrowser/widgethelper.rs b/crates/rnote-ui/src/workspacebrowser/widgethelper.rs index c111e4aa1c..b262729bc8 100644 --- a/crates/rnote-ui/src/workspacebrowser/widgethelper.rs +++ b/crates/rnote-ui/src/workspacebrowser/widgethelper.rs @@ -49,9 +49,13 @@ pub(crate) fn create_entry_dialog(entry: &Entry, label: &Label) -> (Button, Popo .build(); popover.set_child(Some(&grid)); - cancel_button.connect_clicked(clone!(@weak popover => move |_| { - popover.popdown(); - })); + cancel_button.connect_clicked(clone!( + #[weak] + popover, + move |_| { + popover.popdown(); + } + )); (apply_button, popover) } diff --git a/crates/rnote-ui/src/workspacebrowser/workspaceactions/createfolder.rs b/crates/rnote-ui/src/workspacebrowser/workspaceactions/createfolder.rs index f4872c97b3..b55c5d61da 100644 --- a/crates/rnote-ui/src/workspacebrowser/workspaceactions/createfolder.rs +++ b/crates/rnote-ui/src/workspacebrowser/workspaceactions/createfolder.rs @@ -12,53 +12,81 @@ pub(crate) fn create_folder( ) -> gio::SimpleAction { let new_folder_action = gio::SimpleAction::new("create-folder", None); - new_folder_action.connect_activate(clone!(@weak workspacebrowser, @weak appwindow => move |_, _| { - if let Some(parent_path) = workspacebrowser.dir_list_file().and_then(|f| f.path()) { - let folder_name_entry = create_folder_name_entry(); - let dialog_title_label = create_dialog_title_label(); - let (apply_button, popover) = widgethelper::create_entry_dialog(&folder_name_entry, &dialog_title_label); + new_folder_action.connect_activate(clone!( + #[weak] + workspacebrowser, + #[weak] + appwindow, + move |_, _| { + if let Some(parent_path) = workspacebrowser.dir_list_file().and_then(|f| f.path()) { + let folder_name_entry = create_folder_name_entry(); + let dialog_title_label = create_dialog_title_label(); + let (apply_button, popover) = + widgethelper::create_entry_dialog(&folder_name_entry, &dialog_title_label); - // at first don't allow applying, since the user did not enter any text yet. - apply_button.set_sensitive(false); + // at first don't allow applying, since the user did not enter any text yet. + apply_button.set_sensitive(false); - workspacebrowser.dir_controls_actions_box().append(&popover); + workspacebrowser.dir_controls_actions_box().append(&popover); - folder_name_entry.connect_changed(clone!(@weak apply_button, @strong parent_path => move |entry| { - let entry_text = entry.text(); - let new_folder_path = parent_path.join(&entry_text); + folder_name_entry.connect_changed(clone!( + #[weak] + apply_button, + #[strong] + parent_path, + move |entry| { + let entry_text = entry.text(); + let new_folder_path = parent_path.join(&entry_text); - if new_folder_path.exists() || entry_text.is_empty() { - apply_button.set_sensitive(false); - entry.add_css_class("error"); - } else { - // Only allow creating valid folder names - apply_button.set_sensitive(true); - entry.remove_css_class("error"); - } - })); + if new_folder_path.exists() || entry_text.is_empty() { + apply_button.set_sensitive(false); + entry.add_css_class("error"); + } else { + // Only allow creating valid folder names + apply_button.set_sensitive(true); + entry.remove_css_class("error"); + } + } + )); - apply_button.connect_clicked(clone!(@weak popover, @weak folder_name_entry, @weak appwindow => move |_| { - let new_folder_path = parent_path.join(folder_name_entry.text().as_str()); + apply_button.connect_clicked(clone!( + #[weak] + popover, + #[weak] + folder_name_entry, + #[weak] + appwindow, + move |_| { + let new_folder_path = parent_path.join(folder_name_entry.text().as_str()); - if new_folder_path.exists() { - // Should have been caught earlier, but making sure - appwindow.overlays().dispatch_toast_error("Can't create folder that already exists."); - debug!("Couldn't create new folder wit name `{}`, it already exists.", folder_name_entry.text().as_str()); - } else { - if let Err(e) = fs_extra::dir::create(new_folder_path, false) { - appwindow.overlays().dispatch_toast_error("Creating new folder failed"); - debug!("Couldn't create folder, Err: {e:?}"); - } + if new_folder_path.exists() { + // Should have been caught earlier, but making sure + appwindow + .overlays() + .dispatch_toast_error("Can't create folder that already exists."); + debug!( + "Couldn't create new folder wit name `{}`, it already exists.", + folder_name_entry.text().as_str() + ); + } else { + if let Err(e) = fs_extra::dir::create(new_folder_path, false) { + appwindow + .overlays() + .dispatch_toast_error("Creating new folder failed"); + debug!("Couldn't create folder, Err: {e:?}"); + } - popover.popdown(); - } - })); + popover.popdown(); + } + } + )); - popover.popup(); - } else { - warn!("Can't create new folder when there currently is no workspace selected"); + popover.popup(); + } else { + warn!("Can't create new folder when there currently is no workspace selected"); + } } - })); + )); new_folder_action } diff --git a/crates/rnote-ui/src/workspacebrowser/workspacesbar/mod.rs b/crates/rnote-ui/src/workspacebrowser/workspacesbar/mod.rs index 9529e497b8..df0e6655eb 100644 --- a/crates/rnote-ui/src/workspacebrowser/workspacesbar/mod.rs +++ b/crates/rnote-ui/src/workspacebrowser/workspacesbar/mod.rs @@ -287,65 +287,144 @@ impl RnWorkspacesBar { pub(crate) fn init(&self, appwindow: &RnAppWindow) { self.setup_actions(appwindow); - self.imp().workspace_list.connect_items_changed( - clone!(@weak self as workspacesbar, @weak appwindow => move |list, _, _, _| { - workspacesbar.imp().remove_selected_workspace_button.get().set_sensitive(list.n_items() > 1); - workspacesbar.imp().edit_selected_workspace_button.get().set_sensitive(list.n_items() > 0); - }), - ); + self.imp().workspace_list.connect_items_changed(clone!( + #[weak(rename_to=workspacesbar)] + self, + move |list, _, _, _| { + workspacesbar + .imp() + .remove_selected_workspace_button + .get() + .set_sensitive(list.n_items() > 1); + workspacesbar + .imp() + .edit_selected_workspace_button + .get() + .set_sensitive(list.n_items() > 0); + } + )); let workspace_listbox = self.imp().workspaces_listbox.get(); - workspace_listbox.connect_selected_rows_changed( - clone!(@weak appwindow, @weak self as workspacesbar => move |_| { + workspace_listbox.connect_selected_rows_changed(clone!( + #[weak] + appwindow, + #[weak(rename_to=workspacesbar)] + self, + move |_| { if let Some(entry) = workspacesbar.selected_workspacelistentry() { let dir = entry.dir(); let name = entry.name(); - appwindow.sidebar().workspacebrowser().active_workspace_name_label().set_label(&name); - appwindow.sidebar().workspacebrowser().active_workspace_dir_label().set_label(&dir); - appwindow.sidebar().workspacebrowser().set_dir_list_file(Some(&gio::File::for_path(dir))); + appwindow + .sidebar() + .workspacebrowser() + .active_workspace_name_label() + .set_label(&name); + appwindow + .sidebar() + .workspacebrowser() + .active_workspace_dir_label() + .set_label(&dir); + appwindow + .sidebar() + .workspacebrowser() + .set_dir_list_file(Some(&gio::File::for_path(dir))); } - - }), - ); + } + )); workspace_listbox.bind_model( Some(&self.imp().workspace_list), - clone!(@weak appwindow => @default-panic, move |obj| { - let entry = obj.to_owned().downcast::().unwrap(); - let workspacerow = RnWorkspaceRow::new(&entry); - workspacerow.init(&appwindow); - - let entry_expr = ConstantExpression::new(&entry); - entry_expr.bind(&workspacerow, "entry", None::<&glib::Object>); - - workspacerow.upcast::() - }), + clone!( + #[weak] + appwindow, + #[upgrade_or_panic] + move |obj| { + let entry = obj.to_owned().downcast::().unwrap(); + let workspacerow = RnWorkspaceRow::new(&entry); + workspacerow.init(&appwindow); + + let entry_expr = ConstantExpression::new(&entry); + entry_expr.bind(&workspacerow, "entry", None::<&glib::Object>); + + workspacerow.upcast::() + } + ), ); - self.imp().move_selected_workspace_up_button.get().connect_clicked( - clone!(@weak self as workspacesbar, @weak appwindow => move |_| { - adw::prelude::ActionGroupExt::activate_action(&workspacesbar.action_group(), "move-selected-workspace-up", None); - })); + self.imp() + .move_selected_workspace_up_button + .get() + .connect_clicked(clone!( + #[weak(rename_to=workspacesbar)] + self, + move |_| { + adw::prelude::ActionGroupExt::activate_action( + &workspacesbar.action_group(), + "move-selected-workspace-up", + None, + ); + } + )); - self.imp().move_selected_workspace_down_button.get().connect_clicked( - clone!(@weak self as workspacesbar, @weak appwindow => move |_| { - adw::prelude::ActionGroupExt::activate_action(&workspacesbar.action_group(), "move-selected-workspace-down", None); - })); + self.imp() + .move_selected_workspace_down_button + .get() + .connect_clicked(clone!( + #[weak(rename_to=workspacesbar)] + self, + move |_| { + adw::prelude::ActionGroupExt::activate_action( + &workspacesbar.action_group(), + "move-selected-workspace-down", + None, + ); + } + )); - self.imp().add_workspace_button.get().connect_clicked( - clone!(@weak self as workspacesbar, @weak appwindow => move |_| { - adw::prelude::ActionGroupExt::activate_action(&workspacesbar.action_group(), "add-workspace", None); - })); + self.imp() + .add_workspace_button + .get() + .connect_clicked(clone!( + #[weak(rename_to=workspacesbar)] + self, + move |_| { + adw::prelude::ActionGroupExt::activate_action( + &workspacesbar.action_group(), + "add-workspace", + None, + ); + } + )); - self.imp().remove_selected_workspace_button.get().connect_clicked( - clone!(@weak self as workspacesbar, @weak appwindow => move |_| { - adw::prelude::ActionGroupExt::activate_action(&workspacesbar.action_group(), "remove-selected-workspace", None); - })); + self.imp() + .remove_selected_workspace_button + .get() + .connect_clicked(clone!( + #[weak(rename_to=workspacesbar)] + self, + move |_| { + adw::prelude::ActionGroupExt::activate_action( + &workspacesbar.action_group(), + "remove-selected-workspace", + None, + ); + } + )); - self.imp().edit_selected_workspace_button.get().connect_clicked( - clone!(@weak self as workspacesbar, @weak appwindow => move |_| { - adw::prelude::ActionGroupExt::activate_action(&workspacesbar.action_group(), "edit-selected-workspace", None); - })); + self.imp() + .edit_selected_workspace_button + .get() + .connect_clicked(clone!( + #[weak(rename_to=workspacesbar)] + self, + move |_| { + adw::prelude::ActionGroupExt::activate_action( + &workspacesbar.action_group(), + "edit-selected-workspace", + None, + ); + } + )); // Add initial entry self.insert_workspace_entry(0, RnWorkspaceListEntry::default()); @@ -373,44 +452,70 @@ impl RnWorkspacesBar { imp.action_group.add_action(&action_edit_selected_workspace); // Move selected workspace up - action_move_selected_workspace_up.connect_activate( - clone!(@weak self as workspacesbar, @weak appwindow => move |_, _| { + action_move_selected_workspace_up.connect_activate(clone!( + #[weak(rename_to=workspacesbar)] + self, + move |_, _| { workspacesbar.move_selected_workspace_up(); - }), - ); + } + )); // Move selected workspace down - action_move_selected_workspace_down.connect_activate( - clone!(@weak self as workspacesbar, @weak appwindow => move |_, _| { + action_move_selected_workspace_down.connect_activate(clone!( + #[weak(rename_to=workspacesbar)] + self, + move |_, _| { workspacesbar.move_selected_workspace_down(); - }), - ); + } + )); // Add workspace - action_add_workspace.connect_activate( - clone!(@weak self as workspacesbar, @weak appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak workspacesbar, @weak appwindow => async move { - let entry = workspacesbar.selected_workspacelistentry().unwrap_or_default(); - workspacesbar.push_workspace(entry); - - // Popup the edit dialog after creation - dialogs::dialog_edit_selected_workspace(&appwindow).await; - })); - }), - ); + action_add_workspace.connect_activate(clone!( + #[weak(rename_to=workspacesbar)] + self, + #[weak] + appwindow, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + workspacesbar, + #[weak] + appwindow, + async move { + let entry = workspacesbar + .selected_workspacelistentry() + .unwrap_or_default(); + workspacesbar.push_workspace(entry); + + // Popup the edit dialog after creation + dialogs::dialog_edit_selected_workspace(&appwindow).await; + } + )); + } + )); // Remove selected workspace - action_remove_selected_workspace.connect_activate( - clone!(@weak self as workspacesbar, @weak appwindow => move |_, _| { - workspacesbar.remove_selected_workspace(); - }), - ); + action_remove_selected_workspace.connect_activate(clone!( + #[weak(rename_to=workspacesbar)] + self, + move |_, _| { + workspacesbar.remove_selected_workspace(); + } + )); // Edit selected workspace - action_edit_selected_workspace.connect_activate(clone!(@weak appwindow => move |_, _| { - glib::spawn_future_local(clone!(@weak appwindow => async move { - dialogs::dialog_edit_selected_workspace(&appwindow).await; - })); - })); + action_edit_selected_workspace.connect_activate(clone!( + #[weak] + appwindow, + move |_, _| { + glib::spawn_future_local(clone!( + #[weak] + appwindow, + async move { + dialogs::dialog_edit_selected_workspace(&appwindow).await; + } + )); + } + )); } } diff --git a/crates/rnote-ui/src/workspacebrowser/workspacesbar/workspacerow.rs b/crates/rnote-ui/src/workspacebrowser/workspacesbar/workspacerow.rs index b734775bbc..83f05e0475 100644 --- a/crates/rnote-ui/src/workspacebrowser/workspacesbar/workspacerow.rs +++ b/crates/rnote-ui/src/workspacebrowser/workspacesbar/workspacerow.rs @@ -102,30 +102,46 @@ mod imp { self.entry.borrow().connect_notify_local( Some("dir"), - clone!(@weak obj as workspacerow => move |_, _| { - workspacerow.imp().update_apearance(); - }), + clone!( + #[weak(rename_to=workspacerow)] + obj, + move |_, _| { + workspacerow.imp().update_apearance(); + } + ), ); self.entry.borrow().connect_notify_local( Some("icon"), - clone!(@weak obj as workspacerow => move |_, _| { - workspacerow.imp().update_apearance(); - }), + clone!( + #[weak(rename_to=workspacerow)] + obj, + move |_, _| { + workspacerow.imp().update_apearance(); + } + ), ); self.entry.borrow().connect_notify_local( Some("color"), - clone!(@weak obj as workspacerow => move |_, _| { - workspacerow.imp().update_apearance(); - }), + clone!( + #[weak(rename_to=workspacerow)] + obj, + move |_, _| { + workspacerow.imp().update_apearance(); + } + ), ); self.entry.borrow().connect_notify_local( Some("name"), - clone!(@weak obj as workspacerow => move |_, _| { - workspacerow.imp().update_apearance(); - }), + clone!( + #[weak(rename_to=workspacerow)] + obj, + move |_, _| { + workspacerow.imp().update_apearance(); + } + ), ); } From 3da733450a054ac4ae048d451eb661619f310abe Mon Sep 17 00:00:00 2001 From: Felix Zwettler Date: Mon, 16 Sep 2024 17:15:43 +0200 Subject: [PATCH 3/3] fix: accidental wrong piet patch commit, update kurbo --- Cargo.lock | 26 +++++++--------------- Cargo.toml | 6 ++--- crates/rnote-compose/src/shapes/ellipse.rs | 2 +- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da0c4c5eff..0cbfdec463 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1660,9 +1660,9 @@ checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1958,16 +1958,6 @@ dependencies = [ "arrayvec", ] -[[package]] -name = "kurbo" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1618d4ebd923e97d67e7cd363d80aef35fe961005cbbbb3d2dad8bdd1bc63440" -dependencies = [ - "arrayvec", - "smallvec", -] - [[package]] name = "kurbo" version = "0.11.1" @@ -2857,16 +2847,16 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "piet" version = "0.6.2" -source = "git+https://github.com/flxzt/piet?rev=a480bc20bd0d235928d46b009dae54e52e32767a#a480bc20bd0d235928d46b009dae54e52e32767a" +source = "git+https://github.com/flxzt/piet?rev=17fd59f260db3c54029a8288178e32f9f1742be2#17fd59f260db3c54029a8288178e32f9f1742be2" dependencies = [ - "kurbo 0.10.4", + "kurbo 0.11.1", "unic-bidi", ] [[package]] name = "piet-cairo" version = "0.6.2" -source = "git+https://github.com/flxzt/piet?rev=a480bc20bd0d235928d46b009dae54e52e32767a#a480bc20bd0d235928d46b009dae54e52e32767a" +source = "git+https://github.com/flxzt/piet?rev=17fd59f260db3c54029a8288178e32f9f1742be2#17fd59f260db3c54029a8288178e32f9f1742be2" dependencies = [ "cairo-rs", "pango", @@ -3260,7 +3250,7 @@ dependencies = [ "ijson", "image", "itertools 0.13.0", - "kurbo 0.10.4", + "kurbo 0.11.1", "libadwaita", "nalgebra", "notify-debouncer-full", @@ -3322,7 +3312,7 @@ dependencies = [ "base64", "clap", "ink-stroke-modeler-rs", - "kurbo 0.10.4", + "kurbo 0.11.1", "nalgebra", "num-derive", "num-traits", @@ -3361,7 +3351,7 @@ dependencies = [ "ijson", "image", "itertools 0.13.0", - "kurbo 0.10.4", + "kurbo 0.11.1", "librsvg", "nalgebra", "num-derive", diff --git a/Cargo.toml b/Cargo.toml index 873b12d679..dc589434f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ image = "0.25.2" indicatif = "0.17.8" ink-stroke-modeler-rs = { git = "https://github.com/flxzt/ink-stroke-modeler-rs", rev = "84d311e9b0d034dcd955a1f353d37f54b2bda70f" } itertools = "0.13.0" -kurbo = "0.10.4" +kurbo = "0.11.1" librsvg = "2.59.0" nalgebra = { version = "0.33.0", features = ["serde-serialize"] } notify-debouncer-full = "0.3.1" @@ -88,8 +88,8 @@ poppler-rs = { version = "0.24.1", features = ["v20_9"] } [patch.crates-io] # once a new piet (current v0.6.2) is released with updated cairo and kurbo deps, this can be removed. -piet = { git = "https://github.com/flxzt/piet", rev = "a480bc20bd0d235928d46b009dae54e52e32767a" } -piet-cairo = { git = "https://github.com/flxzt/piet", rev = "a480bc20bd0d235928d46b009dae54e52e32767a" } +piet = { git = "https://github.com/flxzt/piet", rev = "17fd59f260db3c54029a8288178e32f9f1742be2" } +piet-cairo = { git = "https://github.com/flxzt/piet", rev = "17fd59f260db3c54029a8288178e32f9f1742be2" } # the latest commit in rough depends on nightly-only features roughr = { git = "https://github.com/orhanbalci/rough-rs", rev = "0701ce0b874061707ef726533b43e1806af8b666" } rough_piet = { git = "https://github.com/orhanbalci/rough-rs", rev = "0701ce0b874061707ef726533b43e1806af8b666" } diff --git a/crates/rnote-compose/src/shapes/ellipse.rs b/crates/rnote-compose/src/shapes/ellipse.rs index c84ca25495..d225f42ab2 100644 --- a/crates/rnote-compose/src/shapes/ellipse.rs +++ b/crates/rnote-compose/src/shapes/ellipse.rs @@ -98,7 +98,7 @@ impl Ellipse { let mut lines = Vec::new(); let mut prev = kurbo::Point::new(0.0, 0.0); - self.outline_path().flatten(0.25, |el| match el { + kurbo::flatten(self.outline_path(), 0.25, |el| match el { kurbo::PathEl::MoveTo(point) => prev = point, kurbo::PathEl::LineTo(next) => { lines.push(Line {