add layer button
This commit is contained in:
parent
b70b86e71c
commit
79189212c2
459
Cargo.lock
generated
459
Cargo.lock
generated
@ -37,6 +37,21 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
@ -274,6 +289,20 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-targets 0.48.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cinrad_g"
|
||||
version = "0.1.0"
|
||||
@ -298,6 +327,8 @@ dependencies = [
|
||||
"ndarray",
|
||||
"npyz",
|
||||
"num-traits",
|
||||
"plotters",
|
||||
"plotters-backend",
|
||||
"proj",
|
||||
"proj-sys",
|
||||
"proj5",
|
||||
@ -308,6 +339,7 @@ dependencies = [
|
||||
"shapefile",
|
||||
"svg",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"topojson",
|
||||
]
|
||||
|
||||
@ -362,12 +394,70 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "const-cstr"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"core-graphics-types",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-text"
|
||||
version = "19.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"
|
||||
dependencies = [
|
||||
"core-foundation",
|
||||
"core-graphics",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.8"
|
||||
@ -532,6 +622,48 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlib"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
|
||||
dependencies = [
|
||||
"libloading 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dwrote"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"winapi",
|
||||
"wio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "earcutr"
|
||||
version = "0.4.2"
|
||||
@ -643,7 +775,7 @@ checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.2.16",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
@ -657,6 +789,12 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "float-ord"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e"
|
||||
|
||||
[[package]]
|
||||
name = "float_next_after"
|
||||
version = "1.0.0"
|
||||
@ -682,12 +820,73 @@ version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "font-kit"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21fe28504d371085fae9ac7a3450f0b289ab71e07c8e57baa3fb68b9e57d6ce5"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"byteorder",
|
||||
"core-foundation",
|
||||
"core-graphics",
|
||||
"core-text",
|
||||
"dirs-next",
|
||||
"dwrote",
|
||||
"float-ord",
|
||||
"freetype",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"pathfinder_geometry",
|
||||
"pathfinder_simd",
|
||||
"walkdir",
|
||||
"winapi",
|
||||
"yeslogic-fontconfig-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "fragile"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
|
||||
|
||||
[[package]]
|
||||
name = "freetype"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6"
|
||||
dependencies = [
|
||||
"freetype-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "freetype-sys"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a"
|
||||
dependencies = [
|
||||
"cmake",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.28"
|
||||
@ -1278,6 +1477,29 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
@ -1459,6 +1681,17 @@ version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
|
||||
dependencies = [
|
||||
"bitflags 2.3.3",
|
||||
"libc",
|
||||
"redox_syscall 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.10"
|
||||
@ -1757,6 +1990,25 @@ dependencies = [
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathfinder_geometry"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pathfinder_simd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathfinder_simd"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0444332826c70dc47be74a7c6a5fc44e23a7905ad6858d4162b658320455ef93"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.11.0"
|
||||
@ -1841,9 +2093,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.10"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
|
||||
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
@ -1857,6 +2109,52 @@ version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"font-kit",
|
||||
"image",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"pathfinder_geometry",
|
||||
"plotters-backend",
|
||||
"plotters-bitmap",
|
||||
"plotters-svg",
|
||||
"ttf-parser 0.17.1",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-bitmap"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cebbe1f70205299abc69e8b295035bb52a6a70ee35474ad10011f0a4efb8543"
|
||||
dependencies = [
|
||||
"gif",
|
||||
"image",
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.9"
|
||||
@ -2056,6 +2354,26 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libredox",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.8.4"
|
||||
@ -2169,7 +2487,7 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bytemuck",
|
||||
"smallvec",
|
||||
"ttf-parser",
|
||||
"ttf-parser 0.18.1",
|
||||
"unicode-bidi-mirroring",
|
||||
"unicode-ccc",
|
||||
"unicode-general-category",
|
||||
@ -2182,6 +2500,15 @@ version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
version = "0.1.9"
|
||||
@ -2488,11 +2815,10 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.29.1"
|
||||
version = "1.35.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
|
||||
checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"backtrace",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
@ -2596,6 +2922,12 @@ dependencies = [
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "375812fa44dab6df41c195cd2f7fecb488f6c09fbaafb62807488cefab642bff"
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.18.1"
|
||||
@ -2686,6 +3018,16 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
@ -2804,13 +3146,22 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2819,13 +3170,28 @@ version = "0.48.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.0",
|
||||
"windows_aarch64_msvc 0.52.0",
|
||||
"windows_i686_gnu 0.52.0",
|
||||
"windows_i686_msvc 0.52.0",
|
||||
"windows_x86_64_gnu 0.52.0",
|
||||
"windows_x86_64_gnullvm 0.52.0",
|
||||
"windows_x86_64_msvc 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2834,42 +3200,84 @@ version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.4.7"
|
||||
@ -2879,6 +3287,15 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wio"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11"
|
||||
version = "2.21.0"
|
||||
@ -2907,6 +3324,18 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yeslogic-fontconfig-sys"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2bbd69036d397ebbff671b1b8e4d918610c181c5a16073b96f984a38d08c386"
|
||||
dependencies = [
|
||||
"const-cstr",
|
||||
"dlib",
|
||||
"once_cell",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.6.6"
|
||||
|
||||
@ -38,6 +38,10 @@ rstar = "*"
|
||||
geo = "0.26.0"
|
||||
topojson = "0.5.1"
|
||||
geojson = "0.24.1"
|
||||
plotters = "0.3.5"
|
||||
plotters-backend = "0.3.5"
|
||||
tokio = "1.35.1"
|
||||
# plotters-cairo = "0.5.0"
|
||||
|
||||
|
||||
|
||||
|
||||
8
back.txt
8
back.txt
@ -77,3 +77,11 @@
|
||||
// RenderConfig { padding: [50.0;4] }
|
||||
// )
|
||||
// )
|
||||
|
||||
|
||||
|
||||
// Layer::grid_render_layer_with_path(
|
||||
// "/users/tsuki/projects/radar-g/test2.npz",
|
||||
// Npz,
|
||||
// BoundaryNorm::default(),
|
||||
// )
|
||||
|
||||
341
src/chart/backend.rs
Normal file
341
src/chart/backend.rs
Normal file
@ -0,0 +1,341 @@
|
||||
use cairo::{Context as CairoContext, FontSlant, FontWeight};
|
||||
|
||||
use plotters_backend::text_anchor::{HPos, VPos};
|
||||
#[allow(unused_imports)]
|
||||
use plotters_backend::{
|
||||
BackendColor, BackendCoord, BackendStyle, BackendTextStyle, DrawingBackend, DrawingErrorKind,
|
||||
FontStyle, FontTransform,
|
||||
};
|
||||
|
||||
|
||||
/// The drawing backend that is backed with a Cairo context
|
||||
pub struct CairoBackend<'a> {
|
||||
context: &'a CairoContext,
|
||||
width: u32,
|
||||
height: u32,
|
||||
init_flag: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CairoError;
|
||||
|
||||
impl std::fmt::Display for CairoError {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(fmt, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for CairoError {}
|
||||
|
||||
impl<'a> CairoBackend<'a> {
|
||||
fn set_color(&self, color: &BackendColor) {
|
||||
self.context.set_source_rgba(
|
||||
f64::from(color.rgb.0) / 255.0,
|
||||
f64::from(color.rgb.1) / 255.0,
|
||||
f64::from(color.rgb.2) / 255.0,
|
||||
color.alpha,
|
||||
);
|
||||
}
|
||||
|
||||
fn set_stroke_width(&self, width: u32) {
|
||||
self.context.set_line_width(f64::from(width));
|
||||
}
|
||||
|
||||
fn set_font<S: BackendTextStyle>(&self, font: &S) {
|
||||
match font.style() {
|
||||
FontStyle::Normal => self.context.select_font_face(
|
||||
font.family().as_str(),
|
||||
FontSlant::Normal,
|
||||
FontWeight::Normal,
|
||||
),
|
||||
FontStyle::Bold => self.context.select_font_face(
|
||||
font.family().as_str(),
|
||||
FontSlant::Normal,
|
||||
FontWeight::Bold,
|
||||
),
|
||||
FontStyle::Oblique => self.context.select_font_face(
|
||||
font.family().as_str(),
|
||||
FontSlant::Oblique,
|
||||
FontWeight::Normal,
|
||||
),
|
||||
FontStyle::Italic => self.context.select_font_face(
|
||||
font.family().as_str(),
|
||||
FontSlant::Italic,
|
||||
FontWeight::Normal,
|
||||
),
|
||||
};
|
||||
self.context.set_font_size(font.size());
|
||||
}
|
||||
|
||||
pub fn new(context: &'a CairoContext, (w, h): (u32, u32)) -> Result<Self, CairoError> {
|
||||
Ok(Self {
|
||||
context,
|
||||
width: w,
|
||||
height: h,
|
||||
init_flag: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DrawingBackend for CairoBackend<'a> {
|
||||
type ErrorType = cairo::Error;
|
||||
|
||||
fn get_size(&self) -> (u32, u32) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
|
||||
fn ensure_prepared(&mut self) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
|
||||
if !self.init_flag {
|
||||
let (x0, y0, x1, y1) = self
|
||||
.context
|
||||
.clip_extents()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
|
||||
self.context.scale(
|
||||
(x1 - x0) / f64::from(self.width),
|
||||
(y1 - y0) / f64::from(self.height),
|
||||
);
|
||||
|
||||
self.init_flag = true;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn present(&mut self) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_pixel(
|
||||
&mut self,
|
||||
point: BackendCoord,
|
||||
color: BackendColor,
|
||||
) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
|
||||
self.context
|
||||
.rectangle(f64::from(point.0), f64::from(point.1), 1.0, 1.0);
|
||||
self.context.set_source_rgba(
|
||||
f64::from(color.rgb.0) / 255.0,
|
||||
f64::from(color.rgb.1) / 255.0,
|
||||
f64::from(color.rgb.2) / 255.0,
|
||||
color.alpha,
|
||||
);
|
||||
|
||||
self.context
|
||||
.fill()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_line<S: BackendStyle>(
|
||||
&mut self,
|
||||
from: BackendCoord,
|
||||
to: BackendCoord,
|
||||
style: &S,
|
||||
) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
|
||||
self.set_color(&style.color());
|
||||
self.set_stroke_width(style.stroke_width());
|
||||
|
||||
self.context.move_to(f64::from(from.0), f64::from(from.1));
|
||||
self.context.line_to(f64::from(to.0), f64::from(to.1));
|
||||
|
||||
self.context
|
||||
.stroke()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_rect<S: BackendStyle>(
|
||||
&mut self,
|
||||
upper_left: BackendCoord,
|
||||
bottom_right: BackendCoord,
|
||||
style: &S,
|
||||
fill: bool,
|
||||
) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
|
||||
self.set_color(&style.color());
|
||||
self.set_stroke_width(style.stroke_width());
|
||||
|
||||
self.context.rectangle(
|
||||
f64::from(upper_left.0),
|
||||
f64::from(upper_left.1),
|
||||
f64::from(bottom_right.0 - upper_left.0),
|
||||
f64::from(bottom_right.1 - upper_left.1),
|
||||
);
|
||||
|
||||
if fill {
|
||||
self.context
|
||||
.fill()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
} else {
|
||||
self.context
|
||||
.stroke()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_path<S: BackendStyle, I: IntoIterator<Item = BackendCoord>>(
|
||||
&mut self,
|
||||
path: I,
|
||||
style: &S,
|
||||
) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
|
||||
self.set_color(&style.color());
|
||||
self.set_stroke_width(style.stroke_width());
|
||||
|
||||
let mut path = path.into_iter();
|
||||
if let Some((x, y)) = path.next() {
|
||||
self.context.move_to(f64::from(x), f64::from(y));
|
||||
}
|
||||
|
||||
for (x, y) in path {
|
||||
self.context.line_to(f64::from(x), f64::from(y));
|
||||
}
|
||||
|
||||
self.context
|
||||
.stroke()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fill_polygon<S: BackendStyle, I: IntoIterator<Item = BackendCoord>>(
|
||||
&mut self,
|
||||
path: I,
|
||||
style: &S,
|
||||
) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
|
||||
self.set_color(&style.color());
|
||||
self.set_stroke_width(style.stroke_width());
|
||||
|
||||
let mut path = path.into_iter();
|
||||
|
||||
if let Some((x, y)) = path.next() {
|
||||
self.context.move_to(f64::from(x), f64::from(y));
|
||||
|
||||
for (x, y) in path {
|
||||
self.context.line_to(f64::from(x), f64::from(y));
|
||||
}
|
||||
|
||||
self.context.close_path();
|
||||
self.context
|
||||
.fill()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_circle<S: BackendStyle>(
|
||||
&mut self,
|
||||
center: BackendCoord,
|
||||
radius: u32,
|
||||
style: &S,
|
||||
fill: bool,
|
||||
) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
|
||||
self.set_color(&style.color());
|
||||
self.set_stroke_width(style.stroke_width());
|
||||
|
||||
self.context.new_sub_path();
|
||||
self.context.arc(
|
||||
f64::from(center.0),
|
||||
f64::from(center.1),
|
||||
f64::from(radius),
|
||||
0.0,
|
||||
std::f64::consts::PI * 2.0,
|
||||
);
|
||||
|
||||
if fill {
|
||||
self.context
|
||||
.fill()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
} else {
|
||||
self.context
|
||||
.stroke()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn estimate_text_size<S: BackendTextStyle>(
|
||||
&self,
|
||||
text: &str,
|
||||
font: &S,
|
||||
) -> Result<(u32, u32), DrawingErrorKind<Self::ErrorType>> {
|
||||
self.set_font(font);
|
||||
|
||||
let extents = self
|
||||
.context
|
||||
.text_extents(text)
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
|
||||
Ok((extents.width() as u32, extents.height() as u32))
|
||||
}
|
||||
|
||||
fn draw_text<S: BackendTextStyle>(
|
||||
&mut self,
|
||||
text: &str,
|
||||
style: &S,
|
||||
pos: BackendCoord,
|
||||
) -> Result<(), DrawingErrorKind<Self::ErrorType>> {
|
||||
let color = style.color();
|
||||
let (mut x, mut y) = (pos.0, pos.1);
|
||||
|
||||
let degree = match style.transform() {
|
||||
FontTransform::None => 0.0,
|
||||
FontTransform::Rotate90 => 90.0,
|
||||
FontTransform::Rotate180 => 180.0,
|
||||
FontTransform::Rotate270 => 270.0,
|
||||
//FontTransform::RotateAngle(angle) => angle as f64,
|
||||
} / 180.0
|
||||
* std::f64::consts::PI;
|
||||
|
||||
if degree != 0.0 {
|
||||
self.context
|
||||
.save()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
self.context.translate(f64::from(x), f64::from(y));
|
||||
self.context.rotate(degree);
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
self.set_font(style);
|
||||
self.set_color(&color);
|
||||
|
||||
let extents = self
|
||||
.context
|
||||
.text_extents(text)
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
|
||||
let dx = match style.anchor().h_pos {
|
||||
HPos::Left => 0.0,
|
||||
HPos::Right => -extents.width(),
|
||||
HPos::Center => -extents.width() / 2.0,
|
||||
};
|
||||
let dy = match style.anchor().v_pos {
|
||||
VPos::Top => extents.height(),
|
||||
VPos::Center => extents.height() / 2.0,
|
||||
VPos::Bottom => 0.0,
|
||||
};
|
||||
|
||||
self.context.move_to(
|
||||
f64::from(x) + dx - extents.x_bearing(),
|
||||
f64::from(y) + dy - extents.y_bearing() - extents.height(),
|
||||
);
|
||||
|
||||
self.context
|
||||
.show_text(text)
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
|
||||
if degree != 0.0 {
|
||||
self.context
|
||||
.restore()
|
||||
.map_err(DrawingErrorKind::DrawingError)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
19
src/chart/imp.rs
Normal file
19
src/chart/imp.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::{glib, prelude::WidgetExtManual};
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Chart {}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for Chart {
|
||||
const NAME: &'static str = "Chart";
|
||||
type Type = super::Chart;
|
||||
type ParentType = gtk::DrawingArea;
|
||||
}
|
||||
|
||||
impl ObjectImpl for Chart {}
|
||||
|
||||
impl WidgetImpl for Chart {}
|
||||
|
||||
impl DrawingAreaImpl for Chart {}
|
||||
110
src/chart/mod.rs
Normal file
110
src/chart/mod.rs
Normal file
@ -0,0 +1,110 @@
|
||||
mod backend;
|
||||
mod imp;
|
||||
use self::backend::CairoBackend;
|
||||
use crate::render::{Render, RenderConfig, RenderMotion};
|
||||
use glib::{clone, ObjectExt};
|
||||
use gtk::prelude::*;
|
||||
use gtk::{glib, AspectFrame};
|
||||
use plotters::prelude::*;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct Chart(ObjectSubclass<imp::Chart>)
|
||||
@extends gtk::DrawingArea, gtk::Widget;
|
||||
}
|
||||
|
||||
impl Chart {
|
||||
pub fn new() -> Self {
|
||||
let this: Self = glib::Object::new();
|
||||
this.set_hexpand(true);
|
||||
this.set_vexpand(true);
|
||||
|
||||
this.set_draw_func(|_s, context, w, h| {
|
||||
let root_area = CairoBackend::new(context, (w as u32, h as u32))
|
||||
.expect("Can't create backend")
|
||||
.into_drawing_area();
|
||||
root_area.fill(&BLACK).unwrap();
|
||||
|
||||
let root_area = root_area.titled("Image Title", ("sans-serif", 60)).unwrap();
|
||||
|
||||
let (upper, lower) = root_area.split_vertically(512);
|
||||
|
||||
let x_axis = (-3.4f32..3.4).step(0.1);
|
||||
|
||||
let mut cc = ChartBuilder::on(&upper)
|
||||
.margin(5)
|
||||
.set_all_label_area_size(50)
|
||||
.caption("Sine and Cosine", ("sans-serif", 40))
|
||||
.build_cartesian_2d(-3.4f32..3.4, -1.2f32..1.2f32).unwrap();
|
||||
|
||||
cc.configure_mesh()
|
||||
.x_labels(20)
|
||||
.y_labels(10)
|
||||
.disable_mesh()
|
||||
.x_label_formatter(&|v| format!("{:.1}", v))
|
||||
.y_label_formatter(&|v| format!("{:.1}", v))
|
||||
.draw().unwrap();
|
||||
|
||||
cc.draw_series(LineSeries::new(x_axis.values().map(|x| (x, x.sin())), &RED)).unwrap()
|
||||
.label("Sine")
|
||||
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], RED));
|
||||
|
||||
cc.draw_series(LineSeries::new(
|
||||
x_axis.values().map(|x| (x, x.cos())),
|
||||
&BLUE,
|
||||
)).unwrap()
|
||||
.label("Cosine")
|
||||
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], BLUE));
|
||||
|
||||
cc.configure_series_labels().border_style(WHITE).draw().unwrap();
|
||||
|
||||
/*
|
||||
// It's possible to use a existing pointing element
|
||||
cc.draw_series(PointSeries::<_, _, Circle<_>>::new(
|
||||
(-3.0f32..2.1f32).step(1.0).values().map(|x| (x, x.sin())),
|
||||
5,
|
||||
Into::<ShapeStyle>::into(&RGBColor(255,0,0)).filled(),
|
||||
)).unwrap();*/
|
||||
|
||||
// Otherwise you can use a function to construct your pointing element yourself
|
||||
cc.draw_series(PointSeries::of_element(
|
||||
(-3.0f32..2.1f32).step(1.0).values().map(|x| (x, x.sin())),
|
||||
5,
|
||||
ShapeStyle::from(&RED).filled(),
|
||||
&|coord, size, style| {
|
||||
EmptyElement::at(coord)
|
||||
+ Circle::new((0, 0), size, style)
|
||||
+ Text::new(format!("{:.?}", coord), (0, 15), ("sans-serif", 15))
|
||||
},
|
||||
)).unwrap();
|
||||
|
||||
let drawing_areas = lower.split_evenly((1, 2));
|
||||
|
||||
for (drawing_area, idx) in drawing_areas.iter().zip(1..) {
|
||||
let mut cc = ChartBuilder::on(drawing_area)
|
||||
.x_label_area_size(30)
|
||||
.y_label_area_size(30)
|
||||
.margin_right(20)
|
||||
.caption(format!("y = x^{}", 1 + 2 * idx), ("sans-serif", 40))
|
||||
.build_cartesian_2d(-1f32..1f32, -1f32..1f32).unwrap();
|
||||
cc.configure_mesh()
|
||||
.x_labels(5)
|
||||
.y_labels(3)
|
||||
.max_light_lines(4)
|
||||
.draw().unwrap();
|
||||
|
||||
cc.draw_series(LineSeries::new(
|
||||
(-1f32..1f32)
|
||||
.step(0.01)
|
||||
.values()
|
||||
.map(|x| (x, x.powf(idx as f32 * 2.0 + 1.0))),
|
||||
&BLUE,
|
||||
)).unwrap();
|
||||
}
|
||||
|
||||
// To avoid the IO failure being ignored silently, we manually call the present function
|
||||
root_area.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir");
|
||||
});
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,34 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::render::Layer;
|
||||
|
||||
pub enum MonitorInputMsg {
|
||||
AddLayer(Layer),
|
||||
RemoveLayer(usize),
|
||||
UpdateLayer((usize, Box<dyn Fn(&mut Layer) + 'static>)),
|
||||
None,
|
||||
}
|
||||
|
||||
impl Debug for MonitorInputMsg {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MonitorInputMsg::AddLayer(_) => write!(f, "MonitorInputMsg::AddLayer"),
|
||||
MonitorInputMsg::RemoveLayer(_) => write!(f, "MonitorInputMsg::RemoveLayer"),
|
||||
MonitorInputMsg::UpdateLayer(_) => write!(f, "MonitorInputMsg::UpdateLayer"),
|
||||
MonitorInputMsg::None => write!(f, "MonitorInputMsg::None"),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MonitorOutputMsg {
|
||||
LayerAdded(usize),
|
||||
LayerRemoved(usize),
|
||||
LayerUpdated(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RenderInputMsg {
|
||||
AddLayer(Layer),
|
||||
RemoveLayer(usize),
|
||||
MoveLayer(usize, usize),
|
||||
SetLayerVisibility(usize, bool),
|
||||
EditLayer(usize),
|
||||
Monitor(MonitorInputMsg),
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pub mod monitor;
|
||||
pub mod sidebar;
|
||||
pub mod render;
|
||||
pub mod sidebar;
|
||||
pub use monitor::MonitorModel;
|
||||
|
||||
@ -1,23 +1,46 @@
|
||||
use super::{render::render::RenderModel, sidebar::sidebar::SideBarModel};
|
||||
use crate::{
|
||||
components::render_panel::messages::{MonitorInputMsg, MonitorOutputMsg},
|
||||
render::{Layer, Render},
|
||||
};
|
||||
|
||||
use super::{render::render::RenderModel, sidebar::{sidebar::SideBarModel, SideBarOutputMsg}};
|
||||
use adw::prelude::*;
|
||||
use relm4::*;
|
||||
pub struct MonitorModel {
|
||||
render: Controller<RenderModel>,
|
||||
sidebar_open: bool,
|
||||
sidebar_width: i32,
|
||||
layers: Vec<Layer>,
|
||||
sidebar: Controller<SideBarModel>,
|
||||
}
|
||||
|
||||
pub struct MonitorWidgets {
|
||||
paned: gtk::Paned,
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for MonitorModel {
|
||||
type Init = ();
|
||||
type Output = ();
|
||||
type Input = ();
|
||||
type Output = MonitorOutputMsg;
|
||||
type Input = MonitorInputMsg;
|
||||
|
||||
view! {
|
||||
adw::OverlaySplitView {
|
||||
set_sidebar_position:gtk::PackType::End,
|
||||
adw::BreakpointBin {
|
||||
set_hexpand: true,
|
||||
set_vexpand: true,
|
||||
set_height_request: 500,
|
||||
set_width_request: 700,
|
||||
#[wrap(Some)]
|
||||
set_sidebar = &adw::NavigationPage::builder().title("sidebar").child(model.sidebar.widget()).build(),
|
||||
set_child=>k::Paned{
|
||||
set_position: 1000,
|
||||
#[wrap(Some)]
|
||||
set_content = &adw::NavigationPage::builder().title("content").child(model.render.widget()).build(),
|
||||
#[name="render"]
|
||||
set_start_child=&Render{
|
||||
#[watch]
|
||||
set_interior_layers: model.layers.clone(),
|
||||
},
|
||||
#[wrap(Some)]
|
||||
set_end_child=model.sidebar.widget(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,19 +51,45 @@ impl SimpleComponent for MonitorModel {
|
||||
) -> relm4::ComponentParts<Self> {
|
||||
let sidebar: Controller<SideBarModel> = SideBarModel::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), |msg| {});
|
||||
let render: Controller<RenderModel> = RenderModel::builder()
|
||||
.launch((None, None))
|
||||
.forward(sender.input_sender(), |msg| {});
|
||||
|
||||
let model = MonitorModel { render, sidebar };
|
||||
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
.forward(sender.input_sender(), |msg| match msg {
|
||||
SideBarOutputMsg::NewLayer(layer) => MonitorInputMsg::AddLayer(layer),
|
||||
});
|
||||
let model = MonitorModel {
|
||||
sidebar_open: true,
|
||||
sidebar_width: 400,
|
||||
layers: vec![],
|
||||
sidebar,
|
||||
};
|
||||
|
||||
let widgets = view_output! {};
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {}
|
||||
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
|
||||
match msg {
|
||||
MonitorInputMsg::AddLayer(layer) => {
|
||||
self.layers.push(layer);
|
||||
_sender
|
||||
.output_sender()
|
||||
.send(MonitorOutputMsg::LayerAdded(0))
|
||||
.unwrap();
|
||||
}
|
||||
MonitorInputMsg::RemoveLayer(index) => {
|
||||
self.layers.remove(index);
|
||||
_sender
|
||||
.output_sender()
|
||||
.send(MonitorOutputMsg::LayerRemoved(0))
|
||||
.unwrap();
|
||||
}
|
||||
MonitorInputMsg::UpdateLayer((idx, f)) => {
|
||||
f(&mut self.layers[idx]);
|
||||
_sender
|
||||
.output_sender()
|
||||
.send(MonitorOutputMsg::LayerUpdated(0))
|
||||
.unwrap();
|
||||
}
|
||||
MonitorInputMsg::None => {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
use relm4::{
|
||||
binding::{Binding, U8Binding},
|
||||
@ -5,6 +6,8 @@ use relm4::{
|
||||
typed_list_view::{RelmListItem, TypedListView},
|
||||
RelmObjectExt,
|
||||
};
|
||||
|
||||
use crate::{chart::Chart, render::{Layer, predefined::color_mapper::BoundaryNorm}, data::Npz};
|
||||
pub struct SideBarModel {
|
||||
counter: u8,
|
||||
list_view_wrapper: TypedListView<MyListItem, gtk::SingleSelection>,
|
||||
@ -17,10 +20,15 @@ pub enum Msg {
|
||||
OnlyShowEven(bool),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SideBarOutputMsg {
|
||||
NewLayer(Layer),
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for SideBarModel {
|
||||
type Init = ();
|
||||
type Output = ();
|
||||
type Output = SideBarOutputMsg;
|
||||
type Input = Msg;
|
||||
|
||||
view! {
|
||||
@ -33,17 +41,21 @@ impl SimpleComponent for SideBarModel {
|
||||
append_page:(&page_1, Some(&label)),
|
||||
},
|
||||
gtk::Button {
|
||||
set_label: "Append 10 items",
|
||||
connect_clicked => Msg::Append,
|
||||
set_label: "Add Layer",
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.output(
|
||||
SideBarOutputMsg::NewLayer(
|
||||
Layer::grid_render_layer_with_path(
|
||||
"/users/tsuki/projects/radar-g/test2.npz",
|
||||
Npz,
|
||||
BoundaryNorm::default(),
|
||||
)
|
||||
)
|
||||
).unwrap()
|
||||
},
|
||||
|
||||
gtk::Button {
|
||||
set_label: "Remove second item",
|
||||
connect_clicked => Msg::Remove,
|
||||
},
|
||||
gtk::ScrolledWindow {
|
||||
set_vexpand: true,
|
||||
|
||||
#[local_ref]
|
||||
my_view -> gtk::ListView {}
|
||||
}
|
||||
@ -69,7 +81,19 @@ impl SimpleComponent for SideBarModel {
|
||||
};
|
||||
let my_view = &model.list_view_wrapper.view;
|
||||
|
||||
let page_1 = gtk::Box::new(gtk::Orientation::Vertical, 5);
|
||||
let page_1 = gtk::Box::builder()
|
||||
.orientation(gtk::Orientation::Vertical)
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
|
||||
let chart = Chart::new();
|
||||
|
||||
chart.connect_resize(clone!(@weak chart as my_view => move |_, w,h|{
|
||||
my_view.set_height_request((w as f32 / 16.0 * 3.0) as i32);
|
||||
}));
|
||||
|
||||
page_1.append(&chart);
|
||||
let label = gtk::Label::new(Some("Page 1"));
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
0
src/dealers/layer_handler.rs
Normal file
0
src/dealers/layer_handler.rs
Normal file
1
src/dealers/mod.rs
Normal file
1
src/dealers/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
mod layer_handler;
|
||||
@ -1,24 +1,19 @@
|
||||
use coords::proj::Mercator;
|
||||
use coords::Mapper;
|
||||
use data::{Npz, Radar2d};
|
||||
use femtovg::{Color, Paint};
|
||||
mod utils;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{gio, glib, Application, ApplicationWindow};
|
||||
use relm4::menu;
|
||||
use relm4::RelmApp;
|
||||
use std::ptr;
|
||||
mod chart;
|
||||
mod components;
|
||||
mod coords;
|
||||
mod data;
|
||||
mod dealers;
|
||||
mod errors;
|
||||
mod monitor;
|
||||
mod pipeline;
|
||||
mod render;
|
||||
mod window;
|
||||
use components::app::{AppMode, AppModel};
|
||||
use monitor::Monitor;
|
||||
use render::{BackgroundConfig, BackgroundWidget, ForegroundConfig, ForegroundWidget, Render};
|
||||
|
||||
const APP_ID: &str = "org.gtk_rs.HelloWorld2";
|
||||
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
use crate::render::Render;
|
||||
use glib::subclass::InitializingObject;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::CompositeTemplate;
|
||||
use gtk::{glib, prelude::WidgetExtManual};
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Monitor {
|
||||
pub(super) renderer: RefCell<Render>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for Monitor {
|
||||
const NAME: &'static str = "Monitor";
|
||||
type Type = super::Monitor;
|
||||
type ParentType = gtk::Box;
|
||||
}
|
||||
|
||||
impl ObjectImpl for Monitor {}
|
||||
|
||||
impl WidgetImpl for Monitor {
|
||||
fn size_allocate(&self, width: i32, height: i32, baseline: i32) {
|
||||
println!("new width {}", width);
|
||||
self.parent_size_allocate(width, height, baseline)
|
||||
}
|
||||
}
|
||||
|
||||
impl BoxImpl for Monitor {}
|
||||
@ -1,92 +0,0 @@
|
||||
mod imp;
|
||||
use crate::render::{Render, RenderMotion, RenderConfig};
|
||||
use adw::prelude::{ButtonExt, GLAreaExt, GestureDragExt};
|
||||
use glib::subclass::prelude::*;
|
||||
use glib::{clone, ObjectExt};
|
||||
use gtk::traits::WidgetExt;
|
||||
use gtk::{glib, AspectFrame};
|
||||
use gtk::{EventControllerScrollFlags, Inhibit};
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct Monitor(ObjectSubclass<imp::Monitor>)
|
||||
@extends gtk::Box,gtk::Widget;
|
||||
}
|
||||
|
||||
impl Monitor {
|
||||
pub fn new(config:RenderConfig) -> Self {
|
||||
let this: Self = glib::Object::new();
|
||||
let pointer_location_detecture = gtk::EventControllerMotion::new();
|
||||
|
||||
let render = Render::new(None, config);
|
||||
|
||||
pointer_location_detecture.connect_motion(
|
||||
clone!(@weak this as s, @weak render as r => move |_context, x, y| {
|
||||
r.update_status(|s| {
|
||||
let dpi = r.scale_factor();
|
||||
let (_,h) = s.window_size;
|
||||
s.pointer_location = (x as f32 * dpi as f32, h as f32 - y as f32 * dpi as f32);
|
||||
});
|
||||
}
|
||||
),
|
||||
);
|
||||
let scale_detecture = gtk::EventControllerScroll::new(EventControllerScrollFlags::VERTICAL);
|
||||
scale_detecture.connect_scroll(clone!(
|
||||
@weak this as s, @weak render as r => @default-panic,move |_context, _x, y| {
|
||||
r.update_status(|status|{
|
||||
status.scale = y as f32;
|
||||
status.motion = RenderMotion::Scale;
|
||||
});
|
||||
r.queue_render();
|
||||
Inhibit(false)
|
||||
}
|
||||
));
|
||||
|
||||
let drag_detecture = gtk::GestureDrag::new();
|
||||
drag_detecture.connect_drag_update(clone!(
|
||||
@weak render as r => move |this, _, _| {
|
||||
let (ox, oy) = this.offset().unwrap_or((0.0,0.0));
|
||||
r.update_status(|s| {
|
||||
s.translate = Some((-ox as f32 * 1.35, oy as f32 * 1.35));
|
||||
s.motion = RenderMotion::Translate;
|
||||
});
|
||||
r.queue_render();
|
||||
}));
|
||||
|
||||
drag_detecture.connect_drag_end(clone!(
|
||||
@weak render as r => move |_,_,_|{
|
||||
r.update_status(|cfg| {
|
||||
cfg.translate = None;
|
||||
cfg.motion = RenderMotion::Translate;
|
||||
})
|
||||
}
|
||||
r.queue_render();
|
||||
));
|
||||
|
||||
let split_view = adw::OverlaySplitView::new();
|
||||
let sidebar = adw::NavigationPage::builder().title("sidebar").child(>k::ListView::builder().build()).build();
|
||||
let content = adw::NavigationPage::builder().title("content").child(&render).build();
|
||||
|
||||
split_view.set_sidebar_position(gtk::PackType::End);
|
||||
|
||||
split_view.set_sidebar(Some(&sidebar));
|
||||
split_view.set_content(Some(&content));
|
||||
|
||||
render.add_controller(pointer_location_detecture);
|
||||
render.add_controller(scale_detecture);
|
||||
render.add_controller(drag_detecture);
|
||||
// render.set_hexpand(true);
|
||||
// render.set_vexpand(true);
|
||||
|
||||
split_view.set_parent(&this);
|
||||
split_view.set_hexpand(true);
|
||||
split_view.set_vexpand(true);
|
||||
|
||||
// paned.set_parent(&this);
|
||||
// render.set_parent(&this);
|
||||
// aspect_frame.set_hexpand(true);
|
||||
// aspect_frame.set_vexpand(true);
|
||||
// aspect_frame.set_parent(&this);
|
||||
this.imp().renderer.replace(render);
|
||||
this
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,12 @@
|
||||
use super::layer::foreground::exterior::ExteriorWidget;
|
||||
use super::layer::foreground::interior::InteriorWidget;
|
||||
use super::WindowCoord;
|
||||
use super::exterior::ExteriorWidget;
|
||||
use super::interior::InteriorWidget;
|
||||
use super::{Layer, WindowCoord};
|
||||
use crate::coords::proj::Mercator;
|
||||
use crate::coords::Mapper;
|
||||
use femtovg::{Color, FontId, Paint, Path, Transform2D};
|
||||
use femtovg::{Canvas, Color, FontId};
|
||||
use gtk::glib;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::traits::{GLAreaExt, WidgetExt};
|
||||
use ndarray::Array2;
|
||||
use std::cell::RefCell;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
@ -29,16 +28,16 @@ impl Default for RenderMotion {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[derive(Default)]
|
||||
pub struct RenderStatus {
|
||||
pub window_size: (i32, i32),
|
||||
pub(super) window_size: (i32, i32),
|
||||
pub(super) scale_rate: Option<f64>,
|
||||
pub(super) pointer_location: WindowCoord,
|
||||
pub(super) motion: RenderMotion,
|
||||
pub(super) scale: f32,
|
||||
pub(super) translate: Option<(f32, f32)>,
|
||||
translation: Option<(f64, f64)>,
|
||||
init_translation: (f64, f64),
|
||||
pub pointer_location: WindowCoord,
|
||||
pub motion: RenderMotion,
|
||||
pub scale: f32,
|
||||
pub translate: Option<(f32, f32)>,
|
||||
}
|
||||
|
||||
struct Fonts {
|
||||
@ -50,10 +49,11 @@ struct Fonts {
|
||||
pub struct Render {
|
||||
pub(super) exterior: RefCell<ExteriorWidget>,
|
||||
pub(super) interior: RefCell<InteriorWidget>,
|
||||
pub(super) canvas: RefCell<Option<femtovg::Canvas<femtovg::renderer::OpenGl>>>,
|
||||
pub config: RefCell<RenderConfig>,
|
||||
pub status: RefCell<RenderStatus>,
|
||||
pub mapper: RefCell<Mapper>,
|
||||
pub(super) canvas: RefCell<Option<femtovg::Canvas<femtovg::renderer::OpenGl>>>,
|
||||
pub(super) interior_layers: RefCell<Vec<Layer>>,
|
||||
}
|
||||
|
||||
impl Default for Render {
|
||||
@ -61,6 +61,7 @@ impl Default for Render {
|
||||
Self {
|
||||
exterior: RefCell::new(ExteriorWidget::default()),
|
||||
interior: RefCell::new(InteriorWidget::default()),
|
||||
interior_layers: RefCell::new(Vec::new()),
|
||||
config: RefCell::new(RenderConfig::default()),
|
||||
status: RefCell::new(RenderStatus::default()),
|
||||
mapper: RefCell::new(Mercator::default().into()),
|
||||
@ -169,11 +170,19 @@ impl GLAreaImpl for Render {
|
||||
}
|
||||
}
|
||||
|
||||
self.interior
|
||||
.borrow()
|
||||
.draw(canvas, &self.obj(), self.status.borrow(), configs);
|
||||
|
||||
let c = &(*self.interior_layers.borrow());
|
||||
|
||||
|
||||
self.interior.borrow().draw(
|
||||
c,
|
||||
canvas,
|
||||
&self.obj(),
|
||||
self.status.borrow(),
|
||||
configs,
|
||||
);
|
||||
self.exterior.borrow().draw(canvas, &self.obj());
|
||||
|
||||
canvas.flush();
|
||||
true
|
||||
}
|
||||
@ -232,7 +241,10 @@ impl Render {
|
||||
status.translation.and_then(|(tx, ty)| {
|
||||
status.scale_rate.and_then(|scale| {
|
||||
let (x1, y1) = (tx + padding[3] as f64, ty + padding[2] as f64);
|
||||
let (x2, y2) = (tx + w * scale + padding[3] as f64, ty + h * scale + padding[2] as f64);
|
||||
let (x2, y2) = (
|
||||
tx + w * scale + padding[3] as f64,
|
||||
ty + h * scale + padding[2] as f64,
|
||||
);
|
||||
let (x1, y1) = mapper.inverse_map((x1, y1)).unwrap();
|
||||
let (x2, y2) = mapper.inverse_map((x2, y2)).unwrap();
|
||||
Some(((x1, x2), (y1, y2)))
|
||||
@ -242,7 +254,6 @@ impl Render {
|
||||
|
||||
pub(super) fn inverse_map(&self, loc: (f32, f32)) -> Option<(f64, f64)> {
|
||||
let (x, y) = loc;
|
||||
// let (_, h) = self.window_size().unwrap();
|
||||
let status = self.status.borrow();
|
||||
status.translation.and_then(|(tx, ty)| {
|
||||
status.scale_rate.and_then(|scale| {
|
||||
@ -257,9 +268,6 @@ impl Render {
|
||||
}
|
||||
|
||||
pub(super) fn map(&self, loc: (f64, f64)) -> Option<(f32, f32)> {
|
||||
// let padding = self.padding();
|
||||
// let left_padding = padding[3];
|
||||
// let bottom_padding = padding[2];
|
||||
let (x, y) = loc;
|
||||
let (_, h) = self.window_size().unwrap();
|
||||
let status = self.status.borrow();
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
use crate::render::layer::background::BackgroundWidget;
|
||||
use crate::render::layer::foreground::ForegroundWidget;
|
||||
use crate::render::{imp, WindowCoord};
|
||||
use femtovg::RenderTarget;
|
||||
use crate::render::WindowCoord;
|
||||
use gtk::glib;
|
||||
use gtk::subclass::prelude::*;
|
||||
use std::cell::RefCell;
|
||||
@ -10,11 +7,8 @@ use super::layers::Layer;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct InteriorWidget {
|
||||
pub(super) background: RefCell<BackgroundWidget>,
|
||||
pub(super) foreground: RefCell<ForegroundWidget>,
|
||||
pub(super) trans: RefCell<WindowCoord>,
|
||||
pub(super) update_trans: RefCell<WindowCoord>,
|
||||
pub(super) layers: RefCell<Vec<Layer>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
@ -1,23 +1,19 @@
|
||||
use geojson::GeoJson;
|
||||
use std::{
|
||||
any::Any,
|
||||
cell::{Ref, RefCell}, fmt::Debug,
|
||||
};
|
||||
use topojson::TopoJson;
|
||||
|
||||
use crate::{
|
||||
coords::{Coord, Mapper, Range},
|
||||
render::{renders::DataRenderer, Render},
|
||||
};
|
||||
use crate::{coords::Range, render::Render};
|
||||
use femtovg::{renderer::OpenGl, Canvas, ImageId};
|
||||
use std::{
|
||||
cell::{Ref, RefCell},
|
||||
fmt::Debug, sync::Arc,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Layer {
|
||||
pub visiable: bool,
|
||||
target: RefCell<Option<Target>>,
|
||||
imp: RefCell<Option<Box<dyn LayerImpl>>>,
|
||||
draw: Box<dyn Fn(&Self, &mut Canvas<OpenGl>, &Render, (f32, f32))>,
|
||||
imp: RefCell<Option<Arc<dyn LayerImpl>>>,
|
||||
draw: Arc<dyn Fn(&Self, &mut Canvas<OpenGl>, &Render, (f32, f32))>,
|
||||
}
|
||||
|
||||
|
||||
impl Debug for Layer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Layer")
|
||||
@ -28,7 +24,7 @@ impl Debug for Layer {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LayerImpl:Debug {
|
||||
pub trait LayerImpl: Debug {
|
||||
fn draw(&self, canvas: &mut Canvas<OpenGl>, render: &Render) -> Option<Target>;
|
||||
}
|
||||
|
||||
@ -44,8 +40,8 @@ impl Layer {
|
||||
Layer {
|
||||
visiable,
|
||||
target: RefCell::new(None),
|
||||
draw: Box::new(draw),
|
||||
imp: RefCell::new(imp.map(|x| Box::new(x) as Box<dyn LayerImpl>)),
|
||||
draw: Arc::new(draw),
|
||||
imp: RefCell::new(imp.map(|x| Arc::new(x) as Arc<dyn LayerImpl>)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +59,7 @@ impl Layer {
|
||||
self.target.borrow().clone()
|
||||
}
|
||||
|
||||
pub fn get_imp(&self) -> Ref<Option<Box<dyn LayerImpl>>> {
|
||||
pub fn get_imp(&self) -> Ref<Option<Arc<dyn LayerImpl>>> {
|
||||
let im = self.imp.borrow();
|
||||
im
|
||||
}
|
||||
@ -1,18 +1,9 @@
|
||||
mod imp;
|
||||
mod layers;
|
||||
use crate::coords::{Mapper, Range};
|
||||
use crate::data::Npz;
|
||||
use crate::data::{DataLoader, RadarData2d};
|
||||
use crate::render::predefined::color_mapper::BoundaryNorm;
|
||||
use crate::render::predefined::gis::MapRender;
|
||||
use crate::render::renders::DataRenderer;
|
||||
use crate::render::Render;
|
||||
use femtovg::{renderer::OpenGl, Canvas, Color, Paint, Path};
|
||||
use glib::subclass::types::ObjectSubclassIsExt;
|
||||
use femtovg::{renderer::OpenGl, Canvas};
|
||||
pub use layers::{Layer, LayerImpl, Target};
|
||||
use ndarray::OwnedRepr;
|
||||
use std::cell::Ref;
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::render::imp::{RenderConfig, RenderStatus};
|
||||
|
||||
@ -29,27 +20,21 @@ impl Default for InteriorWidget {
|
||||
impl InteriorWidget {
|
||||
pub fn new() -> Self {
|
||||
let this: Self = glib::Object::new();
|
||||
this.imp().layers.replace(vec![
|
||||
// Layer::grid_render_layer_with_path(
|
||||
// "/users/tsuki/projects/radar-g/test2.npz",
|
||||
// Npz,
|
||||
// BoundaryNorm::default(),
|
||||
// )
|
||||
]);
|
||||
this
|
||||
}
|
||||
|
||||
|
||||
pub fn draw(
|
||||
&self,
|
||||
layers: &Vec<Layer>,
|
||||
canvas: &mut Canvas<OpenGl>,
|
||||
render: &Render,
|
||||
status: Ref<'_, RenderStatus>,
|
||||
_c: Ref<'_, RenderConfig>,
|
||||
) {
|
||||
let mut layers = self.imp().layers.borrow_mut();
|
||||
|
||||
let (x, y) = (canvas.width(), canvas.height());
|
||||
for layer in layers.iter_mut().filter(|x| x.visiable) {
|
||||
for layer in layers.iter().filter(|x| x.visiable) {
|
||||
layer.draw(canvas, &render, (x, y));
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
use crate::render::{imp, WindowCoord};
|
||||
use femtovg::Paint;
|
||||
use geo_macros::Prj;
|
||||
use geo_types::MultiPolygon;
|
||||
use gtk::glib;
|
||||
use gtk::subclass::prelude::*;
|
||||
use std::cell::RefCell;
|
||||
|
||||
#[derive(Prj, Default)]
|
||||
pub struct BackgroundConfig {
|
||||
pub show_lat_lines: bool,
|
||||
pub show_lon_lines: bool,
|
||||
pub lat_lines: Vec<f64>,
|
||||
pub lon_lines: Vec<f64>,
|
||||
pub painter: Paint,
|
||||
}
|
||||
|
||||
impl BackgroundConfig {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct BackgroundWidget {
|
||||
pub(super) config: RefCell<BackgroundConfig>,
|
||||
pub(super) shp: RefCell<Option<Vec<MultiPolygon>>>
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for BackgroundWidget {
|
||||
const NAME: &'static str = "BackgroundWidget";
|
||||
type Type = super::BackgroundWidget;
|
||||
}
|
||||
|
||||
impl ObjectImpl for BackgroundWidget {}
|
||||
@ -1,238 +0,0 @@
|
||||
mod imp;
|
||||
use crate::coords::{Mapper, Range};
|
||||
use femtovg::{renderer::OpenGl, Canvas, Color, Paint, Path};
|
||||
use geo_types::{line_string, LineString, Point};
|
||||
use glib::subclass::types::ObjectSubclassIsExt;
|
||||
use shapefile;
|
||||
use std::cell::Ref;
|
||||
|
||||
pub use self::imp::BackgroundConfig;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct BackgroundWidget(ObjectSubclass<imp::BackgroundWidget>);
|
||||
}
|
||||
|
||||
impl Default for BackgroundWidget {
|
||||
fn default() -> Self {
|
||||
Self::new(BackgroundConfig::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl BackgroundWidget {
|
||||
pub fn new(config: BackgroundConfig) -> Self {
|
||||
let this: Self = glib::Object::new();
|
||||
let imp = this.imp();
|
||||
let polygons = shapefile::read_as::<_, shapefile::Polygon, shapefile::dbase::Record>(
|
||||
"shp/ne_110m_admin_0_countries.shp",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let polys: Vec<geo_types::MultiPolygon<f64>> = polygons
|
||||
.into_iter()
|
||||
.map(|(polygon, _)| polygon.into())
|
||||
.collect();
|
||||
|
||||
imp.shp.replace(Some(polys));
|
||||
imp.config.replace(config);
|
||||
this
|
||||
}
|
||||
|
||||
fn draw_lines<V: IntoIterator<Item = LineString<f32>>>(
|
||||
&self,
|
||||
canvas: &mut Canvas<OpenGl>,
|
||||
line_painter: &Paint,
|
||||
p: V,
|
||||
) {
|
||||
p.into_iter().for_each(|line| {
|
||||
let mut path = Path::new();
|
||||
let points: Vec<Point<f32>> = line.points().collect();
|
||||
path.move_to(points[0].x() as f32, points[0].y() as f32);
|
||||
points[1..].into_iter().for_each(|p| {
|
||||
path.line_to(p.x() as f32, p.y() as f32);
|
||||
});
|
||||
canvas.stroke_path(&mut path, line_painter);
|
||||
});
|
||||
}
|
||||
|
||||
fn mesh_lines(
|
||||
&self,
|
||||
canvas: &mut Canvas<OpenGl>,
|
||||
scale: f32,
|
||||
translate: (f32, f32),
|
||||
canvas_width: f32,
|
||||
canvas_height: f32,
|
||||
mapper: &Ref<'_, Mapper>,
|
||||
bound: (Range, Range),
|
||||
) {
|
||||
let imp = self.imp();
|
||||
let line_painter = &imp.config.borrow().painter;
|
||||
let (left, right) = (bound.0 .0, bound.0 .1);
|
||||
let (bottom, top) = (bound.1 .0, bound.1 .1);
|
||||
let config = imp.config.borrow();
|
||||
|
||||
if config.show_lat_lines {
|
||||
let r = config.lat_lines.iter().map(|lat| {
|
||||
let line = LineString::new(vec![(left, *lat).into(), (right, *lat).into()]);
|
||||
let result = mapper.map_line(&line).unwrap();
|
||||
LineString::new(
|
||||
result
|
||||
.points()
|
||||
.map(|p| {
|
||||
(
|
||||
p.x() as f32 * canvas_width * scale - translate.0,
|
||||
p.y() as f32 * canvas_height * scale - translate.1,
|
||||
)
|
||||
.into()
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
});
|
||||
|
||||
self.draw_lines(canvas, line_painter, r);
|
||||
}
|
||||
|
||||
if config.show_lat_lines {
|
||||
config.lat_lines.iter().for_each(|lat| {
|
||||
let mut paint = Paint::color(Color::white());
|
||||
paint.set_font_size(25.0);
|
||||
paint.set_line_width(1.0);
|
||||
let (x, y) = self.map_to_screen(
|
||||
mapper,
|
||||
scale,
|
||||
translate,
|
||||
canvas_height,
|
||||
canvas_width,
|
||||
(left, *lat),
|
||||
);
|
||||
|
||||
let _ = canvas.stroke_text(x, y, format!("{:.2} N", lat), &paint);
|
||||
});
|
||||
}
|
||||
|
||||
if config.show_lon_lines {
|
||||
config.lon_lines.iter().for_each(|lon| {
|
||||
let mut paint = Paint::color(Color::white());
|
||||
paint.set_font_size(25.0);
|
||||
paint.set_line_width(1.0);
|
||||
let (x, y) = self.map_to_screen(
|
||||
mapper,
|
||||
scale,
|
||||
translate,
|
||||
canvas_height,
|
||||
canvas_width,
|
||||
(*lon + 0.5, bottom + 0.1),
|
||||
);
|
||||
let _ = canvas.stroke_text(x, y, format!("{:.2}", lon), &paint);
|
||||
});
|
||||
}
|
||||
|
||||
if imp.config.borrow().show_lon_lines {
|
||||
let r = config.lon_lines.iter().map(|lon| {
|
||||
let line = LineString::new(vec![(*lon, bottom).into(), (*lon, top).into()]);
|
||||
let result = mapper.map_line(&line).unwrap();
|
||||
LineString::new(
|
||||
result
|
||||
.points()
|
||||
.map(|p| {
|
||||
(
|
||||
p.x() as f32 * canvas_width * scale - translate.0,
|
||||
p.y() as f32 * canvas_height * scale - translate.1,
|
||||
)
|
||||
.into()
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
});
|
||||
|
||||
self.draw_lines(canvas, line_painter, r);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
&self,
|
||||
canvas: &mut Canvas<OpenGl>,
|
||||
scale: f32,
|
||||
dpi: i32,
|
||||
width: f32,
|
||||
hdight: f32,
|
||||
translate: (f32, f32),
|
||||
mapper: Ref<'_, Mapper>,
|
||||
bound: (Range, Range),
|
||||
) {
|
||||
let config = self.imp().config.borrow();
|
||||
self.mesh_lines(canvas, scale, translate, width, hdight, &mapper, bound);
|
||||
self.shp(mapper, canvas, translate, scale, width, hdight);
|
||||
}
|
||||
|
||||
fn shp(
|
||||
&self,
|
||||
mapper: Ref<'_, Mapper>,
|
||||
canvas: &mut Canvas<OpenGl>,
|
||||
translate: (f32, f32),
|
||||
scale: f32,
|
||||
canvas_width: f32,
|
||||
canvas_height: f32,
|
||||
) {
|
||||
if let Some(s) = self.imp().shp.borrow().as_ref() {
|
||||
for p in s.iter() {
|
||||
for poly in p.iter() {
|
||||
let mut points = poly.exterior().points();
|
||||
let first_point = points.next().unwrap();
|
||||
let mut path = Path::new();
|
||||
|
||||
let first = self.map_to_screen(
|
||||
&mapper,
|
||||
scale,
|
||||
translate,
|
||||
canvas_height,
|
||||
canvas_width,
|
||||
(first_point.x(), first_point.y()),
|
||||
);
|
||||
|
||||
path.move_to(first.0, first.1);
|
||||
|
||||
for p in points {
|
||||
let (nx, ny) = self.map_to_screen(
|
||||
&mapper,
|
||||
scale,
|
||||
translate,
|
||||
canvas_height,
|
||||
canvas_width,
|
||||
(p.x(), p.y()),
|
||||
);
|
||||
path.line_to(nx, ny);
|
||||
}
|
||||
|
||||
canvas.stroke_path(&path, &Paint::color(Color::white()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn map_to_screen(
|
||||
&self,
|
||||
mapper: &Ref<'_, Mapper>,
|
||||
scale: f32,
|
||||
translate: (f32, f32),
|
||||
canvas_height: f32,
|
||||
canvas_width: f32,
|
||||
point: (f64, f64),
|
||||
) -> (f32, f32) {
|
||||
let (x, y) = mapper.map(point).unwrap();
|
||||
(
|
||||
x as f32 * canvas_width * scale - translate.0,
|
||||
y as f32 * canvas_height * scale - translate.1,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn set_lat_lines(&self, lat_lines: Vec<f64>) {
|
||||
let imp = self.imp();
|
||||
imp.config.borrow_mut().lat_lines = lat_lines;
|
||||
}
|
||||
|
||||
pub fn set_lon_lines(&self, lon_lines: Vec<f64>) {
|
||||
let imp = self.imp();
|
||||
imp.config.borrow_mut().lon_lines = lon_lines;
|
||||
}
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
use crate::render::{imp, WindowCoord};
|
||||
use femtovg::{Color, ImageId, Paint, RenderTarget};
|
||||
use geo_macros::Prj;
|
||||
use geo_types::LineString;
|
||||
use gtk::glib;
|
||||
use gtk::subclass::prelude::*;
|
||||
use ndarray::Array2;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Prj, Default)]
|
||||
pub struct ForegroundConfig {
|
||||
pub show_lat_lines: bool,
|
||||
pub show_lon_lines: bool,
|
||||
pub lat_lines: Vec<Vec<WindowCoord>>,
|
||||
pub lon_lines: Vec<Vec<WindowCoord>>,
|
||||
pub painter: Paint,
|
||||
}
|
||||
|
||||
impl ForegroundConfig {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ForegroundWidget {
|
||||
pub(super) config: RefCell<ForegroundConfig>,
|
||||
pub(super) dim1: RefCell<Option<Array2<f64>>>,
|
||||
pub(super) dim2: RefCell<Option<Array2<f64>>>,
|
||||
pub(super) image: RefCell<Option<ImageId>>,
|
||||
pub(super) data: RefCell<Option<Array2<LineString>>>,
|
||||
pub(super) color: RefCell<Option<Array2<Option<Color>>>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for ForegroundWidget {
|
||||
const NAME: &'static str = "ForegroundWidget";
|
||||
type Type = super::ForegroundWidget;
|
||||
}
|
||||
|
||||
impl ObjectImpl for ForegroundWidget {}
|
||||
@ -1,34 +0,0 @@
|
||||
pub mod exterior;
|
||||
mod imp;
|
||||
pub mod interior;
|
||||
use crate::coords::Mapper;
|
||||
use femtovg::{renderer::OpenGl, Canvas, Path};
|
||||
use glib::subclass::types::ObjectSubclassIsExt;
|
||||
use gtk::glib;
|
||||
use std::cell::Ref;
|
||||
|
||||
pub use self::imp::ForegroundConfig;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct ForegroundWidget(ObjectSubclass<imp::ForegroundWidget>);
|
||||
}
|
||||
|
||||
impl Default for ForegroundWidget {
|
||||
fn default() -> Self {
|
||||
Self::new(ForegroundConfig::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl ForegroundWidget {
|
||||
pub fn new(config: ForegroundConfig) -> Self {
|
||||
let this: Self = glib::Object::new();
|
||||
let imp = this.imp();
|
||||
imp.config.replace(config);
|
||||
this
|
||||
}
|
||||
|
||||
pub fn draw(&self, canvas: &mut Canvas<OpenGl>, scale: f32, dpi: i32, mapper: Ref<'_, Mapper>) {
|
||||
let config = self.imp().config.borrow();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
pub mod background;
|
||||
pub mod foreground;
|
||||
@ -1,22 +1,20 @@
|
||||
mod cms;
|
||||
mod imp;
|
||||
mod layer;
|
||||
mod predefined;
|
||||
mod exterior;
|
||||
mod interior;
|
||||
pub mod predefined;
|
||||
mod renders;
|
||||
use self::cms::CMS;
|
||||
pub use self::imp::{RenderConfig, RenderMotion, RenderStatus};
|
||||
pub use self::layer::background::{BackgroundConfig, BackgroundWidget};
|
||||
pub use self::layer::foreground::{ForegroundConfig, ForegroundWidget};
|
||||
use crate::coords::Mapper;
|
||||
use adw::prelude::{GLAreaExt, GestureDragExt};
|
||||
use geo_types::LineString;
|
||||
use glib::clone;
|
||||
pub use glib::subclass::prelude::*;
|
||||
use gtk::traits::WidgetExt;
|
||||
use gtk::{EventControllerScrollFlags, Inhibit};
|
||||
pub use layer::foreground::interior::Layer;
|
||||
use std::cell::Ref;
|
||||
use gtk::prelude::*;
|
||||
pub use glib::subclass::prelude::*;
|
||||
pub use interior::{Layer, LayerImpl, Target};
|
||||
|
||||
pub(super) type WindowCoord = (f32, f32);
|
||||
|
||||
@ -122,13 +120,12 @@ impl Render {
|
||||
self.imp().mapper.replace(mapper);
|
||||
}
|
||||
|
||||
pub fn set_interior_layers(&self, layers: Vec<Layer>) {
|
||||
self.imp().interior_layers.replace(layers);
|
||||
self.queue_render();
|
||||
}
|
||||
|
||||
pub fn map(&self, loc: (f64, f64)) -> Option<(f32, f32)> {
|
||||
// let (x, y) = loc;
|
||||
// let (x_range, y_range) = self.imp().window_range().unwrap();
|
||||
|
||||
// if x >= x_range.0 && x <= x_range.1 && y >= y_range.0 && y <= y_range.1 {
|
||||
|
||||
// }
|
||||
let foremapped = self.get_mapper().map(loc).unwrap();
|
||||
return self.imp().map(foremapped);
|
||||
}
|
||||
@ -170,9 +167,6 @@ impl Render {
|
||||
let mut mapper = self.get_mapper().clone();
|
||||
mapper.set_lat_range(lat1..lat2);
|
||||
mapper.set_lon_range(lon1..lon2);
|
||||
|
||||
println!("new_mapper: {:?}", mapper.get_bounds());
|
||||
println!("old_mapper: {:?}", self.get_mapper().get_bounds());
|
||||
let cms = CMS::new(mapper, window_size);
|
||||
f(&cms);
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use super::color_mapper::{BoundaryNorm, ColorMapper};
|
||||
use crate::render::layer::foreground::interior::LayerImpl;
|
||||
use femtovg::{ImageFlags, Paint, Path, PixelFormat::Rgba8, RenderTarget};
|
||||
use geo_types::LineString;
|
||||
use ndarray::ArrayView2;
|
||||
@ -9,8 +8,7 @@ use std::{marker::PhantomData, fmt::Debug};
|
||||
use super::super::renders::DataRenderer;
|
||||
use crate::{
|
||||
data::Radar2d,
|
||||
render::{layer::foreground::interior::Target, Render},
|
||||
utils::meshgrid,
|
||||
utils::meshgrid, render::{Render, Target, LayerImpl},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -39,6 +37,7 @@ impl<T: NumOps + PartialOrd + Copy, CMAP: ColorMapper<T>> GridFieldRenderer<CMAP
|
||||
window_size: (f32, f32),
|
||||
fill_value: T,
|
||||
) {
|
||||
|
||||
let shape = data.shape();
|
||||
let (rows, cols) = (shape[0], shape[1]);
|
||||
let (dim1, dim2) = dims;
|
||||
|
||||
@ -4,7 +4,7 @@ use std::path::Path;
|
||||
|
||||
use crate::{
|
||||
data::{DataLoader, Radar2d},
|
||||
render::layer::foreground::interior::Layer,
|
||||
render::Layer
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use femtovg::{renderer::OpenGl, Canvas};
|
||||
use crate::render::layer::foreground::interior::Target;
|
||||
use crate::coords::Mapper;
|
||||
use super::Target;
|
||||
use super::Render;
|
||||
|
||||
pub trait DataRenderer {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user