Compare commits

..

No commits in common. "main" and "0.2.0" have entirely different histories.
main ... 0.2.0

12 changed files with 499 additions and 545 deletions

346
Cargo.lock generated
View File

@ -1,7 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "CoreFoundation-sys"
version = "0.1.4"
@ -23,12 +21,6 @@ dependencies = [
"mach 0.1.2",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler32"
version = "1.2.0"
@ -52,21 +44,23 @@ checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
[[package]]
name = "atk"
version = "0.15.1"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd"
checksum = "812b4911e210bd51b24596244523c856ca749e6223c50a7fbbba3f89ee37c426"
dependencies = [
"atk-sys",
"bitflags",
"glib",
"glib-sys",
"gobject-sys",
"libc",
]
[[package]]
name = "atk-sys"
version = "0.15.1"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6"
checksum = "f530e4af131d94cc4fa15c5c9d0348f0ef28bac64ba660b6b2a1cf2605dedfce"
dependencies = [
"glib-sys",
"gobject-sys",
@ -82,28 +76,36 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.3.2"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cairo-rs"
version = "0.15.6"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8b14c80d8d1a02fa6d914b9d1afeeca9bc34257f8300d9696e1e331ae114223"
checksum = "c5c0f2e047e8ca53d0ff249c54ae047931d7a6ebe05d00af73e0ffeb6e34bdb8"
dependencies = [
"bitflags",
"cairo-sys-rs",
"glib",
"glib-sys",
"gobject-sys",
"libc",
"thiserror",
]
[[package]]
name = "cairo-sys-rs"
version = "0.15.1"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8"
checksum = "2ed2639b9ad5f1d6efa76de95558e11339e7318426d84ac4890b86c03e828ca7"
dependencies = [
"glib-sys",
"libc",
@ -116,15 +118,6 @@ version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
[[package]]
name = "cfg-expr"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e068cb2806bbc15b439846dc16c5f89f8599f2c3e4d73d4449d38f9b2f0b6c5"
dependencies = [
"smallvec",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
@ -139,31 +132,28 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crc32fast"
version = "1.3.2"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "deflate"
version = "1.0.0"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f"
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
dependencies = [
"adler32",
"byteorder",
]
[[package]]
name = "field-offset"
version = "0.3.4"
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92"
dependencies = [
"memoffset",
"rustc_version",
]
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "fuchsia-cprng"
@ -171,6 +161,21 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "futures"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.14"
@ -178,6 +183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@ -203,6 +209,24 @@ version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
[[package]]
name = "futures-macro"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23"
[[package]]
name = "futures-task"
version = "0.3.14"
@ -215,47 +239,60 @@ version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"proc-macro-hack",
"proc-macro-nested",
"slab",
]
[[package]]
name = "gdk"
version = "0.15.4"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8"
checksum = "db00839b2a68a7a10af3fa28dfb3febaba3a20c3a9ac2425a33b7df1f84a6b7d"
dependencies = [
"bitflags",
"cairo-rs",
"cairo-sys-rs",
"gdk-pixbuf",
"gdk-sys",
"gio",
"gio-sys",
"glib",
"glib-sys",
"gobject-sys",
"libc",
"pango",
]
[[package]]
name = "gdk-pixbuf"
version = "0.15.6"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8750501d75f318c2ec0314701bc8403901303210def80bafd13f6b6059a3f45"
checksum = "8f6dae3cb99dd49b758b88f0132f8d401108e63ae8edd45f432d42cdff99998a"
dependencies = [
"bitflags",
"gdk-pixbuf-sys",
"gio",
"gio-sys",
"glib",
"glib-sys",
"gobject-sys",
"libc",
]
[[package]]
name = "gdk-pixbuf-sys"
version = "0.15.1"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413424d9818621fa3cfc8a3a915cdb89a7c3c507d56761b4ec83a9a98e587171"
checksum = "3bfe468a7f43e97b8d193a762b6c5cf67a7d36cacbc0b9291dbcae24bfea1e8f"
dependencies = [
"gio-sys",
"glib-sys",
@ -266,9 +303,9 @@ dependencies = [
[[package]]
name = "gdk-sys"
version = "0.15.1"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88"
checksum = "0a9653cfc500fd268015b1ac055ddbc3df7a5c9ea3f4ccef147b3957bd140d69"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
@ -294,16 +331,20 @@ dependencies = [
[[package]]
name = "gio"
version = "0.15.6"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96efd8a1c00d890f6b45671916e165b5e43ccec61957d443aff6d7e44f62d348"
checksum = "1fb60242bfff700772dae5d9e3a1f7aa2e4ebccf18b89662a16acb2822568561"
dependencies = [
"bitflags",
"futures",
"futures-channel",
"futures-core",
"futures-io",
"futures-util",
"gio-sys",
"glib",
"glib-sys",
"gobject-sys",
"libc",
"once_cell",
"thiserror",
@ -311,9 +352,9 @@ dependencies = [
[[package]]
name = "gio-sys"
version = "0.15.6"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d0fa5052773f5a56b8ae47dab09d040f5d9ce1311f4f99006e16e9a08269296"
checksum = "5e24fb752f8f5d2cf6bbc2c606fd2bc989c81c5e2fe321ab974d54f8b6344eac"
dependencies = [
"glib-sys",
"gobject-sys",
@ -324,32 +365,32 @@ dependencies = [
[[package]]
name = "glib"
version = "0.15.6"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa570813c504bdf7539a9400180c2dd4b789a819556fb86da7226d7d1b037b49"
checksum = "0c685013b7515e668f1b57a165b009d4d28cb139a8a989bbd699c10dad29d0c5"
dependencies = [
"bitflags",
"futures-channel",
"futures-core",
"futures-executor",
"futures-task",
"futures-util",
"glib-macros",
"glib-sys",
"gobject-sys",
"libc",
"once_cell",
"smallvec",
"thiserror",
]
[[package]]
name = "glib-macros"
version = "0.15.6"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41bfd8d227dead0829ac142454e97531b93f576d0805d779c42bfd799c65c572"
checksum = "41486a26d1366a8032b160b59065a59fb528530a46a49f627e7048fb8c064039"
dependencies = [
"anyhow",
"heck",
"itertools",
"proc-macro-crate",
"proc-macro-error",
"proc-macro2",
@ -359,9 +400,9 @@ dependencies = [
[[package]]
name = "glib-sys"
version = "0.15.6"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4366377bd56697de8aaee24e673c575d2694d72e7756324ded2b0428829a7b8"
checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1"
dependencies = [
"libc",
"system-deps",
@ -369,9 +410,9 @@ dependencies = [
[[package]]
name = "gobject-sys"
version = "0.15.5"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a"
checksum = "952133b60c318a62bf82ee75b93acc7e84028a093e06b9e27981c2b6fe68218c"
dependencies = [
"glib-sys",
"libc",
@ -380,32 +421,37 @@ dependencies = [
[[package]]
name = "gtk"
version = "0.15.4"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f2d1326b36af927fe46ae2f89a8fec38c6f0d279ebc5ef07ffeeabb70300bfc"
checksum = "2f022f2054072b3af07666341984562c8e626a79daa8be27b955d12d06a5ad6a"
dependencies = [
"atk",
"bitflags",
"cairo-rs",
"field-offset",
"futures-channel",
"cairo-sys-rs",
"cc",
"gdk",
"gdk-pixbuf",
"gdk-pixbuf-sys",
"gdk-sys",
"gio",
"gio-sys",
"glib",
"glib-sys",
"gobject-sys",
"gtk-sys",
"gtk3-macros",
"libc",
"once_cell",
"pango",
"pango-sys",
"pkg-config",
]
[[package]]
name = "gtk-sys"
version = "0.15.3"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84"
checksum = "89acda6f084863307d948ba64a4b1ef674e8527dddab147ee4cdcc194c880457"
dependencies = [
"atk-sys",
"cairo-sys-rs",
@ -419,25 +465,14 @@ dependencies = [
"system-deps",
]
[[package]]
name = "gtk3-macros"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24f518afe90c23fba585b2d7697856f9e6a7bbc62f65588035e66f6afb01a2e9"
dependencies = [
"anyhow",
"proc-macro-crate",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "heck"
version = "0.4.0"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
@ -448,6 +483,15 @@ dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
dependencies = [
"either",
]
[[package]]
name = "libc"
version = "0.2.94"
@ -503,26 +547,17 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.4.1"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "miniz_oxide"
version = "0.5.1"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
dependencies = [
"adler",
"adler32",
]
[[package]]
@ -556,12 +591,14 @@ checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
[[package]]
name = "pango"
version = "0.15.6"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c7420fc01a390ec200da7395b64d705f5d82fe03e5d0708aee422c46538be7"
checksum = "9937068580bebd8ced19975938573803273ccbcbd598c58d4906efd4ac87c438"
dependencies = [
"bitflags",
"glib",
"glib-sys",
"gobject-sys",
"libc",
"once_cell",
"pango-sys",
@ -569,9 +606,9 @@ dependencies = [
[[package]]
name = "pango-sys"
version = "0.15.1"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7022c2fb88cd2d9d55e1a708a8c53a3ae8678234c4a54bf623400aeb7f31fac2"
checksum = "24d2650c8b62d116c020abd0cea26a4ed96526afda89b1c4ea567131fdefc890"
dependencies = [
"glib-sys",
"gobject-sys",
@ -579,15 +616,6 @@ dependencies = [
"system-deps",
]
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]]
name = "pin-project-lite"
version = "0.2.6"
@ -608,9 +636,9 @@ checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "png"
version = "0.17.5"
version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [
"bitflags",
"crc32fast",
@ -626,11 +654,10 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro-crate"
version = "1.1.3"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
dependencies = [
"thiserror",
"toml",
]
@ -659,10 +686,22 @@ dependencies = [
]
[[package]]
name = "proc-macro2"
version = "1.0.36"
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro-nested"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]]
name = "proc-macro2"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
@ -780,33 +819,6 @@ version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
name = "rustc_version"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
dependencies = [
"pest",
]
[[package]]
name = "serde"
version = "1.0.125"
@ -837,16 +849,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
[[package]]
name = "smallvec"
version = "1.8.0"
name = "strum"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
[[package]]
name = "strum_macros"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "1.0.86"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883"
dependencies = [
"proc-macro2",
"quote",
@ -855,20 +879,22 @@ dependencies = [
[[package]]
name = "system-deps"
version = "6.0.2"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709"
checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b"
dependencies = [
"cfg-expr",
"heck",
"pkg-config",
"strum",
"strum_macros",
"thiserror",
"toml",
"version-compare",
]
[[package]]
name = "tarangam"
version = "0.3.1"
version = "0.2.0"
dependencies = [
"cairo-rs",
"gdk",
@ -935,10 +961,10 @@ dependencies = [
]
[[package]]
name = "ucd-trie"
version = "0.1.3"
name = "unicode-segmentation"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
[[package]]
name = "unicode-xid"
@ -948,9 +974,9 @@ checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "version-compare"
version = "0.1.0"
version = "0.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1"
[[package]]
name = "version_check"

View File

@ -1,10 +1,10 @@
[package]
name = "tarangam"
version = "0.3.1"
version = "0.2.0"
authors = ["PiyushXCoder <piyush.raj.kit@gmail.com>"]
license = "GPL-3.0-only"
license = "GPL 3.0"
edition = "2018"
description = "A simple serial plotter. एक सरल सीरीय्ल पलौटर।"
documentation = "A simple serial plotter. एक सरल सीरीय्ल पलौटर।"
readme = "README.md"
repository = "https://github.com/PiyushXCoder/Tarangam"
keywords = ["plotter","serial","serialplotter","arduino","gtk"]
@ -13,19 +13,13 @@ keywords = ["plotter", "serial", "serialplotter", "arduino", "gtk"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.5.0", features = [
"rt",
"rt-multi-thread",
"macros",
"time",
"sync",
] }
gtk = "0.15"
gdk = "0.15"
gio = "0.15"
glib = "0.15"
png = "0.17"
cairo-rs = { version = "0.15", features = ["png"] }
tokio = { version = "1.5.0", features = ["rt", "rt-multi-thread", "macros", "time", "sync"] }
gtk = "0.9.2"
gdk = "0.13.2"
gio = "0.9.1"
glib = "0.10.3"
png = "0.16.8"
cairo-rs = { version = "0.9.1", features = ["png"] }
rand = "0.8.1"
libmath = "0.2.1"
serialport = "4.0.1"

View File

@ -1,5 +1,6 @@
# Tarangam
It is a straightforward application to see the logs from [serial ports](https://wiki.osdev.org/Serial_Ports) and plot information on graph. You can use it with IOT boards ([Arduino](https://www.arduino.cc/), [ESP boards](https://www.espressif.com/),...) in your DIY projects. It gives many basic controls to modify the graph.
It is a simple application to see log from [serialports](https://wiki.osdev.org/Serial_Ports) and plot information on graph. You can use it with IOT boards([ardino](https://www.arduino.cc/), [esp boards](https://www.espressif.com/),...) in you DIY projects. It gives to many basic controls to control graph.
## Interface
![1](screenshots/1.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -1,23 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="256"
height="256"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1000"
height="1000"
viewBox="0 0 1000 1000"
version="1.1"
id="svg8"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="chitra.svg"
inkscape:export-filename="/home/piyush/Projects/tarangam/chitra-small.png"
inkscape:export-xdpi="24"
inkscape:export-ydpi="24"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
sodipodi:docname="icon.svg">
<defs
id="defs2">
<linearGradient
@ -50,20 +47,19 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="607.14286"
inkscape:cy="250"
inkscape:cx="605.76766"
inkscape:cy="248.85918"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1002"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:window-width="1214"
inkscape:window-height="757"
inkscape:window-x="295"
inkscape:window-y="198"
inkscape:window-maximized="0"
units="px"
showguides="false"
inkscape:pagecheckerboard="1">
showguides="false">
<inkscape:grid
type="xygrid"
id="grid869" />

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -20,42 +20,41 @@
use gtk::prelude::*;
use gtk::DrawingArea;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
/// A single line
#[derive(Debug)]
pub(crate) struct Line {
pub(crate) points: Vec<(f64, f64)>,
pub(crate) color: (f64, f64, f64),
pub struct Line {
pub points: Vec<(f64,f64)>,
pub color: (f64, f64, f64)
}
impl Line {
pub(crate) fn new(r: f64, g: f64, b: f64, points: Vec<(f64, f64)>) -> Self {
pub fn new(r: f64, g: f64, b: f64, points: Vec<(f64,f64)>) -> Self {
Line {
points,
color: (r, g, b),
color: (r,g,b)
}
}
}
/// Tools to draw Graph
pub(crate) struct Graph {
pub(crate) area: DrawingArea,
pub(crate) scale_x_start: f64, // start of x on pankti
pub(crate) scale_x_size: f64, // size of pankti to show
pub(crate) scale_y_start: f64, // start of y on stambh
pub(crate) scale_y_size: f64, // size of stambh to show
pub(crate) draw_patch: bool, // enable to draw circle spot on line
pub(crate) draw_box: bool, // enable to show boxes linke graph paper
pub(crate) draw_baarik_box: bool, // enable to show baarik(similar meaning to smaller) linke graph paper
pub(crate) auto_adjust_y: bool, // enable to automatically adjust y axis
pub(crate) lines: HashMap<String, Line>,
pub(crate) pankti_sankya: f64, // use used while adding to point in lines to see last count of graphable input
pub struct Graph {
pub area: DrawingArea,
pub scale_x_start: f64, // start of x on pankti
pub scale_x_size: f64, // size of pankti to show
pub scale_y_start: f64, // start of y on stambh
pub scale_y_size: f64, // size of stambh to show
pub draw_patch: bool, // enable to draw circle spot on line
pub draw_box: bool, // enable to show boxes linke graph paper
pub draw_baarik_box: bool, // enable to show baarik(similar meaning to smaller) linke graph paper
pub auto_adjust_y: bool, // enable to automatically adjust y axis
pub lines: HashMap<String, Line>,
pub pankti_sankya: f64 // use used while adding to point in lines to see last count of graphable input
}
impl Graph {
pub(crate) fn new(
area: DrawingArea,
pub fn new(area: DrawingArea,
scale_x_start: f64,
scale_x_size: f64,
scale_y_start: f64,
@ -65,8 +64,8 @@ impl Graph {
draw_baarik_box: bool,
auto_adjust_y: bool,
lines: HashMap<String, Line>,
pankti_sankya: f64,
) -> Rc<RefCell<Self>> {
pankti_sankya: f64) -> Rc<RefCell<Self>> {
let graph = Rc::new(RefCell::new(Graph {
area,
scale_x_start,
@ -78,7 +77,7 @@ impl Graph {
draw_baarik_box,
auto_adjust_y,
lines,
pankti_sankya,
pankti_sankya
}));
let graph_tmp = Rc::clone(&graph);
@ -91,14 +90,7 @@ impl Graph {
}
/// used to draw box and baarik box
fn draw_boxes(
ctx: &cairo::Context,
area_width: f64,
area_height: f64,
src_x: f64,
cell_size: f64,
color: f64,
) {
fn draw_boxes(ctx: &cairo::Context, area_width: f64, area_height: f64, src_x: f64, cell_size: f64, color: f64) {
ctx.set_source_rgb(color, color, color);
ctx.set_line_width(1.0);
// lines parallel to stambh
@ -113,7 +105,7 @@ impl Graph {
ctx.move_to(src_x, yi);
ctx.line_to(area_width + src_x, yi);
}
ctx.stroke().unwrap();
ctx.stroke();
}
/// transform point to show on graph
@ -127,25 +119,27 @@ impl Graph {
scale_x_size: f64,
scale_y_size: f64,
height: f64,
stambh_scale_width: f64,
) -> (f64, f64) {
stambh_scale_width: f64) -> (f64, f64){
(
((p - p_start) * aa_dumm_pankti)/scale_x_size + stambh_scale_width,
height - ((s - s_start) * aa_dumm_stambh) / scale_y_size,
height - ((s - s_start) * aa_dumm_stambh) / scale_y_size
)
}
/// callback of drawing area to draw graph
fn draw(area: &gtk::DrawingArea, ctx: &cairo::Context, graph: &Rc<RefCell<Graph>>) {
fn draw(area: &gtk::DrawingArea,
ctx: &cairo::Context,
graph: &Rc<RefCell<Graph>>) {
let graph = graph.borrow();
ctx.set_source_rgb(0.1, 0.5, 0.5);
ctx.paint().unwrap();
ctx.paint();
let pankti_scale_height = 50.0;
let stambh_scale_width = 60.0;
let width = area.allocated_width() as f64 - stambh_scale_width;
let height = area.allocated_height() as f64 - pankti_scale_height;
let width = area.get_allocated_width() as f64 - stambh_scale_width;
let height = area.get_allocated_height() as f64 - pankti_scale_height;
let manjusa_maap = 50.0;
@ -208,19 +202,14 @@ impl Graph {
ctx.set_source_rgb(line.color.0, line.color.1, line.color.2);
ctx.move_to(bindu_dumm_t.0, bindu_dumm_t.1);
ctx.line_to(bindu_t.0, bindu_t.1);
ctx.stroke().unwrap();
ctx.stroke();
// draw circle over point
if draw_patch {
ctx.set_source_rgb(0.0, 0.0, 1.0);
ctx.arc(
bindu_dumm_t.0,
bindu_dumm_t.1,
5.0,
0.0,
std::f64::consts::PI * 2.0,
);
ctx.stroke().unwrap();
ctx.arc(bindu_dumm_t.0, bindu_dumm_t.1,
5.0, 0.0, std::f64::consts::PI * 2.0);
ctx.stroke();
}
}
}
@ -229,41 +218,33 @@ impl Graph {
ctx.set_source_rgb(0.1, 0.4, 0.4);
ctx.rectangle(0.0, 0.0, stambh_scale_width, height + pankti_scale_height);
ctx.rectangle(stambh_scale_width, height, width, pankti_scale_height);
ctx.fill().unwrap();
ctx.fill();
ctx.set_source_rgb(1.0, 1.0, 1.0);
// write numbers on pankti scale
for i in 0..(rekha_sankhya_pankti as i32 + 1) {
let text =
math::round::floor(i as f64 * anupat_pankti + graph.scale_x_start, 4).to_string();
let f = ctx.text_extents(&text).expect("Text dimension");
ctx.move_to(
i as f64 * manjusa_maap - f.width + stambh_scale_width + f.height / 0.866,
height + f.width * 0.5 + f.height,
);
ctx.save().unwrap();
let text = math::round::floor(i as f64 * anupat_pankti + graph.scale_x_start, 4).to_string();
let f = ctx.text_extents(&text);
ctx.move_to(i as f64 * manjusa_maap - f.width + stambh_scale_width + f.height / 0.866, height + f.width * 0.5 + f.height);
ctx.save();
ctx.rotate(std::f64::consts::PI / -6.0);
ctx.show_text(&text).unwrap();
ctx.restore().unwrap();
ctx.show_text(&text);
ctx.restore();
}
// write numbers on stambh scale
for i in (0..aa_dumm_stambh as i32 + 1).rev() {
let text =
math::round::floor(i as f64 * anupat_stambh + graph.scale_y_start, 4).to_string();
let f = ctx.text_extents(&text).expect("Text dimension");
ctx.move_to(
stambh_scale_width - f.width,
height - i as f64 * manjusa_maap + f.width * 0.5,
);
ctx.save().unwrap();
let text = math::round::floor(i as f64 * anupat_stambh + graph.scale_y_start, 4).to_string();
let f = ctx.text_extents(&text);
ctx.move_to(stambh_scale_width - f.width, height - i as f64 * manjusa_maap + f.width * 0.5);
ctx.save();
ctx.rotate(std::f64::consts::PI / -6.0);
ctx.show_text(&text).unwrap();
ctx.restore().unwrap();
ctx.show_text(&text);
ctx.restore();
}
}
/// Adjust stambh and pankti as needed , trim lines and redraws
pub(crate) fn redraw(&mut self) {
pub fn redraw(&mut self) {
let (mx_x, mi_x, mx_y, mi_y) = self.get_extremes();
// stambh
@ -286,7 +267,7 @@ impl Graph {
}
/// find minimun and maximum value from all lines
pub(crate) fn get_extremes(&self) -> (f64, f64, f64, f64) {
pub fn get_extremes(&self) -> (f64, f64, f64, f64){
// trick to avoid no lines
if self.lines.len() == 0 {
return (0.0,0.0,0.0,0.0);
@ -339,16 +320,17 @@ impl Graph {
// tims line form left side of line. Why left?? to avoid wasting time in ponits in range
// it skips i point out of screen to keep a non terminating line experience
pub(crate) fn trim_lines(&mut self) {
pub fn trim_lines(&mut self) {
for (_, line) in self.lines.iter_mut() {
let mut i = 0;
while i < line.points.len() {
match line.points.get(i + 2) {
Some(_) => {
if line.points[i+1].0 < self.scale_x_start {
line.points.remove(i);
}
}
},
None => {
if line.points[line.points.len() - 1].0 < self.scale_x_start {
line.points.clear();

View File

@ -17,95 +17,69 @@
//! Feel free to see through codes. Application is not written to be used as a library for other app. :)
pub(crate) mod graph;
pub(crate) mod port_util;
pub(crate) mod util;
pub mod graph;
pub mod util;
pub mod port_util;
use glib::clone;
use gtk::prelude::*;
use glib::clone;
use rand::Rng;
use std::cell::RefCell;
use std::collections::HashMap;
use std::io::BufReader;
use std::rc::Rc;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::rc::Rc;
use std::cell::RefCell;
use std::io::BufReader;
use std::sync::atomic::Ordering;
use graph::Graph;
use util::Config;
use port_util as putil;
use util::Properties;
// Building and propsuring GUI
pub fn build_ui(app: &gtk::Application) {
let props = Arc::new(Properties::default());
let ui_file = include_str!("ui.glade");
let builder = gtk::Builder::from_string(ui_file);
// Building and configuring GUI
pub fn build_ui(app: &gtk::Application, config: &Arc<Config>) {
let builder = gtk::Builder::from_file(&config.ui_file);
let win = builder
.object::<gtk::ApplicationWindow>("win")
.expect("Resource file missing!");
let win = builder.get_object::<gtk::ApplicationWindow>("win").expect("Resource file missing!");
win.set_application(Some(app));
// Status Bar
let bar = builder
.object::<gtk::Statusbar>("status_bar")
.expect("Resource file missing!");
let bar = builder.get_object::<gtk::Statusbar>("status_bar").expect("Resource file missing!");
// Logging Area
let log_area = builder
.object::<gtk::TextView>("log_area")
.expect("Resource file missing!");
let log_area = builder.get_object::<gtk::TextView>("log_area").expect("Resource file missing!");
// About Window
let about_window = builder
.object::<gtk::AboutDialog>("about_window")
.expect("Resource file missing!");
let about_window = builder.get_object::<gtk::AboutDialog>("about_window").expect("Resource file missing!");
// Save Window
let save_window = builder
.object::<gtk::FileChooserDialog>("save_window")
.expect("Resource file missing!");
let save_window = builder.get_object::<gtk::FileChooserDialog>("save_window").expect("Resource file missing!");
save_window.set_transient_for(Some(&win));
save_window.set_action(gtk::FileChooserAction::Save);
save_window.add_button("_Save", gtk::ResponseType::Apply);
save_window.add_button("_Cancel", gtk::ResponseType::Cancel);
let graph = Graph::new(
builder
.object::<gtk::DrawingArea>("draw_area")
.expect("Resource file missing!"),
0.0,
100.0,
0.0,
100.0,
builder.get_object::<gtk::DrawingArea>("draw_area").expect("Resource file missing!"),
0.0, 100.0,
0.0, 100.0,
false,
true,
false,
true,
HashMap::new(),
0.0,
0.0
);
win.show_all();
// required by signals
let stambh_1 = builder
.object::<gtk::Entry>("stambh_1")
.expect("Resource file missing!");
let stambh_2 = builder
.object::<gtk::Entry>("stambh_2")
.expect("Resource file missing!");
let draw_baarik_box = builder
.object::<gtk::CheckButton>("draw_baarik_box")
.expect("Resource file missing!");
let port = builder
.object::<gtk::ComboBoxText>("port")
.expect("Resource file missing!");
let send_entry = builder
.object::<gtk::Entry>("send_entry")
.expect("Resource file missing!");
let stambh_1 = builder.get_object::<gtk::Entry>("stambh_1").expect("Resource file missing!");
let stambh_2 = builder.get_object::<gtk::Entry>("stambh_2").expect("Resource file missing!");
let draw_baarik_box = builder.get_object::<gtk::CheckButton>("draw_baarik_box").expect("Resource file missing!");
let port = builder.get_object::<gtk::ComboBoxText>("port").expect("Resource file missing!");
let send_entry = builder.get_object::<gtk::Entry>("send_entry").expect("Resource file missing!");
// Signals
builder.connect_signals(|_, handler_name| {
match handler_name {
@ -129,16 +103,16 @@ pub fn build_ui(app: &gtk::Application) {
None
})),
"pankti_value_changed" => Box::new(clone!(@weak graph => @default-return None, move |a| {
let btn = a[0].get::<gtk::SpinButton>().unwrap();
let btn = a[0].get::<gtk::SpinButton>().unwrap().unwrap();
let mut tmp_graph = graph.borrow_mut();
tmp_graph.scale_x_size = btn.value();
tmp_graph.scale_x_size = btn.get_value();
tmp_graph.redraw();
None
})),
"stambh_1_changed" => Box::new(clone!(@weak graph => @default-return None, move |a| {
let entry = a[0].get::<gtk::Entry>().unwrap();
let entry = a[0].get::<gtk::Entry>().unwrap().unwrap();
let mut tmp_graph = graph.borrow_mut();
let val = entry.text().parse::<f64>().unwrap_or(0.0);
let val = entry.get_text().parse::<f64>().unwrap_or(0.0);
let purana_y_start = tmp_graph.scale_y_start;
let y_size = tmp_graph.scale_y_size;
tmp_graph.scale_y_start = val;
@ -147,44 +121,44 @@ pub fn build_ui(app: &gtk::Application) {
None
})),
"stambh_2_changed" => Box::new(clone!(@weak graph => @default-return None, move |a| {
let entry = a[0].get::<gtk::Entry>().unwrap();
let entry = a[0].get::<gtk::Entry>().unwrap().unwrap();
let mut tmp_graph = graph.borrow_mut();
let val = entry.text().parse::<f64>().unwrap_or(0.0);
let val = entry.get_text().parse::<f64>().unwrap_or(0.0);
let y_start = tmp_graph.scale_y_start;
tmp_graph.scale_y_size = (val - y_start).abs();
tmp_graph.redraw();
None
})),
"nimna_stambh_toggled" => Box::new(clone!(@weak graph, @weak stambh_1, @weak stambh_2 => @default-return None, move |a| {
let btn = a[0].get::<gtk::CheckButton>().unwrap();
graph.borrow_mut().auto_adjust_y = !btn.is_active();
stambh_1.set_sensitive(btn.is_active());
stambh_2.set_sensitive(btn.is_active());
if btn.is_active() {
let btn = a[0].get::<gtk::CheckButton>().unwrap().unwrap();
graph.borrow_mut().auto_adjust_y = !btn.get_active();
stambh_1.set_sensitive(btn.get_active());
stambh_2.set_sensitive(btn.get_active());
if btn.get_active() {
stambh_1.emit_activate();
stambh_2.emit_activate();
}
None
})),
"draw_patches_toggled" => Box::new(clone!(@weak graph => @default-return None, move |a| {
let btn = a[0].get::<gtk::CheckButton>().unwrap();
let btn = a[0].get::<gtk::CheckButton>().unwrap().unwrap();
let mut tmp_graph = graph.borrow_mut();
tmp_graph.draw_patch = btn.is_active();
tmp_graph.draw_patch = btn.get_active();
tmp_graph.redraw();
None
})),
"draw_box_toggled" => Box::new(clone!(@weak graph, @weak draw_baarik_box => @default-return None, move |a| {
let btn = a[0].get::<gtk::CheckButton>().unwrap();
let btn = a[0].get::<gtk::CheckButton>().unwrap().unwrap();
let mut tmp_graph = graph.borrow_mut();
draw_baarik_box.set_sensitive(btn.is_active());
tmp_graph.draw_box = btn.is_active();
draw_baarik_box.set_sensitive(btn.get_active());
tmp_graph.draw_box = btn.get_active();
tmp_graph.redraw();
None
})),
"draw_baarik_box_toggled" => Box::new(clone!(@weak graph => @default-return None, move |a| {
let btn = a[0].get::<gtk::CheckButton>().unwrap();
let btn = a[0].get::<gtk::CheckButton>().unwrap().unwrap();
let mut tmp_graph = graph.borrow_mut();
tmp_graph.draw_baarik_box = btn.is_active();
tmp_graph.draw_baarik_box = btn.get_active();
tmp_graph.redraw();
None
})),
@ -195,24 +169,24 @@ pub fn build_ui(app: &gtk::Application) {
tmp_graph.redraw();
None
})),
"bondrate_changed" => Box::new(clone!(@weak props => @default-return None, move |a| {
let btn = a[0].get::<gtk::ComboBoxText>().unwrap();
props.bondrate.store(btn.active_text().unwrap().parse::<u32>().unwrap_or(9600u32), Ordering::SeqCst);
"bondrate_changed" => Box::new(clone!(@weak config => @default-return None, move |a| {
let btn = a[0].get::<gtk::ComboBoxText>().unwrap().unwrap();
config.bondrate.store(btn.get_active_text().unwrap().parse::<u32>().unwrap_or(9600u32), Ordering::SeqCst);
None
})),
"port_changed" => Box::new(clone!(@weak props, @weak bar => @default-return None, move |a| {
let btn = a[0].get::<gtk::ComboBoxText>().unwrap();
if let Some(val) = btn.active_text() {
match props.port.lock() {
"port_changed" => Box::new(clone!(@weak config, @weak bar => @default-return None, move |a| {
let btn = a[0].get::<gtk::ComboBoxText>().unwrap().unwrap();
if let Some(val) = btn.get_active_text() {
match config.port.lock() {
Ok(mut a) => { *a = val.to_string() },
Err(_) => { bar.push(1, "Can't set Port"); }
}
}
None
})),
"refresh_port_clicked" => Box::new(clone!(@weak port, @weak bar, @weak props => @default-return None, move |_| {
"refresh_port_clicked" => Box::new(clone!(@weak port, @weak bar, @weak config => @default-return None, move |_| {
port.remove_all();
match props.status.lock() {
match config.status.lock() {
Ok(mut a) => { *a = util::Status::AVRODTIH },
Err(_) => { bar.push(1, "Can't Avrodhit"); return None; }
}
@ -229,50 +203,53 @@ pub fn build_ui(app: &gtk::Application) {
}
None
})),
"jagrit_btn_clicked" => Box::new(clone!(@weak props, @weak graph, @weak bar => @default-return None, move |_| {
"jagrit_btn_clicked" => Box::new(clone!(@weak config, @weak graph, @weak bar => @default-return None, move |_| {
let mut tmp_graph = graph.borrow_mut();
tmp_graph.pankti_sankya = 0.0;
tmp_graph.lines.clear();
tmp_graph.redraw();
bar.push(1, "Jagrit");
match props.status.lock() {
match config.status.lock() {
Ok(mut a) => { *a = util::Status::PARIVARTIT },
Err(_) => { bar.push(1, "Can't Jagrit"); }
}
None
})),
"avrodith_btn_clicked" => Box::new(clone!(@weak props, @weak bar => @default-return None, move |_| {
"avrodith_btn_clicked" => Box::new(clone!(@weak config, @weak bar => @default-return None, move |_| {
bar.push(1, "Avrodhit");
match props.status.lock() {
match config.status.lock() {
Ok(mut a) => { *a = util::Status::AVRODTIH },
Err(_) => { bar.push(1, "Can't Avrodhit"); }
}
None
})),
"clear_log_clicked" => Box::new(clone!(@weak log_area => @default-return None, move |_| {
log_area.buffer().expect("Couldn't get window").set_text("");
log_area.get_buffer().expect("Couldn't get window").set_text("");
None
})),
"send_entry_key_press_event" => Box::new(clone!(@weak props, @weak bar => @default-return None, move |a| {
let ev = a[1].get::<gdk::Event>().unwrap();
let ev: Result<gdk::EventKey,_> = gdk::FromEvent::from(ev);
if ev.unwrap().keyval() == gdk::keys::constants::Return {
let ent = a[0].get::<gtk::Entry>().unwrap();
putil::send_text(&props, &ent, &bar);
"send_entry_key_press_event" => Box::new(clone!(@weak config, @weak bar => @default-return None, move |a| {
let ev = a[1].get::<gdk::Event>().unwrap().unwrap();
if let Some(val) = ev.get_keyval() {
if let Some(val) = gdk::keys::keyval_name(val) {
if val == "Return" {
let ent = a[0].get::<gtk::Entry>().unwrap().unwrap();
putil::send_text(&config, &ent, &bar);
}
}
}
Some(false.to_value())
})),
"send_btn_clicked" => Box::new(clone!(@weak props, @weak bar, @weak send_entry => @default-return None, move |_| {
putil::send_text(&props, &send_entry, &bar);
"send_btn_clicked" => Box::new(clone!(@weak config, @weak bar, @weak send_entry => @default-return None, move |_| {
putil::send_text(&config, &send_entry, &bar);
None
})),
"about_window_delete" => Box::new(|a| {
let win = a[0].get::<gtk::AboutDialog>().unwrap();
let win = a[0].get::<gtk::AboutDialog>().unwrap().unwrap();
win.hide();
Some(true.to_value())
}),
"save_window_delete" => Box::new(|a| {
let win = a[0].get::<gtk::FileChooserDialog>().unwrap();
let win = a[0].get::<gtk::FileChooserDialog>().unwrap().unwrap();
win.hide();
Some(true.to_value())
}),
@ -290,28 +267,27 @@ pub fn build_ui(app: &gtk::Application) {
let tmp_log_area = log_area.clone();
let tmp_bar = bar.clone();
save_window.connect_response(move |win, res| match res {
save_window.connect_response(move |win, res| {
match res {
gtk::ResponseType::Cancel => win.hide(),
gtk::ResponseType::Apply => {
if let Some(path) = win.filename() {
if let Some(buf) = tmp_log_area.buffer() {
let text = buf
.text(&buf.start_iter(), &buf.end_iter(), false)
.unwrap()
.to_string();
if let Some(path) = win.get_filename() {
if let Some(buf) = tmp_log_area.get_buffer() {
let text = buf.get_text(&buf.get_start_iter(), &buf.get_end_iter(), false).unwrap().to_string();
match std::fs::write(path, text) {
Ok(_) => {
win.hide();
}
},
Err(_) => {
tmp_bar.push(1, "Failed to save!");
}
}
}
}
},
_ => ()
}
_ => (),
});
/*
@ -323,28 +299,24 @@ pub fn build_ui(app: &gtk::Application) {
*/
let (sender, receiver) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
let tmp_props = Arc::clone(&props);
let tmp_config = Arc::clone(&config);
tokio::task::spawn(async move {
let mut bufread: Option<BufReader<Box<dyn serialport::SerialPort>>> = None;
let mut buf = String::new();
loop {
putil::serial_thread_work(&tmp_props, &mut bufread, &sender, &mut buf).await;
putil::serial_thread_work(&tmp_config, &mut bufread, &sender, &mut buf).await;
}
});
// Reciver for MessageSerialThread from the "Thread to manage Serial Port" and works accordingly
let full_log = builder
.object::<gtk::CheckButton>("full_log")
.expect("Resource file missing!");
let graph_data = builder
.object::<gtk::TextView>("graph_data")
.expect("Resource file missing!");
let full_log = builder.get_object::<gtk::CheckButton>("full_log").expect("Resource file missing!");
let graph_data = builder.get_object::<gtk::TextView>("graph_data").expect("Resource file missing!");
let tmp_graph = Rc::clone(&graph);
receiver.attach(None, move |msg| {
match msg {
util::MessageSerialThread::Msg(text, msg_type) => {
receiver_for_msg(text, &msg_type, &full_log, &log_area);
}
},
util::MessageSerialThread::Points(points) => {
receiver_for_points(points, &tmp_graph, &graph_data);
}
@ -357,13 +329,8 @@ pub fn build_ui(app: &gtk::Application) {
}
// Receives MessageSerialThread from Serial Port managing thread adds message to text area
fn receiver_for_msg(
text: String,
msg_type: &util::MessageSerialThreadMsgType,
full_log: &gtk::CheckButton,
log_area: &gtk::TextView,
) {
if !full_log.is_active() {
fn receiver_for_msg(text: String, msg_type: &util::MessageSerialThreadMsgType, full_log: &gtk::CheckButton, log_area: &gtk::TextView) {
if !full_log.get_active(){
if let util::MessageSerialThreadMsgType::Point = msg_type {
return;
}
@ -371,18 +338,15 @@ fn receiver_for_msg(
if text.len() <= 0 {
return;
}
let buf = log_area.buffer().expect("Couldn't get log_area");
buf.insert(&mut buf.end_iter(), &format!("{}\n", text));
log_area.scroll_to_iter(&mut buf.end_iter(), 0.4, true, 0.0, 0.0);
let buf = log_area.get_buffer()
.expect("Couldn't get log_area");
buf.insert(&mut buf.get_end_iter(), &format!("{}\n",text));
log_area.scroll_to_iter(&mut buf.get_end_iter(), 0.4, true, 0.0, 0.0);
log_area.queue_draw();
}
// Receives MessageSerialThread from Serial Port managing thread and add points to draw on graph
fn receiver_for_points(
points: Vec<(String, f64)>,
graph: &Rc<RefCell<Graph>>,
graph_data: &gtk::TextView,
) {
fn receiver_for_points(points: Vec<(String, f64)>, graph: &Rc<RefCell<Graph>>, graph_data: &gtk::TextView) {
for (line, point) in points {
let mut gp = graph.borrow_mut();
@ -390,30 +354,27 @@ fn receiver_for_points(
match gp.lines.get_mut(&line) {
Some(val) => {
val.points.push((sankhya, point));
}
None => {
} None => {
let v = vec![(sankhya, point)];
let mut rng = rand::thread_rng();
gp.lines.insert(
line,
graph::Line::new(rng.gen_range(0.0..1.0), 0.0, rng.gen_range(0.0..1.0), v),
);
let buf = graph_data.buffer().expect("Couldn't get graph_data");
gp.lines.insert(line, graph::Line::new(rng.gen_range(0.0..1.0), 0.0, rng.gen_range(0.0..1.0), v));
let buf = graph_data.get_buffer().expect("Couldn't get graph_data");
buf.set_text("");
gp.lines.iter().for_each(|(key, line)| {
buf.insert(&mut buf.end_iter(), "##");
buf.insert(&mut buf.get_end_iter(), "##");
let tag = gtk::TextTag::new(None);
let rgba = gdk::RGBA::new(line.color.0, line.color.1, line.color.2, 1.0);
tag.set_background_rgba(Some(&rgba));
tag.set_foreground_rgba(Some(&rgba));
buf.tag_table().unwrap().add(&tag);
buf.apply_tag(
&tag,
&buf.iter_at_offset(buf.end_iter().offset() - 2),
&buf.end_iter(),
);
buf.insert(&mut buf.end_iter(), &format!(" {}, ", key));
let rgba = gdk::RGBA {
red: line.color.0,
green: line.color.1,
blue: line.color.2,
alpha: 1.0
};
tag.set_property_background_rgba(Some(&rgba));
tag.set_property_foreground_rgba(Some(&rgba));
buf.get_tag_table().unwrap().add(&tag);
buf.apply_tag(&tag, &buf.get_iter_at_offset(buf.get_end_iter().get_offset() - 2), &buf.get_end_iter());
buf.insert(&mut buf.get_end_iter(), &format!(" {}, ", key));
});
graph_data.queue_draw();
}

View File

@ -12,16 +12,26 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#![windows_subsystem = "windows"]
use gio::{prelude::*, ApplicationFlags};
use gio::prelude::*;
use std::env::args;
use std::sync::Arc;
use tarangam::util::Config;
#[tokio::main]
async fn main() {
let app = gtk::Application::new(Some("sng.tarangm"), ApplicationFlags::default());
let conf = Arc::new(Config::default());
let app = gtk::Application::new(Some("sng.tarangm"), Default::default())
.expect("Failed to initiate gtk");
let tmp_conf = Arc::clone(&conf);
app.connect_activate(move |app| {
tarangam::build_ui(app);
tarangam::build_ui(app, &tmp_conf);
});
app.run();
app.run(&args().collect::<Vec<_>>());
}

View File

@ -19,25 +19,23 @@
use gtk::prelude::*;
use std::sync::Arc;
use std::io::prelude::*;
use std::io::BufReader;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use crate::{util, util::Properties};
use crate::{util::Config, util};
// Controls the thread and read from serial port
pub(crate) async fn serial_thread_work(
config: &Arc<Properties>,
pub async fn serial_thread_work(
config: &Arc<Config>,
bufread: &mut Option<BufReader<Box<dyn serialport::SerialPort>>>,
sender: &glib::Sender<util::MessageSerialThread>,
buf: &mut String,
) {
buf: &mut String) {
let status = match config.status.try_lock() {
Ok(a) => a.to_owned(),
Err(_) => {
return;
}
Err(_) => { return; }
};
match status {
@ -45,11 +43,9 @@ pub(crate) async fn serial_thread_work(
*bufread = None;
match config.status.lock() {
Ok(mut a) => *a = util::Status::SAYAN,
Err(_) => {
return;
}
Err(_) => { return; }
};
}
},
util::Status::JAGRIT => {
if let Some(read) = bufread {
if let Ok(_) = read.read_line(buf) {
@ -71,28 +67,13 @@ pub(crate) async fn serial_thread_work(
points.push((index.to_string(), num));
} else if part.len() == 2 {
points.push((
part[0].trim().to_owned(),
part[1].parse::<f64>().unwrap(),
));
points.push((part[0].trim().to_owned(), part[1].parse::<f64>().unwrap()));
}
}
sender
.send(util::MessageSerialThread::Points(points))
.unwrap();
sender
.send(util::MessageSerialThread::Msg(
line.to_owned(),
util::MessageSerialThreadMsgType::Point,
))
.unwrap();
sender.send(util::MessageSerialThread::Points(points)).unwrap();
sender.send(util::MessageSerialThread::Msg(line.to_owned(), util::MessageSerialThreadMsgType::Point)).unwrap();
} else {
sender
.send(util::MessageSerialThread::Msg(
line.to_owned(),
util::MessageSerialThreadMsgType::Log,
))
.unwrap();
sender.send(util::MessageSerialThread::Msg(line.to_owned(), util::MessageSerialThreadMsgType::Log)).unwrap();
}
}
buf.clear();
@ -100,13 +81,11 @@ pub(crate) async fn serial_thread_work(
}
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
}
},
util::Status::PARIVARTIT => {
let port = match config.port.lock() {
Ok(a) => a.to_owned(),
Err(_) => {
return;
}
Err(_) => { return; }
};
let p = match serialport::new(&port, config.bondrate.load(Ordering::SeqCst)).open() {
Ok(p) => p,
@ -118,24 +97,22 @@ pub(crate) async fn serial_thread_work(
*bufread = Some(BufReader::new(p));
match config.status.try_lock() {
Ok(mut a) => *a = util::Status::JAGRIT,
Err(_) => {
return;
}
Err(_) => { return; }
};
}
_ => {
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
}
},
}
}
// // Sends text through Serial Post to device
pub(crate) fn send_text(config: &Arc<Properties>, entry: &gtk::Entry, bar: &gtk::Statusbar) {
pub fn send_text(config: &Arc<Config>, entry: &gtk::Entry, bar: &gtk::Statusbar) {
let status = match config.status.try_lock() {
Ok(a) => a.to_owned(),
Err(_) => {
return;
}
Err(_) => { return; }
};
if let util::Status::JAGRIT = status {
let port = match config.port.lock() {
@ -155,9 +132,9 @@ pub(crate) fn send_text(config: &Arc<Properties>, entry: &gtk::Entry, bar: &gtk:
};
unsafe {
p.write_all(entry.text().to_string().as_bytes_mut())
.unwrap();
p.write_all(entry.get_text().to_string().as_bytes_mut()).unwrap();
}
entry.set_text("");
}
}

View File

@ -21,41 +21,48 @@ use std::sync::{atomic::*, Mutex};
/// Status of Serial reading
#[derive(Debug, Clone, Copy)]
pub(crate) enum Status {
pub enum Status {
AVRODTIH, // Mode of being stopped
SAYAN, // Mode of Sleeping
JAGRIT, // Mode of Active
PARIVARTIT, // Mode of being values modified
PARIVARTIT // Mode of being values modified
}
#[derive(Debug)]
pub(crate) struct Properties {
pub(crate) bondrate: AtomicU32,
pub(crate) port: Mutex<String>,
pub(crate) status: Mutex<Status>,
pub struct Config {
pub ui_file: String,
pub bondrate: AtomicU32,
pub port: Mutex<String>,
pub status: Mutex<Status>
}
/// For communication between mpsc of graph and serial port
#[allow(dead_code)]
#[derive(Debug)]
pub(crate) enum MessageSerialThread {
pub enum MessageSerialThread {
Msg(String, MessageSerialThreadMsgType),
Points(Vec<(String, f64)>),
Status(String),
Status(String)
}
#[derive(Debug)]
pub(crate) enum MessageSerialThreadMsgType {
pub enum MessageSerialThreadMsgType {
Point,
Log,
Log
}
impl Properties {
pub(crate) fn default() -> Self {
Properties {
impl Config {
pub fn default() -> Self {
let ui_file = std::env::var("TARANGAM_UI_FILE");
Config {
ui_file: match ui_file {
Ok(val) => val,
Err(_) => std::env::current_exe().unwrap().parent().unwrap()
.join("ui.glade").to_str().unwrap().to_owned()
},
bondrate: AtomicU32::new(9600),
port: Mutex::new(String::new()),
status: Mutex::new(Status::AVRODTIH),
status: Mutex::new(Status::AVRODTIH)
}
}
}

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<!-- Generated with glade 3.38.1 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkAboutDialog" id="about_window">
<property name="can-focus">False</property>
<property name="title" translatable="yes">Tarangam</property>
<property name="icon">chitra-small.png</property>
<property name="icon">chitra.svg</property>
<property name="type-hint">dialog</property>
<property name="program-name">Tarangam (तरंगम्)</property>
<property name="comments" translatable="yes">A simple serial plotter.
@ -54,7 +54,7 @@
</object>
<object class="GtkFileChooserDialog" id="save_window">
<property name="can-focus">False</property>
<property name="icon">chitra-small.png</property>
<property name="icon">chitra.svg</property>
<property name="type-hint">dialog</property>
<property name="action">select-folder</property>
<signal name="close" handler="save_window_close" swapped="no"/>
@ -98,7 +98,7 @@
<property name="title" translatable="yes">Tarangam</property>
<property name="default-width">850</property>
<property name="default-height">600</property>
<property name="icon">chitra-small.png</property>
<property name="icon">chitra.svg</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>