refactor: unify month and year calendar views

Signed-off-by: Fabrizio Iannetti <fabrizio.iannetti@gmail.com>
This commit is contained in:
Fabrizio Iannetti 2023-12-09 19:45:05 +01:00
parent aaf6f46316
commit 80a05b0b04
6 changed files with 514 additions and 675 deletions

382
Cargo.lock generated
View File

@ -55,21 +55,6 @@ dependencies = [
"version_check",
]
[[package]]
name = "aho-corasick"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
dependencies = [
"memchr",
]
[[package]]
name = "aliasable"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
[[package]]
name = "allocator-api2"
version = "0.2.16"
@ -576,16 +561,17 @@ dependencies = [
[[package]]
name = "cosmic-text"
version = "0.9.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0b68966c2543609f8d92f9d33ac3b719b2a67529b0c6c0b3e025637b477eef9"
checksum = "75acbfb314aeb4f5210d379af45ed1ec2c98c7f1790bf57b8a4c562ac0c51b71"
dependencies = [
"aliasable",
"fontdb",
"libm",
"log",
"rangemap",
"rustc-hash",
"rustybuzz",
"self_cell",
"swash",
"sys-locale",
"unicode-bidi",
@ -668,6 +654,12 @@ version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.1"
@ -753,16 +745,38 @@ dependencies = [
]
[[package]]
name = "fontdb"
version = "0.14.1"
name = "flume"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8d8cbea8f21307d7e84bca254772981296f058a1d36b461bf4d83a7499fc9e"
checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
dependencies = [
"futures-core",
"futures-sink",
"nanorand",
"spin",
]
[[package]]
name = "fontconfig-parser"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "674e258f4b5d2dcd63888c01c68413c51f565e8af99d2f7701c7b81d79ef41c4"
dependencies = [
"roxmltree",
]
[[package]]
name = "fontdb"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "020e203f177c0fb250fb19455a252e838d2bbbce1f80f25ecc42402aafa8cd38"
dependencies = [
"fontconfig-parser",
"log",
"memmap2 0.6.2",
"memmap2 0.8.0",
"slotmap",
"tinyvec",
"ttf-parser",
"ttf-parser 0.19.0",
]
[[package]]
@ -914,8 +928,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasm-bindgen",
]
[[package]]
@ -924,6 +940,17 @@ version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
[[package]]
name = "gl_generator"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
dependencies = [
"khronos_api",
"log",
"xml-rs",
]
[[package]]
name = "glam"
version = "0.24.0"
@ -938,9 +965,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "glow"
version = "0.12.3"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca0fe580e4b60a8ab24a868bc08e2f03cbcb20d3d676601fa909386713333728"
checksum = "886c2a30b160c4c6fec8f987430c26b526b7988ca71f664e6a699ddf6f9601e4"
dependencies = [
"js-sys",
"slotmap",
@ -948,10 +975,19 @@ dependencies = [
"web-sys",
]
[[package]]
name = "glutin_wgl_sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead"
dependencies = [
"gl_generator",
]
[[package]]
name = "glyphon"
version = "0.3.0"
source = "git+https://github.com/grovesNL/glyphon.git?rev=20f0f8fa80e0d0df4c63634ce9176fa489546ca9#20f0f8fa80e0d0df4c63634ce9176fa489546ca9"
source = "git+https://github.com/grovesNL/glyphon.git?rev=2caa9fc5e5923c1d827d177c3619cab7e9885b85#2caa9fc5e5923c1d827d177c3619cab7e9885b85"
dependencies = [
"cosmic-text",
"etagere",
@ -980,15 +1016,16 @@ dependencies = [
[[package]]
name = "gpu-allocator"
version = "0.22.0"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8"
checksum = "40fe17c8a05d60c38c0a4e5a3c802f2f1ceb66b76c67d96ffb34bef0475a7fad"
dependencies = [
"backtrace",
"log",
"presser",
"thiserror",
"winapi",
"windows 0.44.0",
"windows 0.51.1",
]
[[package]]
@ -1148,8 +1185,9 @@ dependencies = [
"log",
"num-traits",
"palette",
"raw-window-handle",
"thiserror",
"twox-hash",
"xxhash-rust",
]
[[package]]
@ -1174,10 +1212,12 @@ dependencies = [
"half",
"iced_core",
"log",
"once_cell",
"raw-window-handle",
"rustc-hash",
"thiserror",
"twox-hash",
"unicode-segmentation",
"xxhash-rust",
]
[[package]]
@ -1222,8 +1262,8 @@ dependencies = [
"raw-window-handle",
"rustc-hash",
"softbuffer",
"tiny-skia 0.10.0",
"twox-hash",
"tiny-skia 0.11.2",
"xxhash-rust",
]
[[package]]
@ -1263,7 +1303,6 @@ dependencies = [
"iced_runtime",
"iced_style",
"log",
"raw-window-handle",
"thiserror",
"tracing",
"web-sys",
@ -1282,6 +1321,16 @@ dependencies = [
"hashbrown 0.12.3",
]
[[package]]
name = "indexmap"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad227c3af19d4914570ad36d30409928b75967c298feb9ea1969db3a610bb14e"
dependencies = [
"equivalent",
"hashbrown 0.14.0",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -1351,15 +1400,21 @@ dependencies = [
[[package]]
name = "khronos-egl"
version = "4.1.0"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3"
checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76"
dependencies = [
"libc",
"libloading 0.7.4",
"libloading 0.8.0",
"pkg-config",
]
[[package]]
name = "khronos_api"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "kurbo"
version = "0.9.5"
@ -1409,9 +1464,9 @@ dependencies = [
[[package]]
name = "libm"
version = "0.2.7"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "linux-raw-sys"
@ -1431,9 +1486,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.18"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "lru"
@ -1484,9 +1539,9 @@ dependencies = [
[[package]]
name = "memmap2"
version = "0.6.2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872"
checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed"
dependencies = [
"libc",
]
@ -1511,9 +1566,9 @@ dependencies = [
[[package]]
name = "metal"
version = "0.26.0"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "623b5e6cefd76e58f774bd3cc0c6f5c7615c58c03a97815245a25c3c9bdee318"
checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25"
dependencies = [
"bitflags 2.3.3",
"block",
@ -1563,15 +1618,15 @@ dependencies = [
[[package]]
name = "naga"
version = "0.13.0"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ceaaa4eedaece7e4ec08c55c640ba03dbb73fb812a6570a59bcf1930d0f70e"
checksum = "61d829abac9f5230a85d8cc83ec0879b4c09790208ae25b5ea031ef84562e071"
dependencies = [
"bit-set",
"bitflags 2.3.3",
"codespan-reporting",
"hexf-parse",
"indexmap",
"indexmap 2.0.1",
"log",
"num-traits",
"rustc-hash",
@ -1581,6 +1636,15 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "nanorand"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
dependencies = [
"getrandom",
]
[[package]]
name = "ndk"
version = "0.7.0"
@ -1788,9 +1852,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.17.2"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "option-ext"
@ -1813,7 +1877,7 @@ version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "706de7e2214113d63a8238d1910463cfce781129a6f263d13fdb09ff64355ba4"
dependencies = [
"ttf-parser",
"ttf-parser 0.19.0",
]
[[package]]
@ -1979,10 +2043,10 @@ dependencies = [
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
name = "presser"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
[[package]]
name = "prettyplease"
@ -2043,18 +2107,6 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
@ -2063,9 +2115,6 @@ name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "range-alloc"
@ -2075,9 +2124,9 @@ checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab"
[[package]]
name = "rangemap"
version = "1.3.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9283c6b06096b47afc7109834fdedab891175bb5241ee5d4f7d2546549f263"
checksum = "977b1e897f9d764566891689e642653e5ed90c6895106acd005eb4c1d0203991"
[[package]]
name = "raw-window-handle"
@ -2120,8 +2169,6 @@ version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
@ -2137,6 +2184,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b"
[[package]]
name = "roxmltree"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862340e351ce1b271a378ec53f304a5558f7db87f3769dc655a8f6ecbb68b302"
dependencies = [
"xmlparser",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
@ -2164,18 +2220,18 @@ dependencies = [
[[package]]
name = "rustybuzz"
version = "0.8.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82eea22c8f56965eeaf3a209b3d24508256c7b920fb3b6211b8ba0f7c0583250"
checksum = "2ee8fe2a8461a0854a37101fe7a1b13998d0cfa987e43248e81d2a5f4570f6fa"
dependencies = [
"bitflags 1.3.2",
"bytemuck",
"libm",
"smallvec",
"ttf-parser",
"ttf-parser 0.20.0",
"unicode-bidi-mirroring",
"unicode-ccc",
"unicode-general-category",
"unicode-properties",
"unicode-script",
]
@ -2204,6 +2260,12 @@ dependencies = [
"tiny-skia 0.8.4",
]
[[package]]
name = "self_cell"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c309e515543e67811222dbc9e3dd7e1056279b782e1dacffe4242b718734fb6"
[[package]]
name = "shlex"
version = "1.1.0"
@ -2303,6 +2365,15 @@ dependencies = [
"x11rb 0.11.1",
]
[[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.2.0+1.5.4"
@ -2377,12 +2448,11 @@ dependencies = [
[[package]]
name = "sys-locale"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea0b9eefabb91675082b41eb94c3ecd91af7656caee3fb4961a07c0ec8c7ca6f"
checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0"
dependencies = [
"libc",
"windows-sys 0.45.0",
]
[[package]]
@ -2441,9 +2511,9 @@ dependencies = [
[[package]]
name = "tiny-skia"
version = "0.10.0"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7db11798945fa5c3e5490c794ccca7c6de86d3afdd54b4eb324109939c6f37bc"
checksum = "3b72a92a05db376db09fe6d50b7948d106011761c05a6a45e23e17ee9b556222"
dependencies = [
"arrayref",
"arrayvec",
@ -2451,7 +2521,7 @@ dependencies = [
"cfg-if",
"log",
"png",
"tiny-skia-path 0.10.0",
"tiny-skia-path 0.11.2",
]
[[package]]
@ -2467,9 +2537,9 @@ dependencies = [
[[package]]
name = "tiny-skia-path"
version = "0.10.0"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f60aa35c89ac2687ace1a2556eaaea68e8c0d47408a2e3e7f5c98a489e7281c"
checksum = "6ac3865b9708fc7e1961a65c3a4fa55e984272f33092d3c859929f887fceb647"
dependencies = [
"arrayref",
"bytemuck",
@ -2503,7 +2573,7 @@ version = "0.19.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
dependencies = [
"indexmap",
"indexmap 1.9.3",
"toml_datetime",
"winnow",
]
@ -2547,15 +2617,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746"
[[package]]
name = "twox-hash"
version = "1.6.3"
name = "ttf-parser"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
dependencies = [
"cfg-if",
"rand",
"static_assertions",
]
checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"
[[package]]
name = "unicode-bidi"
@ -2575,12 +2640,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1"
[[package]]
name = "unicode-general-category"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2281c8c1d221438e373249e065ca4989c4c36952c211ff21a0ee91c44a3869e7"
[[package]]
name = "unicode-ident"
version = "1.0.9"
@ -2589,13 +2648,15 @@ checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
[[package]]
name = "unicode-linebreak"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137"
dependencies = [
"hashbrown 0.12.3",
"regex",
]
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]]
name = "unicode-properties"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0"
[[package]]
name = "unicode-script"
@ -2876,12 +2937,13 @@ dependencies = [
[[package]]
name = "wgpu"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7472f3b69449a8ae073f6ec41d05b6f846902d92a6c45313c50cb25857b736ce"
checksum = "30e7d227c9f961f2061c26f4cb0fbd4df0ef37e056edd0931783599d6c94ef24"
dependencies = [
"arrayvec",
"cfg-if",
"flume",
"js-sys",
"log",
"naga",
@ -2900,9 +2962,9 @@ dependencies = [
[[package]]
name = "wgpu-core"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecf7454d9386f602f7399225c92dd2fbdcde52c519bc8fb0bd6fbeb388075dc2"
checksum = "837e02ddcdc6d4a9b56ba4598f7fd4202a7699ab03f6ef4dcdebfad2c966aea6"
dependencies = [
"arrayvec",
"bit-vec",
@ -2923,9 +2985,9 @@ dependencies = [
[[package]]
name = "wgpu-hal"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6654a13885a17f475e8324efb46dc6986d7aaaa98353330f8de2077b153d0101"
checksum = "1e30b9a8155c83868e82a8c5d3ce899de6c3961d2ef595de8fc168a1677fc2d8"
dependencies = [
"android_system_properties",
"arrayvec",
@ -2936,6 +2998,7 @@ dependencies = [
"core-graphics-types",
"d3d12",
"glow",
"glutin_wgl_sys",
"gpu-alloc",
"gpu-allocator",
"gpu-descriptor",
@ -2948,6 +3011,7 @@ dependencies = [
"metal",
"naga",
"objc",
"once_cell",
"parking_lot 0.12.1",
"profiling",
"range-alloc",
@ -2964,9 +3028,9 @@ dependencies = [
[[package]]
name = "wgpu-types"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee64d7398d0c2f9ca48922c902ef69c42d000c759f3db41e355f4a570b052b67"
checksum = "0d5ed5f0edf0de351fe311c53304986315ce866f394a2e6df0c4b3c70774bcdd"
dependencies = [
"bitflags 2.3.3",
"js-sys",
@ -3044,22 +3108,32 @@ dependencies = [
"thiserror",
]
[[package]]
name = "windows"
version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b"
dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"windows-targets 0.48.0",
"windows-targets 0.48.5",
]
[[package]]
name = "windows"
version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9"
dependencies = [
"windows-core",
"windows-targets 0.48.5",
]
[[package]]
name = "windows-core"
version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
@ -3077,7 +3151,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.0",
"windows-targets 0.48.5",
]
[[package]]
@ -3097,17 +3171,17 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
"windows_i686_gnu 0.48.0",
"windows_i686_msvc 0.48.0",
"windows_x86_64_gnu 0.48.0",
"windows_x86_64_gnullvm 0.48.0",
"windows_x86_64_msvc 0.48.0",
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
@ -3118,9 +3192,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
@ -3130,9 +3204,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
@ -3142,9 +3216,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
@ -3154,9 +3228,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
@ -3166,9 +3240,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
@ -3178,9 +3252,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
@ -3190,9 +3264,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "winit"
@ -3300,6 +3374,18 @@ version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c"
[[package]]
name = "xmlparser"
version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
[[package]]
name = "xxhash-rust"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9828b178da53440fa9c766a3d2f73f7cf5d0ac1fe3980c1e5018d899fd19e07b"
[[package]]
name = "yazi"
version = "0.1.6"

View File

@ -4,7 +4,7 @@
it is currently in an early development phase.
As a dependency, it requires the iced GUI repository to be cloned alongaside (see `Cargo.toml`)
As a dependency, it requires the iced GUI repository to be cloned alongside (see `Cargo.toml`)
## supported views:

View File

@ -7,7 +7,8 @@ use model::events::EventsCollection;
use model::ical_bridge::load_calendar;
use chrono::{Datelike, NaiveDate, Months, Utc};
use calendar::{CalendarMonthView, CalendarYearView, CalendarParams };
use calendar::{CalendarParams, CalendarView };
use calendar::CalendarViewMode as ViewMode;
use std::path;
use clap;
@ -86,12 +87,6 @@ impl Default for Controls {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ViewMode {
Month,
Year,
}
impl std::fmt::Display for ViewMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
@ -225,16 +220,12 @@ impl Application for CalendarApp {
"novembre",
"dicembre",
];
let mut content = Column::new()
let content = Column::new()
.align_items(Alignment::Center)
.push(self.controls.view(MONTH_NAMES[self.month.month0() as usize], self.month.year()))
.push(CalendarView::new(self.controls.mode.unwrap_or(ViewMode::Year), &CalendarParams::new(), self.month, &self.events))
;
match self.controls.mode {
Some(ViewMode::Year) => content = content.push(CalendarYearView::new(&CalendarParams::new(), self.month, &self.events)),
Some(ViewMode::Month) | None => content = content.push(CalendarMonthView::new(&CalendarParams::new(), self.month, &self.events)),
};
let container = Container::new(content)
.width(Length::Fill)
.height(Length::Fill)

View File

@ -1,2 +1,3 @@
pub mod calendar;
pub mod basics;
mod row;

View File

@ -9,9 +9,12 @@
// implemented by `iced_wgpu` and other renderers.
use super::basics::CellGrid;
use super::row::CalendarRow;
use super::row::RowDay;
use crate::model::events::{Event, EventsCollection};
use chrono::{Datelike, Duration, Local, Months, NaiveDate};
use iced::advanced::text::{self, LineHeight, Shaping, Text, Paragraph};
use iced::advanced::text::Paragraph as _; // this is necessary to have Paragraph in scope and use its methods
use iced::advanced::text::{self, LineHeight, Shaping, Text};
use iced::advanced::widget::{Tree, Widget};
use iced::advanced::{layout, renderer};
use iced::mouse;
@ -32,11 +35,14 @@ const MONTH_NAMES: [&str; 12] = [
const DAY_NAMES: [&str; 7] = ["LUN", "MAR", "MER", "GIO", "VEN", "SAB", "DOM"];
// 5 weeks plus two extra days is enough to accomodate the longest months of 31 days
const YEAR_VIEW_DAYS_PER_ROW: u32 = 5 * 7 + 2;
//-------------------------------------------------------------------------
#[derive(Clone)]
pub struct CalendarParams {
show_weeks: bool,
show_sidebar: bool,
header_fg: Color,
header_bg: Color,
day_fg: Color,
@ -54,7 +60,7 @@ pub struct CalendarParams {
impl CalendarParams {
pub fn new() -> Self {
Self {
show_weeks: true,
show_sidebar: true,
header_fg: Color::BLACK,
header_bg: Color::TRANSPARENT,
day_today_bg: Color::from_rgb8(214, 242, 252),
@ -68,25 +74,38 @@ impl CalendarParams {
ev_fontsize: 16.0,
}
}
pub fn bg_for_day(self: &Self, day: NaiveDate) -> Color {
let weekday = day.weekday().num_days_from_monday();
if day == Local::now().date_naive() {
self.day_today_bg
} else if weekday > 4 {
self.day_weekend_bg
} else {
Color::TRANSPARENT
}
}
}
//-------------------------------------------------------------------------
fn render_events_in_row(
fn render_events_in_row<Renderer>(
params: &CalendarParams,
renderer: &mut impl text::Renderer,
first_day: NaiveDate,
num_days: i64,
renderer: &mut Renderer,
cal_row: CalendarRow,
row_bounds: Rectangle,
min_row_height: f32,
font_size: Pixels,
fg: Color,
content: &str,
events: &EventsCollection,
) {
if num_days < 1 {
) where
Renderer: text::Renderer,
{
if cal_row.begin >= cal_row.end {
return;
}
#[cfg(feature = "tracing")]
tracepoints::calendar::draw_days_entry(row_bounds.width as i32, row_bounds.height as i32);
@ -95,7 +114,7 @@ fn render_events_in_row(
ev: &'a Event,
bounds: Rectangle,
}
let paragraph = renderer.create_paragraph(Text {
let paragraph = Renderer::Paragraph::with_text(Text {
content,
bounds: row_bounds.size(),
size: font_size,
@ -108,8 +127,8 @@ fn render_events_in_row(
let day_text_height = paragraph.min_height();
// render events, if enough space
let last_day = first_day + Duration::days(num_days - 1);
let all_events = events.within(first_day, last_day);
let last_day = cal_row.end.pred_opt().unwrap();
let all_events = events.within(cal_row.begin, last_day);
let x = row_bounds.x;
let y = row_bounds.y + params.day_text_margin + day_text_height;
let ev_height = params.ev_height;
@ -123,7 +142,7 @@ fn render_events_in_row(
ev: e,
bounds: Rectangle {
x,
y: y,
y,
width: 0.0,
height: ev_height,
},
@ -136,18 +155,18 @@ fn render_events_in_row(
row_bounds.y,
row_bounds.width,
row_bounds.height,
num_days.try_into().unwrap(),
cal_row.num_days().try_into().unwrap(),
1,
);
let mut current_day = first_day;
let mut current_day = cal_row.begin;
// update event bars
for cell in row_grid.iter() {
ev_y = y;
for ev_bar in ev_bars.iter_mut() {
if ev_bar.ev.begin == current_day
|| (ev_bar.ev.begin < first_day && current_day == first_day)
|| (ev_bar.ev.begin < cal_row.begin && current_day == cal_row.begin)
{
// start of event
ev_bar.bounds.x = cell.x;
@ -192,6 +211,7 @@ fn render_events_in_row(
},
ev_bar.bounds.position(),
fg,
ev_bar.bounds,
);
ev_y += ev_height
}
@ -200,409 +220,134 @@ fn render_events_in_row(
tracepoints::calendar::draw_days_exit(row_bounds.width as i32, row_bounds.height as i32);
}
//-------------------------------------------------------------------------
pub struct CalendarMonthView<'a> {
fn compute_month_name_width<Renderer>(renderer: &Renderer, bounds: Size, margin: f32, font_size: Pixels) -> f32
where
Renderer: text::Renderer,
{
let mut max_month_width = 0.0;
for month_name in MONTH_NAMES {
let paragraph = Renderer::Paragraph::with_text(Text {
content: month_name,
bounds,
size: font_size,
line_height: LineHeight::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default(),
});
let month_width = paragraph.min_width();
if month_width > max_month_width {
max_month_width = month_width;
}
}
max_month_width + margin
}
//-------------------------------------------------------------------------
fn compute_week_num_width<Renderer>(renderer: &Renderer, bounds: Size, margin: f32, font_size: Pixels) -> f32
where
Renderer: text::Renderer,
{
let mut max_month_width = 0.0;
let paragraph = Renderer::Paragraph::with_text(Text {
content: "55",
bounds,
size: font_size,
line_height: LineHeight::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default(),
});
let month_width = paragraph.min_width();
if month_width > max_month_width {
max_month_width = month_width;
}
max_month_width + margin
}
//-------------------------------------------------------------------------
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CalendarViewMode {
Month,
Year,
}
pub struct CalendarView<'a> {
first_day: NaiveDate,
first_day_in_view: NaiveDate,
params: CalendarParams,
mode: CalendarViewMode,
events: &'a EventsCollection,
week_column_width: f32,
week_column_font_size: f32,
events: &'a EventsCollection,
}
impl<'a> CalendarMonthView<'a> {
pub fn new(params: &CalendarParams, day: NaiveDate, events: &'a EventsCollection) -> Self {
// first day of the month
let first_day = if day.day() == 1 {
day
} else {
NaiveDate::from_ymd_opt(day.year(), day.month(), 1).unwrap()
};
// weekday on first day of the month
let weekday_on_first = first_day.weekday();
// first visible day in the view
let first_day_in_view =
first_day - Duration::days(weekday_on_first.num_days_from_monday() as i64);
Self {
first_day,
first_day_in_view,
params: params.clone(),
week_column_width: 30.0,
week_column_font_size: 18.0,
events,
}
}
pub fn set_month(&mut self, day: NaiveDate) {
// first day of the month
let first_day = if day.day() == 1 {
day
} else {
NaiveDate::from_ymd_opt(day.year(), day.month(), 1).unwrap()
};
// weekday on first day of the month
let weekday_on_first = first_day.weekday();
// first visible day in the view
let first_day_in_view =
first_day - Duration::days(weekday_on_first.num_days_from_monday() as i64);
self.first_day = first_day;
self.first_day_in_view = first_day_in_view;
}
fn draw_header(&self, renderer: &mut impl text::Renderer, bounds: Rectangle, week_w: f32) {
// paint background over full width
if self.params.header_bg != Color::TRANSPARENT {
renderer.fill_quad(
renderer::Quad {
bounds,
border_radius: 0.0.into(),
border_width: 0.0,
border_color: Color::TRANSPARENT,
},
self.params.header_bg,
);
}
// redefine bounds to skip the week column
let bounds = Rectangle {
x: bounds.x + week_w,
y: bounds.y,
width: bounds.width - week_w,
height: bounds.height,
};
// font dimension
let font_size = renderer.default_size();
let h_axis = CellGrid::new(bounds.x, bounds.y, bounds.width, bounds.height, 7, 1);
for cell in h_axis.iter() {
let bounds = Rectangle {
x: cell.x + self.params.day_text_margin,
y: bounds.center_y(),
width: cell.width,
height: bounds.height,
};
// label (day letter on row 0, day number on the rest)
let t = DAY_NAMES[cell.pos_x as usize];
// color of text
let fg = self.params.header_fg;
renderer.fill_text(
Text {
content: t,
bounds: bounds.size(),
size: font_size,
line_height: LineHeight::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
shaping: Shaping::default(),
},
bounds.position(),
fg,
);
}
}
fn draw_week_column(&self, renderer: &mut impl text::Renderer, bounds: Rectangle) {
let mut day = self.first_day;
let v_axis = CellGrid::new(
bounds.x,
bounds.y,
self.week_column_width,
bounds.height,
1,
6,
);
for cell in v_axis.iter() {
// where to place the week number
let day_bounds = Rectangle {
x: bounds.x,
y: cell.y + self.params.day_text_margin,
width: cell.width,
height: cell.height,
};
let week_of_first_day_of_month = day.iso_week().week();
day += Duration::weeks(1);
// render week cell text
renderer.fill_text(
Text {
content: &(week_of_first_day_of_month).to_string(),
bounds: day_bounds.size(),
size: self.week_column_font_size.into(),
line_height: LineHeight::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Center,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default(),
},
Point {
x: day_bounds.center_x(),
y: day_bounds.y,
},
self.params.day_fg,
);
}
}
fn draw_days(&self, renderer: &mut impl text::Renderer, bounds: Rectangle) {
// font dimension
let font_size = renderer.default_size();
let mut current_day = self.first_day_in_view;
let grid = CellGrid::new(bounds.x, bounds.y, bounds.width, bounds.height, 7, 6);
// use the minimum row height to compute available space for event bars
// to avoid inconsistentencies when rowas have slightly different heights
// and some can fit more event bars than others
let min_row_height = grid.compute_min_height();
for row in grid.rows().iter() {
let row_first_day = current_day;
let row_grid = CellGrid::new(row.x, row.y, row.width, row.height, 7, 1);
for cell in row_grid.iter() {
let day_bounds = Rectangle {
x: cell.x,
y: cell.y,
width: cell.width,
height: cell.height,
};
// label (day letter on row 0, day number on the rest)
let t = current_day.day().to_string();
let content = t.as_str();
// color of text
let fg = if current_day.month() == self.first_day.month() {
self.params.day_fg
} else {
self.params.day_other_month_fg
};
// background color of the day cell
let bg_color = if current_day == Local::now().date_naive() {
self.params.day_today_bg
} else if current_day.weekday().num_days_from_monday() > 4 {
self.params.day_weekend_bg
} else {
Color::TRANSPARENT
};
renderer.fill_quad(
renderer::Quad {
bounds: Rectangle {
width: day_bounds.width + 0.5,
height: day_bounds.height + 0.5,
..day_bounds
},
border_radius: 0.0.into(),
border_width: 1.0,
border_color: self.params.day_other_month_fg,
},
bg_color,
);
// render day cell text
renderer.fill_text(
Text {
content,
bounds: day_bounds.size(),
size: font_size,
line_height: LineHeight::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default(),
},
day_bounds.position(),
fg,
);
current_day = current_day.succ_opt().unwrap();
}
let row_bounds = Rectangle {
x: row.x,
y: row.y,
width: row.width,
height: row.height,
};
let content = "10";
render_events_in_row(
&self.params,
renderer,
row_first_day,
6,
row_bounds,
min_row_height,
font_size,
self.params.day_fg,
content,
self.events,
);
}
}
} // CalendarMonthView
impl<Message, Renderer> Widget<Message, Renderer> for CalendarMonthView<'_>
where
Renderer: text::Renderer,
{
fn width(&self) -> Length {
Length::Shrink
}
fn height(&self) -> Length {
Length::Shrink
}
fn layout(
&self,
_tree: &mut Tree,
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
layout::Node::new(limits.max())
}
fn draw(
&self,
_state: &Tree,
renderer: &mut Renderer,
_theme: &Renderer::Theme,
_style: &renderer::Style,
layout: layout::Layout<'_>,
_cursor: mouse::Cursor,
_viewport: &Rectangle,
) {
let bounds = layout.bounds();
let margin: f32 = 20.0;
// week column only visible if there is enough space
let week_w = if self.params.show_weeks && bounds.width > self.week_column_width {
self.week_column_width
} else {
0.0
};
// font and header dimension
let font_size = f32::from(renderer.default_size());
let first_row_h = font_size + margin;
// header
self.draw_header(
renderer,
Rectangle {
height: first_row_h,
..bounds
},
week_w,
);
// week column
if week_w > 0.0 {
let x = bounds.x;
let y = bounds.y + first_row_h;
let width = self.week_column_width;
let height = bounds.height - first_row_h;
self.draw_week_column(
renderer,
Rectangle {
x,
y,
width,
height,
},
);
}
// monthly calendar cells
let x = bounds.x + week_w;
let y = bounds.y + first_row_h;
let width = bounds.width - week_w;
let height = bounds.height - first_row_h;
self.draw_days(
renderer,
Rectangle {
x,
y,
width,
height,
},
);
}
}
impl<'a, Message, Renderer> From<CalendarMonthView<'a>> for Element<'a, Message, Renderer>
where
Renderer: text::Renderer,
{
fn from(month_view: CalendarMonthView<'a>) -> Self {
Self::new(month_view)
}
}
//-------------------------------------------------------------------------
// 5 weeks plus two extra days is enough to accomodate the longest months of 31 days
static YEAR_VIEW_DAYS_PER_ROW: u32 = 5 * 7 + 2;
pub struct CalendarYearView<'a> {
first_day: NaiveDate,
first_day_in_view: NaiveDate,
params: CalendarParams,
month_column_font_size: f32,
row_name_font_size: f32,
margin: f32,
events: &'a EventsCollection,
}
impl<'a> CalendarYearView<'a> {
pub fn new(params: &CalendarParams, day: NaiveDate, events: &'a EventsCollection) -> Self {
// first day of the year
let first_day = NaiveDate::from_ymd_opt(day.year(), 1, 1).unwrap();
impl<'a> CalendarView<'a> {
pub fn new(mode: CalendarViewMode, params: &CalendarParams, day: NaiveDate, events: &'a EventsCollection) -> Self {
let first_day = match mode {
CalendarViewMode::Month => day.with_day0(0),
CalendarViewMode::Year => day.with_month0(0).unwrap().with_day0(0)
}.unwrap();
CalendarView {
first_day,
params: params.clone(),
mode,
events,
week_column_width: 30.0,
row_name_font_size: 24.0,
margin: 10.0,
}
}
// weekday on first day of the year
let weekday_on_first = first_day.weekday();
// first visible day in the view
let first_day_in_view =
first_day - Duration::days(weekday_on_first.num_days_from_monday() as i64);
Self {
first_day,
first_day_in_view,
params: params.clone(),
month_column_font_size: 24.0,
margin: 10.0,
events,
fn get_days_per_row(&self) -> u32 {
match self.mode {
CalendarViewMode::Month => 7, // one week per row -> 7 days
CalendarViewMode::Year => YEAR_VIEW_DAYS_PER_ROW, // one month per row, aligned by weekday
}
}
pub fn set_year(&mut self, day: NaiveDate) {
// first day of the year
self.first_day = NaiveDate::from_ymd_opt(day.year(), 1, 1).unwrap();
// weekday on first day of the year
let weekday_on_first = self.first_day.weekday();
// first visible day in the view
self.first_day_in_view =
self.first_day - Duration::days(weekday_on_first.num_days_from_monday() as i64);
fn get_row_count(&self) -> u32 {
match self.mode {
CalendarViewMode::Month => 6, // one week per row -> max 6 (incomplate) in a month
CalendarViewMode::Year => 12, // one month per row
}
}
fn draw_header(&self, renderer: &mut impl text::Renderer, bounds: Rectangle, week_w: f32) {
fn get_calendar_row(&self, day: NaiveDate, row: u32) -> CalendarRow {
match self.mode {
CalendarViewMode::Month => CalendarRow::for_week(day + Duration::weeks(row.into())),
CalendarViewMode::Year => CalendarRow::for_month(day + Months::new(row)),
}
}
fn get_row_label(&self, cal_row: CalendarRow) -> String {
match self.mode {
CalendarViewMode::Month => (cal_row.begin.iso_week().week()).to_string(),
CalendarViewMode::Year => MONTH_NAMES[cal_row.begin.month0() as usize].to_string(),
}
}
fn get_sidebar_width(&self, renderer: &mut impl text::Renderer, bounds: Size) -> f32 {
let sidebar_width = match self.mode {
CalendarViewMode::Month => compute_week_num_width(renderer, bounds, self.margin, self.row_name_font_size.into()),
CalendarViewMode::Year => compute_month_name_width(renderer, bounds, self.margin, self.row_name_font_size.into()),
};
// side column only visible if there is enough space
if self.params.show_sidebar && bounds.width > sidebar_width {
sidebar_width
} else {
0.0
}
}
fn draw_header(&self, renderer: &mut impl text::Renderer, bounds: Rectangle, side_w: f32) {
// paint background over full width
if self.params.header_bg != Color::TRANSPARENT {
renderer.fill_quad(
@ -616,11 +361,11 @@ impl<'a> CalendarYearView<'a> {
);
}
// redefine bounds to skip the week column
// redefine bounds to skip the side column
let bounds = Rectangle {
x: bounds.x + week_w,
x: bounds.x + side_w,
y: bounds.y,
width: bounds.width - week_w,
width: bounds.width - side_w,
height: bounds.height,
};
@ -634,7 +379,7 @@ impl<'a> CalendarYearView<'a> {
bounds.y,
bounds.width,
bounds.height,
YEAR_VIEW_DAYS_PER_ROW,
self.get_days_per_row(),
1,
);
for cell in grid.iter() {
@ -685,29 +430,31 @@ impl<'a> CalendarYearView<'a> {
},
Point { x, y },
fg,
bounds,
);
}
}
fn draw_month_column(&self, renderer: &mut impl text::Renderer, bounds: Rectangle) {
// dimensions of each box representing a month name
let h: f32 = bounds.height / 12.0;
fn draw_sidebar(&self, renderer: &mut impl text::Renderer, bounds: Rectangle) {
// dimensions of each box representing a row name
let h: f32 = bounds.height / (self.get_row_count() as f32);
for month in 0..12usize {
// where to place the month name
let month_name_bounds = Rectangle {
for row in 0..self.get_row_count() {
let cal_row = self.get_calendar_row(self.first_day, row);
// where to place the row name
let row_name_bounds = Rectangle {
x: bounds.x,
y: (month as f32) * h + bounds.y + self.params.day_text_margin,
y: (row as f32) * h + bounds.y + self.params.day_text_margin,
width: bounds.width,
height: h,
};
// render month name
// render row name
renderer.fill_text(
Text {
content: MONTH_NAMES[month],
bounds: month_name_bounds.size(),
size: self.month_column_font_size.into(),
content: &self.get_row_label(cal_row),
bounds: row_name_bounds.size(),
size: self.row_name_font_size.into(),
line_height: LineHeight::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
@ -715,10 +462,11 @@ impl<'a> CalendarYearView<'a> {
shaping: Shaping::default(),
},
Point {
x: month_name_bounds.x + self.margin,
y: month_name_bounds.center_y(),
x: row_name_bounds.x + self.margin,
y: row_name_bounds.center_y(),
},
self.params.day_fg,
row_name_bounds,
);
}
}
@ -732,14 +480,14 @@ impl<'a> CalendarYearView<'a> {
bounds.y,
bounds.width,
bounds.height,
YEAR_VIEW_DAYS_PER_ROW,
12,
self.get_days_per_row(),
self.get_row_count(),
);
// use the minimum row height to compute available space for event bars
// to avoid inconsistentencies when rowas have slightly different heights
// and some can fit more event bars than others
let min_row_height = grid.compute_min_height();
// use the minimum row height to compute available space for event bars
// to avoid inconsistentencies when rowas have slightly different heights
// and some can fit more event bars than others
let min_row_height = grid.compute_min_height();
for row in grid.rows().iter() {
let row_grid = CellGrid::new(
@ -747,48 +495,38 @@ impl<'a> CalendarYearView<'a> {
row.y,
row.width,
row.height,
YEAR_VIEW_DAYS_PER_ROW,
self.get_days_per_row(),
1,
);
// the row index is the month
let month = row.pos_y;
let first_day_of_month = self
.first_day
.with_day0(0)
.unwrap()
.with_month0(month)
.unwrap();
let first_weekday = first_day_of_month.weekday().num_days_from_monday();
let mut row_bounds: Rectangle = Rectangle {
x: row.x,
y: row.y,
width: row.width,
height: row.height,
};
let row_days = ((first_day_of_month + Months::new(1)) - first_day_of_month).num_days();
let cal_row = self.get_calendar_row(self.first_day, row.pos_y);
for cell in row_grid.iter() {
let day_bounds = Rectangle {
x: cell.x,
y: cell.y,
width: cell.width,
height: cell.height,
};
let current_day = first_day_of_month
+ Duration::days((cell.pos_x as i64) - (first_weekday as i64));
let dat_for_col = cal_row.date_for_col(cell.pos_x.into());
if let RowDay::InRange(current_day) = dat_for_col {
let day_bounds = Rectangle {
x: cell.x,
y: cell.y,
width: cell.width,
height: cell.height,
};
if current_day.month0() == month {
if current_day.day() == 1 {
// update bounds for the rectangle with the actual days
if current_day == cal_row.begin {
let diff = cell.x - row_bounds.x;
row_bounds.x = cell.x;
row_bounds.width -= diff;
} else if current_day.day() == row_days as u32 {
} else if current_day + Duration::days(1) == cal_row.end {
row_bounds.width = cell.x - row_bounds.x + cell.width;
}
let weekday = current_day.weekday().num_days_from_monday();
// label (day letter on row 0, day number on the rest)
// label: day number
let t = current_day.day().to_string();
let content = t.as_str();
@ -796,13 +534,7 @@ impl<'a> CalendarYearView<'a> {
let fg = self.params.day_fg;
// background color of the day cell
let bg_color = if current_day == Local::now().date_naive() {
self.params.day_today_bg
} else if weekday > 4 {
self.params.day_weekend_bg
} else {
Color::TRANSPARENT
};
let bg_color = self.params.bg_for_day(current_day);
renderer.fill_quad(
renderer::Quad {
@ -828,6 +560,7 @@ impl<'a> CalendarYearView<'a> {
},
day_bounds.position(),
fg,
day_bounds,
);
}
}
@ -835,8 +568,7 @@ impl<'a> CalendarYearView<'a> {
render_events_in_row(
&self.params,
renderer,
first_day_of_month,
row_days as i64,
cal_row,
row_bounds,
min_row_height,
font_size,
@ -846,30 +578,9 @@ impl<'a> CalendarYearView<'a> {
);
}
}
}
fn compute_month_col_width(&self, renderer: &mut impl text::Renderer, bounds: Size) -> f32 {
let mut max_max_font_width = 0.0;
for month_name in MONTH_NAMES {
let paragraph = renderer.create_paragraph(Text {
content: month_name,
bounds,
size: renderer.default_size(),
line_height: LineHeight::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default(),
});
let month_width = paragraph.min_width();
if month_width > max_max_font_width {
max_max_font_width = month_width;
}
}
return max_max_font_width + self.margin;
}
} // CalendarYearView
impl<Message, Renderer> Widget<Message, Renderer> for CalendarYearView<'_>
impl<Message, Renderer> Widget<Message, Renderer> for CalendarView<'_>
where
Renderer: text::Renderer,
{
@ -881,17 +592,11 @@ where
Length::Shrink
}
fn layout(
&self,
_tree: &mut Tree,
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits) -> layout::Node {
layout::Node::new(limits.max())
}
fn draw(
&self,
fn draw(&self,
_state: &Tree,
renderer: &mut Renderer,
_theme: &Renderer::Theme,
@ -902,16 +607,9 @@ where
) {
let bounds = layout.bounds();
let margin: f32 = 20.0;
#[cfg(feature = "tracing")]
tracepoints::calendar::draw_entry(bounds.width as i32, bounds.height as i32);
// week column only visible if there is enough space
let month_w = if self.params.show_weeks {
//self.month_column_width
self.compute_month_col_width(renderer, bounds.size()) + self.margin
} else {
0.0
};
// side column only visible if there is enough space
let sidebar_width = self.get_sidebar_width(renderer, bounds.size());
// font and header dimension
let font_size = f32::from(renderer.default_size());
@ -924,16 +622,16 @@ where
height: first_row_h,
..bounds
},
month_w,
sidebar_width,
);
// month column
if month_w > 0.0 && bounds.width > month_w {
// week column
if sidebar_width > 0.0 {
let x = bounds.x;
let y = bounds.y + first_row_h;
let width = month_w;
let width = sidebar_width;
let height = bounds.height - first_row_h;
self.draw_month_column(
self.draw_sidebar(
renderer,
Rectangle {
x,
@ -945,9 +643,9 @@ where
}
// monthly calendar cells
let x = bounds.x + month_w;
let x = bounds.x + sidebar_width;
let y = bounds.y + first_row_h;
let width = bounds.width - month_w;
let width = bounds.width - sidebar_width;
let height = bounds.height - first_row_h;
self.draw_days(
renderer,
@ -958,16 +656,14 @@ where
height,
},
);
#[cfg(feature = "tracing")]
tracepoints::calendar::draw_exit(bounds.width as i32, bounds.height as i32);
}
}
impl<'a, Message, Renderer> From<CalendarYearView<'a>> for Element<'a, Message, Renderer>
impl<'a, Message, Renderer> From<CalendarView<'a>> for Element<'a, Message, Renderer>
where
Renderer: text::Renderer,
{
fn from(year_view: CalendarYearView<'a>) -> Self {
Self::new(year_view)
fn from(month_view: CalendarView<'a>) -> Self {
Self::new(month_view)
}
}

65
src/ui/row.rs Normal file
View File

@ -0,0 +1,65 @@
use chrono::{Datelike, Duration, Months, NaiveDate, Weekday};
#[derive(Debug)]
pub struct CalendarRow {
pub begin: NaiveDate,
pub end: NaiveDate,
}
pub enum RowDay {
InRange(NaiveDate),
NotInRange(NaiveDate),
}
impl RowDay {
pub fn new(row: &CalendarRow, day: NaiveDate) -> RowDay {
if day >= row.begin && day < row.end {
RowDay::InRange(day)
} else {
RowDay::NotInRange(day)
}
}
pub fn day(self) -> NaiveDate {
match self {
Self::InRange(day) => day,
Self::NotInRange(day) => day,
}
}
}
/// A row in the calendar.
///
/// The row is always aligned to a week, i.e. the first
/// day of the row is the first day of the week (for now always Monday)
impl CalendarRow {
/// A row that spans the month containing the given day
pub fn for_month(day: NaiveDate) -> CalendarRow {
let begin = day.with_day0(0).unwrap();
CalendarRow {
begin,
end: begin + Months::new(1),
}
}
/// A row that spans the week containing the given day
pub fn for_week(day: NaiveDate) -> CalendarRow {
let begin = day.week(Weekday::Mon).first_day();
CalendarRow {
begin,
end: begin + Duration::weeks(1),
}
}
/// Get the day for the given column of the row
pub fn date_for_col(self: &Self, col: i64) -> RowDay {
RowDay::new(
self,
self.begin.week(Weekday::Mon).first_day() + Duration::days(col),
)
}
pub fn num_days(&self) -> i64 {
(self.end - self.begin).num_days()
}
}