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

View File

@ -4,7 +4,7 @@
it is currently in an early development phase. 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: ## supported views:

View File

@ -7,7 +7,8 @@ use model::events::EventsCollection;
use model::ical_bridge::load_calendar; use model::ical_bridge::load_calendar;
use chrono::{Datelike, NaiveDate, Months, Utc}; use chrono::{Datelike, NaiveDate, Months, Utc};
use calendar::{CalendarMonthView, CalendarYearView, CalendarParams }; use calendar::{CalendarParams, CalendarView };
use calendar::CalendarViewMode as ViewMode;
use std::path; use std::path;
use clap; 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 { impl std::fmt::Display for ViewMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!( write!(
@ -225,16 +220,12 @@ impl Application for CalendarApp {
"novembre", "novembre",
"dicembre", "dicembre",
]; ];
let mut content = Column::new() let content = Column::new()
.align_items(Alignment::Center) .align_items(Alignment::Center)
.push(self.controls.view(MONTH_NAMES[self.month.month0() as usize], self.month.year())) .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) let container = Container::new(content)
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fill) .height(Length::Fill)

View File

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

View File

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