diff --git a/Cargo.lock b/Cargo.lock index 7b3fb0a..a85e624 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,12 +27,6 @@ dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -117,9 +111,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.90" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "appit" @@ -141,9 +135,9 @@ dependencies = [ [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "arboard" @@ -171,7 +165,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -339,7 +333,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -374,7 +368,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -385,23 +379,23 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "attribute-derive" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f18fc482cf559bca9efe778ba2fd0d1c16a31d5d24a2c886ed16b2d217e454" +checksum = "f1800e974930e9079c965b9ffbcb6667a40401063a26396c7b4f15edc92da690" dependencies = [ "attribute-derive-macro", "derive-where", "manyhow", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "attribute-derive-macro" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85958950e587256a16c72325ff3c4f3e4db25999173e9ca2864665be84ff63b" +checksum = "5d908eb786ef94296bff86f90130b3b748b49401dc81fd2bb8b3dccd44cfacbd" dependencies = [ "collection_literals", "interpolator", @@ -410,7 +404,7 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -451,7 +445,7 @@ dependencies = [ "addr2line", "cfg-if", "libc", - "miniz_oxide 0.8.0", + "miniz_oxide", "object", "rustc-demangle", "windows-targets 0.52.6", @@ -492,9 +486,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitstream-io" -version = "2.5.3" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b81e1519b0d82120d2fd469d5bfb2919a9361c48b02d82d04befc1cdd2002452" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" [[package]] name = "block" @@ -568,7 +562,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -585,9 +579,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "calloop" @@ -617,9 +611,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.31" +version = "1.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" dependencies = [ "jobserver", "libc", @@ -923,7 +917,7 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -965,7 +959,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -984,6 +978,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "dlib" version = "0.5.2" @@ -1056,7 +1061,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1123,15 +1128,14 @@ dependencies = [ [[package]] name = "exr" -version = "1.72.0" +version = "1.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" dependencies = [ "bit_field", - "flume", "half", "lebe", - "miniz_oxide 0.7.4", + "miniz_oxide", "rayon-core", "smallvec", "zune-inflate", @@ -1151,18 +1155,18 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fdeflate" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" +checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" dependencies = [ "simd-adler32", ] [[package]] name = "figures" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "097ad6ec659462a9d6efea9af358a9564e52d76981aa9d73343ab3c566d083c0" +checksum = "62cab407ec9ab5f649d809025b956687f756aad87fcea48d59fd56f47771c90d" dependencies = [ "bytemuck", "euclid", @@ -1179,7 +1183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -1188,20 +1192,11 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "spin", -] - [[package]] name = "font-types" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda6e36206148f69fc6ecb1bb6c0dedd7ee469f3db1d0dc2045beea28430ca43" +checksum = "b3971f9a5ca983419cdc386941ba3b9e1feba01a0ab888adf78739feb2798492" dependencies = [ "bytemuck", ] @@ -1247,7 +1242,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1288,9 +1283,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "3f1fa2f9765705486b33fd2acf1577f8ec449c2ba1f318ae5447697b7c08d210" dependencies = [ "fastrand", "futures-core", @@ -1307,7 +1302,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1499,9 +1494,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "hassle-rs" @@ -1543,20 +1538,149 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] -name = "idna" -version = "0.5.0" +name = "icu_collections" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "image" -version = "0.25.4" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc144d44a31d753b02ce64093d532f55ff8dc4ebf2ffb8a63c0dda691385acae" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" dependencies = [ "bytemuck", "byteorder-lite", @@ -1598,14 +1722,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.1", ] [[package]] name = "insta" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60" +checksum = "7e9ffc4d4892617c50a928c52b2961cb5174b6fc6ebf252b2fac9d21955c48b8" dependencies = [ "console", "lazy_static", @@ -1633,7 +1757,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1729,7 +1853,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kludgine" version = "0.11.0" -source = "git+https://github.com/khonsulabs/kludgine#2f7755a1a9b7cae67711f7c41ee2cd2c6b12fd64" +source = "git+https://github.com/khonsulabs/kludgine#3d7b7164230449f914fa48cc4ccdf2d28b7188f2" dependencies = [ "ahash", "alot", @@ -1766,9 +1890,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libdbus-sys" @@ -1802,9 +1926,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -1829,6 +1953,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "litrs" version = "0.4.1" @@ -1862,9 +1992,9 @@ dependencies = [ [[package]] name = "lyon_geom" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edecfb8d234a2b0be031ab02ebcdd9f3b9ee418fb35e265f7a540a48d197bff9" +checksum = "8af69edc087272df438b3ee436c4bb6d7c04aa8af665cfd398feae627dbd8570" dependencies = [ "arrayvec", "euclid", @@ -1873,9 +2003,9 @@ dependencies = [ [[package]] name = "lyon_path" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c08a606c7a59638d6c6aa18ac91a06aa9fb5f765a7efb27e6a4da58700740d7" +checksum = "8e0b8aec2f58586f6eef237985b9a9b7cb3a3aff4417c575075cf95bf925252e" dependencies = [ "lyon_geom", "num-traits", @@ -1910,7 +2040,7 @@ dependencies = [ "manyhow-macros", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1940,6 +2070,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" dependencies = [ "cfg-if", + "rayon", ] [[package]] @@ -1987,15 +2118,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -2135,7 +2257,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2186,7 +2308,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2471,7 +2593,7 @@ dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2545,7 +2667,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2559,29 +2681,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2634,14 +2756,14 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] name = "polling" -version = "3.7.3" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", @@ -2675,12 +2797,12 @@ checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2705,9 +2827,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -2728,7 +2850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" dependencies = [ "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2783,7 +2905,7 @@ dependencies = [ "proc-macro-utils", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2874,6 +2996,7 @@ dependencies = [ "loop9", "quick-error", "rav1e", + "rayon", "rgb", ] @@ -2905,9 +3028,9 @@ dependencies = [ [[package]] name = "read-fonts" -version = "0.22.3" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb94d9ac780fdcf9b6b252253f7d8f221379b84bd3573131139b383df69f85e1" +checksum = "4a04b892cb6f91951f144c33321843790c8574c825aafdb16d815fd7183b5229" dependencies = [ "bytemuck", "font-types", @@ -2933,9 +3056,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -3029,9 +3152,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ "bitflags 2.6.0", "errno", @@ -3099,22 +3222,22 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -3125,7 +3248,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -3267,15 +3390,6 @@ dependencies = [ "serde", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" @@ -3285,6 +3399,12 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -3299,9 +3419,9 @@ checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" [[package]] name = "svg_fmt" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca" +checksum = "ce5d813d71d82c4cbc1742135004e4a79fd870214c155443451c139c9470a0aa" [[package]] name = "swash" @@ -3327,9 +3447,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -3337,10 +3457,21 @@ dependencies = [ ] [[package]] -name = "sys-locale" -version = "0.3.1" +name = "synstructure" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" dependencies = [ "libc", ] @@ -3388,22 +3519,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -3452,6 +3583,16 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -3469,9 +3610,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "pin-project-lite", @@ -3530,7 +3671,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -3637,15 +3778,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-properties" version = "0.1.3" @@ -3678,9 +3810,9 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", @@ -3694,6 +3826,18 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "v_frame" version = "0.3.8" @@ -3761,7 +3905,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -3795,7 +3939,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3822,9 +3966,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.6" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" dependencies = [ "bitflags 2.6.0", "rustix", @@ -3845,9 +3989,9 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.31.6" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a94697e66e76c85923b0d28a0c251e8f0666f58fc47d316c0f4da6da75d37cb" +checksum = "32b08bc3aafdb0035e7fe0fdf17ba0c09c268732707dca4ae098f60cb28c9e4c" dependencies = [ "rustix", "wayland-client", @@ -3856,9 +4000,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.4" +version = "0.32.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5755d77ae9040bb872a25026555ce4cb0ae75fd923e90d25fba07d81057de0" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -3868,9 +4012,9 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0a41a6875e585172495f7a96dfa42ca7e0213868f4f15c313f7c33221a7eff" +checksum = "9b31cab548ee68c7eb155517f2212049dc151f7cd7910c2b66abfd31c3ee12bd" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -3881,9 +4025,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad87b5fd1b1d3ca2f792df8f686a2a11e3fe1077b71096f7a175ab699f89109" +checksum = "782e12f6cd923c3c316130d56205ebab53f55d6666b7faddfad36cecaeeb4022" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -4378,6 +4522,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "x11-dl" version = "2.21.0" @@ -4447,9 +4603,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" +checksum = "af310deaae937e48a26602b730250b4949e125f468f11e6990be3e5304ddd96f" [[package]] name = "yazi" @@ -4457,6 +4613,30 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + [[package]] name = "zbus" version = "4.4.0" @@ -4504,7 +4684,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "zvariant_utils", ] @@ -4543,7 +4723,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", ] [[package]] @@ -4552,6 +4753,28 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "zune-core" version = "0.4.12" @@ -4599,7 +4822,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "zvariant_utils", ] @@ -4611,5 +4834,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] diff --git a/examples/virtual-list.rs b/examples/virtual-list.rs index 35c9637..7482f84 100644 --- a/examples/virtual-list.rs +++ b/examples/virtual-list.rs @@ -1,29 +1,9 @@ -use cushy::styles::Dimension; use cushy::widget::MakeWidget; -use cushy::widgets::virtual_list::{VirtualList, VirtualListContent}; +use cushy::widgets::VirtualList; use cushy::Run; -use figures::units::Lp; - -#[derive(Debug)] -struct TestVirtualList; - -impl VirtualListContent for TestVirtualList { - fn item_count(&self) -> impl cushy::value::IntoValue { - 50 - } - fn item_height(&self) -> impl cushy::value::IntoValue { - cushy::styles::Dimension::Lp(Lp::inches_f(0.5)) - } - fn widget_at(&self, index: usize) -> impl MakeWidget { - format!("Item {}", index) - } - fn width(&self) -> impl cushy::value::IntoValue { - Dimension::Lp(Lp::inches_f(10.)) - } -} fn list() -> impl MakeWidget { - VirtualList::new(TestVirtualList).expand() + VirtualList::new(50, |index| format!("Item {}", index)).expand() } fn main() -> cushy::Result { diff --git a/guide/guide-examples/examples/virtual-list.rs b/guide/guide-examples/examples/virtual-list.rs index 3781511..f32654a 100644 --- a/guide/guide-examples/examples/virtual-list.rs +++ b/guide/guide-examples/examples/virtual-list.rs @@ -1,32 +1,10 @@ -use cushy::figures::units::Lp; -use cushy::styles::Dimension; use cushy::widget::MakeWidget; -use cushy::widgets::virtual_list::{VirtualList, VirtualListContent}; +use cushy::widgets::VirtualList; use cushy::Run; -// ANCHOR: implementation -#[derive(Debug)] -struct TestVirtualList; - -impl VirtualListContent for TestVirtualList { - fn item_count(&self) -> impl cushy::value::IntoValue { - 50 - } - fn item_height(&self) -> impl cushy::value::IntoValue { - cushy::styles::Dimension::Lp(Lp::inches_f(0.5)) - } - fn widget_at(&self, index: usize) -> impl MakeWidget { - format!("Item {}", index) - } - fn width(&self) -> impl cushy::value::IntoValue { - Dimension::Lp(Lp::inches_f(10.)) - } -} -// ANCHOR_END: implementation - // ANCHOR: list fn list() -> impl MakeWidget { - VirtualList::new(TestVirtualList).expand() + VirtualList::new(50, |index| format!("Item {}", index)).expand() } // ANCHOR_END: list diff --git a/src/lib.rs b/src/lib.rs index 28e4308..ae48f5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -195,6 +195,19 @@ impl ConstraintLimit { ConstraintLimit::SizeToFit(_) => measured.into_unsigned(), } } + + /// When `self` is `SizeToFit`, the smallest of the constraint and + /// `measured` will be returned. When `self` is `Fill`, the fill size will + /// be returned. + pub fn fill_or_fit(self, measured: Unit) -> UPx + where + Unit: IntoUnsigned, + { + match self { + ConstraintLimit::Fill(size) => size, + ConstraintLimit::SizeToFit(size) => size.min(measured.into_unsigned()), + } + } } /// An extension trait for `Size`. diff --git a/src/widget.rs b/src/widget.rs index 809456f..8e4fca6 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1348,7 +1348,7 @@ pub trait MakeWidget: Sized { /// Creates a [`WidgetRef`] for use as child widget. #[must_use] - fn widget_ref(self) -> WidgetRef { + fn into_ref(self) -> WidgetRef { WidgetRef::new(self) } diff --git a/src/widgets.rs b/src/widgets.rs index 054c870..0bbeb18 100644 --- a/src/widgets.rs +++ b/src/widgets.rs @@ -25,7 +25,6 @@ pub mod progress; pub mod radio; mod resize; pub mod scroll; -pub mod virtual_list; pub mod select; pub mod shortcuts; pub mod slider; @@ -36,6 +35,7 @@ mod switcher; mod themed; mod tilemap; pub mod validated; +mod virtual_list; pub mod wrap; pub use self::align::Align; @@ -70,4 +70,5 @@ pub use self::switcher::Switcher; pub use self::themed::Themed; pub use self::tilemap::TileMap; pub use self::validated::Validated; +pub use self::virtual_list::VirtualList; pub use self::wrap::Wrap; diff --git a/src/widgets/button.rs b/src/widgets/button.rs index 027ae3b..fa57373 100644 --- a/src/widgets/button.rs +++ b/src/widgets/button.rs @@ -137,7 +137,7 @@ impl Button { /// Returns a new button with the provided label. pub fn new(content: impl MakeWidget) -> Self { Self { - content: content.widget_ref(), + content: content.into_ref(), on_click: None, per_window: WindowLocal::default(), kind: Value::Constant(ButtonKind::default()), diff --git a/src/widgets/expand.rs b/src/widgets/expand.rs index 0b096c1..5931ed0 100644 --- a/src/widgets/expand.rs +++ b/src/widgets/expand.rs @@ -107,7 +107,17 @@ impl WrapperWidget for Expand { available_space: Size, context: &mut LayoutContext<'_, '_, '_, '_>, ) -> WrappedLayout { - let available_space = available_space.map(|lim| ConstraintLimit::Fill(lim.max())); + let available_space = match &self.kind { + ExpandKind::Weighted(_) => available_space.map(|lim| ConstraintLimit::Fill(lim.max())), + ExpandKind::Horizontal => Size::new( + ConstraintLimit::Fill(available_space.width.max()), + ConstraintLimit::SizeToFit(available_space.height.max()), + ), + ExpandKind::Vertical => Size::new( + ConstraintLimit::SizeToFit(available_space.width.max()), + ConstraintLimit::Fill(available_space.height.max()), + ), + }; let child = self.child.mounted(&mut context.as_event_context()); let size = context.for_other(&child).layout(available_space); diff --git a/src/widgets/virtual_list.rs b/src/widgets/virtual_list.rs index b7bd93c..0d29042 100644 --- a/src/widgets/virtual_list.rs +++ b/src/widgets/virtual_list.rs @@ -1,22 +1,38 @@ -use std::{collections::VecDeque, fmt::Debug, ops::Range}; +use std::collections::VecDeque; +use std::fmt::Debug; +use std::ops::Range; -use crate::{context::{AsEventContext, EventContext}, figures::{units::{Px, UPx}, IntoSigned, Point, Rect, Round, ScreenScale, Size, Zero}, kludgine::app::winit::{event::{ MouseScrollDelta, TouchPhase}, window::CursorIcon}, styles::Dimension, value::{Destination, Dynamic, DynamicReader, IntoDynamic, IntoValue, Source}, widget::{EventHandling, MakeWidget, MountedWidget, Widget, HANDLED, IGNORED}, widgets::scroll::ScrollBar, window::DeviceId, ConstraintLimit}; +use cushy::context::LayoutContext; +use cushy::ConstraintLimit; +use figures::UnscaledUnit; use super::scroll::OwnedWidget; +use crate::context::{AsEventContext, EventContext}; +use crate::figures::units::{Px, UPx}; +use crate::figures::{IntoSigned, Point, Rect, Round, ScreenScale, Size, Zero}; +use crate::kludgine::app::winit::event::{MouseScrollDelta, TouchPhase}; +use crate::kludgine::app::winit::window::CursorIcon; +use crate::value::{Destination, Dynamic, DynamicReader, IntoDynamic, IntoValue, Source}; +use crate::widget::{ + Callback, EventHandling, MakeWidget, MountedWidget, Widget, WidgetInstance, HANDLED, IGNORED, +}; +use crate::widgets::scroll::ScrollBar; +use crate::window::DeviceId; -/// A virtual list contents. -/// This simple virtual list assumes that all items have the same height, width and that the item count is known. -/// All the values are dynamic, so the list will update when the values change. -pub trait VirtualListContent: Debug { - /// Single item height - fn item_height(&self) -> impl IntoValue; - /// Width of the items - fn width(&self) -> impl IntoValue; - /// Number of items - fn item_count(&self) -> impl IntoValue; - /// Create a widget for the item at the given index. - /// This is called when the widget comes into view. The widget may be removed at any moment (by scrolling it out of view) and recreated later. - fn widget_at(&self, index: usize) -> impl MakeWidget; +#[derive(Debug)] +struct RowMaker(Callback); + +impl RowMaker { + fn make_row( + &mut self, + index: usize, + context: &mut LayoutContext<'_, '_, '_, '_>, + ) -> VirtualListItem { + VirtualListItem { + index, + mounted: context.push_child(self.0.invoke(index)), + } + } } #[derive(Debug)] @@ -26,37 +42,47 @@ struct VirtualListItem { } #[derive(Debug)] -/// A virtual list widget. -/// Requires a [VirtualListContent] trait implementation to render the items. -/// Items are lazily recreated as they go in and out of view. -pub struct VirtualList { - virtual_list: T, +/// A virtuallized list view +/// +/// This widget allows scrolling a list of rows by lazily loading only the rows +/// that are currently being displayed to the screen. +pub struct VirtualList { + make_row: RowMaker, vertical_scroll: OwnedWidget, items: VecDeque, content_size: Dynamic>, - /// Maximum scroll value - max_scroll.y + control_size.height should be the height of the content. + /// Maximum scroll value - `max_scroll.y` + `control_size.height` should be the height of the content. pub max_scroll: DynamicReader>, - /// Current scroll value. The x value is always 0. Change the value to scroll the widget programmatically. + /// Current scroll value. Changes to this dynamic will scroll the list + /// programmatically. pub scroll: Dynamic>, control_size: Dynamic>, - /// Height of an item. Based on [VirtualListContent::item_height]. - pub item_height: DynamicReader, - /// Width of the items. Based on [VirtualListContent::width]. - pub width: DynamicReader, - /// Number of items. Based on [VirtualListContent::item_count]. - pub item_count: DynamicReader, + item_count: DynamicReader, + item_size: Dynamic>, - visible_range: Dynamic> + visible_range: Dynamic>, } -impl VirtualList { - /// Creates a new [VirtualList] based on the given [VirtualListContent]. - pub fn new(virtual_list: T) -> Self { +impl VirtualList { + /// Creates a new [`VirtualList`] that displays `item_count` rows, loading + /// each row as needed by invoking `make_row`. + /// + /// `make_row` will be called each time a new row becomes visible. As rows + /// are no longer visible, they will be freed, ensuring a minimum number of + /// widgets is kept in memory at any given time. + /// + /// Each row will be sized to match the first visible row. To ensure all + /// rows have a consistent size, use the [`Resize`](../Resize) widget. + pub fn new(item_count: impl IntoValue, mut make_row: MakeRow) -> Self + where + MakeRow: FnMut(usize) -> Row + Send + 'static, + Row: MakeWidget, + { + let make_row = RowMaker(Callback::new(move |row| make_row(row).make_widget())); let scroll = Dynamic::>::default(); - let item_height = virtual_list.item_height().into_value().into_dynamic().create_reader(); - let width = virtual_list.width().into_value().into_dynamic().create_reader(); - let item_count = virtual_list.item_count().into_value().into_dynamic().create_reader(); + let item_size = Dynamic::new(Size::ZERO); + let item_count = item_count.into_value().into_dynamic().into_reader(); let content_size = Dynamic::new(Size::default()); let y = scroll.map_each_cloned(|scroll| scroll.y); @@ -71,14 +97,14 @@ impl VirtualList { } }) .persist(); - let vertical = - ScrollBar::new(content_size.map_each_cloned(|size| size.height), y, true); - let max_scroll = (&vertical.max_scroll()) + let vertical = ScrollBar::new(content_size.map_each_cloned(|size| size.height), y, true); + let max_scroll = vertical + .max_scroll() .map_each_cloned(|y| Point::new(UPx::ZERO, y)) .into_reader(); Self { - virtual_list, + make_row, vertical_scroll: OwnedWidget::new(vertical), items: VecDeque::new(), control_size: Dynamic::new(Size::default()), @@ -86,10 +112,9 @@ impl VirtualList { max_scroll, scroll, - item_height, - width, + item_size, item_count, - visible_range: Default::default() + visible_range: Dynamic::default(), } } @@ -134,9 +159,140 @@ impl VirtualList { .expect("a ScrollBar") .hide(context); } + + fn layout_rows( + &mut self, + item_count: usize, + available_space: Size, + context: &mut LayoutContext<'_, '_, '_, '_>, + ) -> Size { + let mut item_size = self.calculate_item_size(available_space, context).ceil(); + + let content_height = item_size.height * u32::try_from(item_count).unwrap_or(u32::MAX); + let content_height = content_height.into_upx(context.gfx.scale()); + + let new_control_size = Size::new( + available_space.width.fill_or_fit(item_size.width), + available_space.height.fill_or_fit(content_height), + ) + .ceil(); + if item_size.width < new_control_size.width { + item_size.width = new_control_size.width; + } + + let vertical = self + .vertical_scroll + .make_if_needed() + .mounted(&mut context.as_event_context()); + let scrollbar_layout = context.for_other(&vertical).layout(available_space); + context.set_child_layout( + &vertical, + Rect::new( + Point::new( + available_space + .width + .fit_measured(new_control_size.width) + .saturating_sub(scrollbar_layout.width) + .into_signed(), + Px::ZERO, + ), + scrollbar_layout.into_signed(), + ), + ); + let scroll = self.scroll.get_tracking_invalidate(context); + + let start_item = (scroll.y.floor() / item_size.height).floor().get() as usize; + let end_item = ((scroll.y.ceil() + new_control_size.height) / item_size.height) + .ceil() + .get() as usize; + let end_item = end_item.min(item_count - 1); + + self.visible_range.set(start_item..end_item); + + let first = self.items.front().map(|t| t.index); + let last = self.items.back().map(|t| t.index); + + if self.items.is_empty() || first.unwrap() > end_item || last.unwrap() < start_item { + for item in self.items.drain(..) { + context.remove_child(&item.mounted); + } + self.items.extend( + (start_item..=end_item).map(|index| self.make_row.make_row(index, context)), + ); + } else { + let first = first.expect("List is not empty"); + let last = last.expect("List is not empty"); + while self + .items + .front() + .map_or(false, |item| item.index < start_item) + { + context.remove_child(&self.items.pop_front().expect("at least one item").mounted); + } + while self + .items + .back() + .map_or(false, |item| item.index > end_item) + { + self.items.pop_back(); + } + // no extend front :( + for item in (start_item..first).rev() { + self.items.push_front(self.make_row.make_row(item, context)); + } + self.items.extend( + ((last + 1)..=end_item).map(|index| self.make_row.make_row(index, context)), + ); + } + + // TODO add % to Figures + let mut y = + -UPx::from_unscaled(scroll.y.into_unscaled() % item_size.height.into_unscaled()) + .into_signed(); + let constraint = item_size.map(ConstraintLimit::SizeToFit); + for item in &self.items { + let child_size = context.for_other(&item.mounted).layout(constraint); + + context.set_child_layout( + &item.mounted, + Rect::new( + Point::new(Px::ZERO, y), + item_size.min(child_size).into_signed(), + ), + ); + y += item_size.height.into_signed(); + } + + self.control_size.set(new_control_size); + self.content_size + .set(Size::new(item_size.width, content_height)); + self.item_size.set(item_size); + + new_control_size + } + + fn calculate_item_size( + &mut self, + available_space: Size, + context: &mut LayoutContext<'_, '_, '_, '_>, + ) -> Size { + if self.items.is_empty() { + self.items.push_front(self.make_row.make_row(0, context)); + } + + context + .for_other( + &self + .items + .front() + .expect("at least one mounted item") + .mounted, + ) + .layout(available_space.map(|space| ConstraintLimit::SizeToFit(space.max()))) + } } -impl Widget for VirtualList { +impl Widget for VirtualList { fn hit_test(&mut self, _location: Point, _context: &mut EventContext<'_>) -> bool { true } @@ -173,104 +329,16 @@ impl Widget for VirtualList { } fn layout( - &mut self, - available_space: Size, - context: &mut cushy::context::LayoutContext<'_, '_, '_, '_>, - ) -> Size { - let item_height = self.item_height.get_tracking_invalidate(context); - let item_height_upx = item_height.into_upx(context.gfx.scale()); + &mut self, + available_space: Size, + context: &mut LayoutContext<'_, '_, '_, '_>, + ) -> Size { let item_count = self.item_count.get_tracking_invalidate(context); - let content_height = item_height * item_count as i32; - let content_height = content_height.into_upx(context.gfx.scale()); - let width = self.width.get_tracking_invalidate(context); - let width = width.into_upx(context.gfx.scale()); - - let new_control_size = Size::new( - width, - constrain_child(available_space.height, content_height), - ); - - let vertical = self - .vertical_scroll - .make_if_needed() - .mounted(&mut context.as_event_context()); - let scrollbar_layout = context.for_other(&vertical).layout(available_space); - context.set_child_layout( - &vertical, - Rect::new( - Point::new( - available_space.width - .fit_measured(new_control_size.width) - .saturating_sub(scrollbar_layout.width) - .into_signed(), - Px::ZERO, - ), - scrollbar_layout.into_signed(), - ), - ); - let scroll = self.scroll.get_tracking_invalidate(context); - - let start_item = (scroll.y / item_height_upx).floor().get() as usize; - let end_item = ((scroll.y + new_control_size.height) / item_height_upx).ceil().get() as usize; - let end_item = end_item.min(item_count-1); - - self.visible_range.set(start_item..end_item); - - let first = self.items.front().map(|t| t.index); - let last = self.items.back().map(|t| t.index); - let mut closure = |index| { - let widget = self.virtual_list.widget_at(index); - let mut widget = widget.widget_ref(); - let mounted = widget.mounted(&mut context.as_event_context()); - VirtualListItem { index, mounted } - }; - if self.items.is_empty() || first.unwrap() > end_item || last.unwrap() < start_item { - self.items.clear(); - self.items.extend((start_item..=end_item).map(closure)); - } else { - let first = first.expect("List is not empty"); - let last = last.expect("List is not empty"); - if first < start_item { - while self.items.front().is_some() && self.items.front().expect("Checked is some").index < start_item { - self.items.pop_front(); - } - } - if last > end_item { - while self.items.back().is_some() && self.items.back().expect("Checked is some").index > end_item { - self.items.pop_back(); - } - } - // no extend front :( - for item in (start_item..first).rev() { - self.items.push_front(closure(item)); - } - self.items.extend(((last+1)..=end_item).map(closure)); + if item_count == 0 { + return available_space.map(ConstraintLimit::min); } - let item_size = Size::new(width, item_height_upx); - let constraint = item_size.map(ConstraintLimit::Fill); - - for item in &self.items { - context.for_other(&item.mounted).layout(constraint); - } - - let item_size = item_size.into_signed(); - let scroll = self.scroll.get_tracking_invalidate(context).into_signed(); - - for item in &self.items { - context.set_child_layout( - &item.mounted, - Rect::new( - Point::new(Px::ZERO, (item_height_upx * item.index as f32).into_signed() - scroll.y), - item_size, - ) - ); - } - - self.control_size.set(new_control_size); - self.content_size.set(Size::new(width, content_height)); - - new_control_size + self.layout_rows(item_count, available_space, context) } fn mouse_wheel( @@ -299,11 +367,3 @@ impl Widget for VirtualList { } } } - -fn constrain_child(constraint: ConstraintLimit, measured: UPx) -> UPx { - match constraint { - ConstraintLimit::Fill(size) => size.min(measured), - // change from Scroll widget: returning just measured here would break the functionality (render too many items) - ConstraintLimit::SizeToFit(size) => size.min(measured), - } -} \ No newline at end of file