move rust-sciter in
This commit is contained in:
parent
bdfb59dd1a
commit
237e889604
540
Cargo.lock
generated
540
Cargo.lock
generated
@ -46,6 +46,26 @@ dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "andrew"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"line_drawing",
|
||||
"rusttype 0.7.9",
|
||||
"walkdir",
|
||||
"xdg",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android_glue"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
|
||||
|
||||
[[package]]
|
||||
name = "android_log-sys"
|
||||
version = "0.2.0"
|
||||
@ -79,14 +99,23 @@ version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
|
||||
dependencies = [
|
||||
"num-traits 0.2.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -176,8 +205,8 @@ dependencies = [
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
@ -200,8 +229,8 @@ dependencies = [
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
@ -373,6 +402,21 @@ dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.18.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"core-foundation 0.6.4",
|
||||
"core-graphics 0.17.3",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.24.0"
|
||||
@ -383,7 +427,7 @@ dependencies = [
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"core-foundation 0.9.1",
|
||||
"core-graphics",
|
||||
"core-graphics 0.22.2",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"objc",
|
||||
@ -438,6 +482,16 @@ dependencies = [
|
||||
"x11-clipboard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.6.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.7.0"
|
||||
@ -476,6 +530,18 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.17.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation 0.6.4",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.22.2"
|
||||
@ -537,7 +603,7 @@ dependencies = [
|
||||
"ndk-glue",
|
||||
"nix 0.20.0",
|
||||
"oboe",
|
||||
"parking_lot",
|
||||
"parking_lot 0.11.1",
|
||||
"stdweb",
|
||||
"thiserror",
|
||||
"web-sys",
|
||||
@ -596,8 +662,8 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"strsim 0.9.3",
|
||||
"syn",
|
||||
]
|
||||
@ -609,7 +675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -758,8 +824,8 @@ version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -769,8 +835,8 @@ version = "0.99.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f82b1b72f1263f214c0f823371768776c4f5841b942c9883aa8e5ec584fd0ba6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -893,7 +959,7 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
name = "enigo"
|
||||
version = "0.0.14"
|
||||
dependencies = [
|
||||
"core-graphics",
|
||||
"core-graphics 0.22.2",
|
||||
"libc",
|
||||
"log",
|
||||
"objc",
|
||||
@ -937,8 +1003,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"rustversion",
|
||||
"syn",
|
||||
"synstructure",
|
||||
@ -951,8 +1017,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcc7f65832b62ed38939f98966824eb6294911c3629b0e9a262bfb80836d9686"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"rustversion",
|
||||
"syn",
|
||||
"synstructure",
|
||||
@ -975,7 +1041,7 @@ checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.2.7",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
@ -1105,8 +1171,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -1309,8 +1375,8 @@ dependencies = [
|
||||
"itertools",
|
||||
"proc-macro-crate",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -1688,6 +1754,24 @@ dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "line_drawing"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9"
|
||||
dependencies = [
|
||||
"num-traits 0.2.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.4"
|
||||
@ -1751,12 +1835,28 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maybe-uninit"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
|
||||
|
||||
[[package]]
|
||||
name = "memmap"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.1.0"
|
||||
@ -1873,8 +1973,8 @@ checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -1895,6 +1995,19 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.17.0"
|
||||
@ -1970,8 +2083,8 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -2030,8 +2143,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -2111,6 +2224,15 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7"
|
||||
dependencies = [
|
||||
"num-traits 0.2.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pango"
|
||||
version = "0.9.1"
|
||||
@ -2152,6 +2274,17 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
|
||||
dependencies = [
|
||||
"lock_api 0.3.4",
|
||||
"parking_lot_core 0.6.2",
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.1"
|
||||
@ -2159,8 +2292,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
"lock_api 0.4.4",
|
||||
"parking_lot_core 0.8.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"cloudabi",
|
||||
"libc",
|
||||
"redox_syscall 0.1.57",
|
||||
"rustc_version",
|
||||
"smallvec 0.6.14",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2172,8 +2320,8 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"redox_syscall 0.2.7",
|
||||
"smallvec 1.6.1",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
@ -2183,6 +2331,12 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.7.24"
|
||||
@ -2273,8 +2427,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
"version_check 0.9.3",
|
||||
]
|
||||
@ -2285,8 +2439,8 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"version_check 0.9.3",
|
||||
]
|
||||
|
||||
@ -2302,13 +2456,22 @@ version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"unicode-xid 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2408,13 +2571,22 @@ dependencies = [
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2 1.0.26",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2604,6 +2776,15 @@ dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
@ -2613,6 +2794,12 @@ dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.7"
|
||||
@ -2629,7 +2816,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
||||
dependencies = [
|
||||
"getrandom 0.2.2",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.2.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2733,6 +2920,15 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustdesk"
|
||||
version = "1.1.2"
|
||||
@ -2742,10 +2938,10 @@ dependencies = [
|
||||
"cc",
|
||||
"cfg-if 1.0.0",
|
||||
"clap",
|
||||
"cocoa",
|
||||
"cocoa 0.24.0",
|
||||
"copypasta",
|
||||
"core-foundation 0.9.1",
|
||||
"core-graphics",
|
||||
"core-graphics 0.22.2",
|
||||
"cpal",
|
||||
"crc32fast",
|
||||
"ctrlc",
|
||||
@ -2809,6 +3005,26 @@ dependencies = [
|
||||
"security-framework",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusttype"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "310942406a39981bed7e12b09182a221a29e0990f3e7e0c971f131922ed135d5"
|
||||
dependencies = [
|
||||
"rusttype 0.8.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusttype"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f61411055101f7b60ecf1041d87fb74205fb20b0c7a723f07ef39174cf6b4c0"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"ordered-float",
|
||||
"stb_truetype",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.4"
|
||||
@ -2843,12 +3059,14 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sciter-rs"
|
||||
version = "0.5.53"
|
||||
source = "git+https://github.com/sciter-sdk/rust-sciter?rev=7702fb17290e76606bdd7010a0c3cbb32e85db76#7702fb17290e76606bdd7010a0c3cbb32e85db76"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"raw-window-handle",
|
||||
"winapi 0.3.9",
|
||||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2914,6 +3132,21 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "0.9.15"
|
||||
@ -2935,8 +3168,8 @@ version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -3003,12 +3236,38 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "0.6.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0"
|
||||
dependencies = [
|
||||
"maybe-uninit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
||||
|
||||
[[package]]
|
||||
name = "smithay-client-toolkit"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ccb8c57049b2a34d2cc2b203fa785020ba0129d31920ef0d317430adaf748fa"
|
||||
dependencies = [
|
||||
"andrew",
|
||||
"bitflags",
|
||||
"dlib 0.4.2",
|
||||
"lazy_static",
|
||||
"memmap",
|
||||
"nix 0.14.1",
|
||||
"wayland-client 0.21.13",
|
||||
"wayland-commons 0.21.13",
|
||||
"wayland-protocols 0.21.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smithay-client-toolkit"
|
||||
version = "0.12.3"
|
||||
@ -3021,9 +3280,9 @@ dependencies = [
|
||||
"log",
|
||||
"memmap2",
|
||||
"nix 0.18.0",
|
||||
"wayland-client",
|
||||
"wayland-client 0.28.5",
|
||||
"wayland-cursor",
|
||||
"wayland-protocols",
|
||||
"wayland-protocols 0.28.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3032,8 +3291,8 @@ version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06384dfaf645908220d976ae24ed39f6cf92efecb0225ea0a948e403014de527"
|
||||
dependencies = [
|
||||
"smithay-client-toolkit",
|
||||
"wayland-client",
|
||||
"smithay-client-toolkit 0.12.3",
|
||||
"wayland-client 0.28.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3064,6 +3323,15 @@ version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "stb_truetype"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f77b6b07e862c66a9f3e62a07588fee67cd90a9135a2b942409f195507b4fb51"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stdweb"
|
||||
version = "0.1.3"
|
||||
@ -3101,8 +3369,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -3112,9 +3380,9 @@ version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"unicode-xid 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3123,10 +3391,10 @@ version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
"unicode-xid",
|
||||
"unicode-xid 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3176,7 +3444,7 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"rand 0.8.3",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.2.7",
|
||||
"remove_dir_all",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
@ -3223,8 +3491,8 @@ version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -3268,8 +3536,8 @@ version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -3315,8 +3583,8 @@ version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -3353,6 +3621,12 @@ version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
@ -3446,8 +3720,8 @@ dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -3458,7 +3732,7 @@ version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"quote 1.0.9",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
@ -3468,8 +3742,8 @@ version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
@ -3481,6 +3755,21 @@ version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
|
||||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
version = "0.21.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49963e5f9eeaf637bfcd1b9f0701c99fd5cd05225eb51035550d4272806f2713"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"downcast-rs",
|
||||
"libc",
|
||||
"nix 0.14.1",
|
||||
"wayland-commons 0.21.13",
|
||||
"wayland-scanner 0.21.13",
|
||||
"wayland-sys 0.21.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
version = "0.28.5"
|
||||
@ -3492,9 +3781,19 @@ dependencies = [
|
||||
"libc",
|
||||
"nix 0.20.0",
|
||||
"scoped-tls",
|
||||
"wayland-commons",
|
||||
"wayland-scanner",
|
||||
"wayland-sys",
|
||||
"wayland-commons 0.28.5",
|
||||
"wayland-scanner 0.28.5",
|
||||
"wayland-sys 0.28.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-commons"
|
||||
version = "0.21.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c08896768b667e1df195d88a62a53a2d1351a1ed96188be79c196b35bb32ec"
|
||||
dependencies = [
|
||||
"nix 0.14.1",
|
||||
"wayland-sys 0.21.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3505,8 +3804,8 @@ checksum = "8bd75ae380325dbcff2707f0cd9869827ea1d2d6d534cff076858d3f0460fd5a"
|
||||
dependencies = [
|
||||
"nix 0.20.0",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
"wayland-sys",
|
||||
"smallvec 1.6.1",
|
||||
"wayland-sys 0.28.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3516,10 +3815,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b37e5455ec72f5de555ec39b5c3704036ac07c2ecd50d0bffe02d5fe2d4e65ab"
|
||||
dependencies = [
|
||||
"nix 0.20.0",
|
||||
"wayland-client",
|
||||
"wayland-client 0.28.5",
|
||||
"xcursor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-protocols"
|
||||
version = "0.21.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4afde2ea2a428eee6d7d2c8584fdbe8b82eee8b6c353e129a434cd6e07f42145"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"wayland-client 0.21.13",
|
||||
"wayland-commons 0.21.13",
|
||||
"wayland-scanner 0.21.13",
|
||||
"wayland-sys 0.21.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-protocols"
|
||||
version = "0.28.5"
|
||||
@ -3527,9 +3839,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95df3317872bcf9eec096c864b69aa4769a1d5d6291a5b513f8ba0af0efbd52c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"wayland-client",
|
||||
"wayland-commons",
|
||||
"wayland-scanner",
|
||||
"wayland-client 0.28.5",
|
||||
"wayland-commons 0.28.5",
|
||||
"wayland-scanner 0.28.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-scanner"
|
||||
version = "0.21.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf3828c568714507315ee425a9529edc4a4aa9901409e373e9e0027e7622b79e"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3538,11 +3861,21 @@ version = "0.28.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389d680d7bd67512dc9c37f39560224327038deb0f0e8d33f870900441b68720"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-sys"
|
||||
version = "0.21.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "520ab0fd578017a0ee2206623ba9ef4afe5e8f23ca7b42f6acfba2f4e66b1628"
|
||||
dependencies = [
|
||||
"dlib 0.4.2",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-sys"
|
||||
version = "0.28.5"
|
||||
@ -3668,6 +4001,31 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winit"
|
||||
version = "0.19.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e96eb4bb472fa43e718e8fa4aef82f86cd9deac9483a1e1529230babdb394a8"
|
||||
dependencies = [
|
||||
"android_glue",
|
||||
"backtrace",
|
||||
"bitflags",
|
||||
"cocoa 0.18.5",
|
||||
"core-foundation 0.6.4",
|
||||
"core-graphics 0.17.3",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"objc",
|
||||
"parking_lot 0.9.0",
|
||||
"percent-encoding",
|
||||
"raw-window-handle",
|
||||
"smithay-client-toolkit 0.4.6",
|
||||
"wayland-client 0.21.13",
|
||||
"winapi 0.3.9",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.6.2"
|
||||
@ -3714,6 +4072,18 @@ dependencies = [
|
||||
"xcb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-dl"
|
||||
version = "2.18.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"maybe-uninit",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xcb"
|
||||
version = "0.9.0"
|
||||
@ -3733,6 +4103,12 @@ dependencies = [
|
||||
"nom 6.1.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xdg"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.3"
|
||||
|
@ -46,7 +46,7 @@ cpal = { git = "https://github.com/rustaudio/cpal" }
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
machine-uid = "0.2"
|
||||
mac_address = "1.1"
|
||||
sciter-rs = { git = "https://github.com/sciter-sdk/rust-sciter", rev = "7702fb17290e76606bdd7010a0c3cbb32e85db76" }
|
||||
sciter-rs = { path = "libs/rust-sciter" }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
systray = { path = "libs/systray-rs" }
|
||||
|
98
libs/rust-sciter/.appveyor.yml
Normal file
98
libs/rust-sciter/.appveyor.yml
Normal file
@ -0,0 +1,98 @@
|
||||
version: 0.5.0.{build}
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- travis
|
||||
|
||||
image:
|
||||
- Visual Studio 2017
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
CHANNEL: stable
|
||||
ARCH: 64
|
||||
|
||||
- TARGET: i686-pc-windows-msvc
|
||||
CHANNEL: stable
|
||||
ARCH: 32
|
||||
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
CHANNEL: stable
|
||||
ARCH: 64skia
|
||||
|
||||
- TARGET: i686-pc-windows-msvc
|
||||
CHANNEL: stable
|
||||
ARCH: 32skia
|
||||
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
CHANNEL: stable
|
||||
ARCH: 64
|
||||
FEATURES: --features "dynamic"
|
||||
|
||||
- TARGET: i686-pc-windows-msvc
|
||||
CHANNEL: stable
|
||||
ARCH: 32
|
||||
FEATURES: --features "dynamic"
|
||||
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
CHANNEL: nightly
|
||||
ARCH: 64
|
||||
|
||||
- TARGET: i686-pc-windows-msvc
|
||||
CHANNEL: nightly
|
||||
ARCH: 32
|
||||
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
CHANNEL: 1.38.0
|
||||
ARCH: 64
|
||||
|
||||
- TARGET: i686-pc-windows-msvc
|
||||
CHANNEL: 1.38.0
|
||||
ARCH: 32
|
||||
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
CHANNEL: 1.38.0
|
||||
ARCH: 64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
|
||||
|
||||
cache:
|
||||
- C:\Users\appveyor\.cargo\registry
|
||||
#- C:\projects\deps -> appveyor.yml
|
||||
#- target
|
||||
|
||||
install:
|
||||
- cmd: echo Testing sciter%ARCH% with Rust %CHANNEL%.
|
||||
- cmd: echo Current directory is %APPVEYOR_BUILD_FOLDER%
|
||||
- cmd: mkdir ..\deps
|
||||
- curl -sSLo "..\deps\sciter.dll" "https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x%ARCH%/sciter.dll"
|
||||
- curl -sSLo "..\deps\rustup-init.exe" "https://win.rustup.rs/"
|
||||
- ..\deps\rustup-init.exe -y --default-host %TARGET% --default-toolchain %CHANNEL%
|
||||
- cmd: set PATH=%PATH%;C:\Users\appveyor\.cargo\bin;C:\projects\deps
|
||||
|
||||
before_build:
|
||||
- cmd: cd
|
||||
- rustc --version
|
||||
- cargo update
|
||||
|
||||
build_script:
|
||||
- cmd: echo Building library
|
||||
- cargo build --release --all %FEATURES%
|
||||
|
||||
- cmd: echo Building examples
|
||||
- cargo build --example first --verbose
|
||||
- cargo build --example windowless --features windowless
|
||||
- cargo build --release --examples %FEATURES%
|
||||
|
||||
test_script:
|
||||
- cargo run --example first %FEATURES%
|
||||
- cargo run --example first %FEATURES%
|
||||
- cargo run --example first %FEATURES% -- C:/projects/deps/sciter.dll
|
||||
|
||||
- cargo test -p sciter-rs %FEATURES%
|
||||
- cargo test -p sciter-rs %FEATURES% --release
|
||||
|
||||
- cargo test -p sciter-serde %FEATURES%
|
||||
- cargo test -p sciter-serde %FEATURES% --release
|
1
libs/rust-sciter/.clippy.toml
Normal file
1
libs/rust-sciter/.clippy.toml
Normal file
@ -0,0 +1 @@
|
||||
doc-valid-idents = ["TIScript"]
|
20
libs/rust-sciter/.editorconfig
Normal file
20
libs/rust-sciter/.editorconfig
Normal file
@ -0,0 +1,20 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.rs]
|
||||
indent_style = tab
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
|
||||
[*.{yml,toml,md}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
115
libs/rust-sciter/.github/workflows/cargo.yml
vendored
Normal file
115
libs/rust-sciter/.github/workflows/cargo.yml
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
name: Build-n-Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- travis
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
# Look:
|
||||
# https://github.com/actions/starter-workflows/blob/master/ci/rust.yml
|
||||
#
|
||||
# Simple, right? Right.
|
||||
# But we need to:
|
||||
# * download a specific Sciter library matching the running OS
|
||||
# * figure out where to save it
|
||||
# * add it to the $PATH
|
||||
#
|
||||
# yet,
|
||||
# * in case of macOS realize that it doesn't have Rust installed, so
|
||||
# * install it manually and don't forget to add cargo and rustc to the $PATH on each step
|
||||
# * and in case of Linux install additional packages for GTK3
|
||||
#
|
||||
# So, now we're ended up with this ugly script.
|
||||
|
||||
jobs:
|
||||
fetch:
|
||||
name: Fetch dependencies
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
# macOS doesn't have Rust installed
|
||||
# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners#macos-1015
|
||||
# we will try to install it manually below.
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
- name: Environment
|
||||
shell: bash
|
||||
env:
|
||||
RUNNER_CONTEXT: ${{ toJson(runner) }}
|
||||
SCITER_DEPS: ${{ runner.workspace }}
|
||||
run: |
|
||||
echo HOME is "$HOME"
|
||||
echo workspace is "$SCITER_DEPS"
|
||||
echo temp is "$TEMP"
|
||||
echo runner is "$RUNNER_CONTEXT"
|
||||
echo cargo is at `which cargo`
|
||||
echo rustc is at `which rustc`
|
||||
command -v cargo && rustc -vV
|
||||
echo done
|
||||
|
||||
build:
|
||||
needs: [fetch]
|
||||
name: Build and test
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Windows deps
|
||||
if: runner.os == 'Windows'
|
||||
# Windows: download sciter library
|
||||
run: curl -sSLo "%SCITER_DEPS%/sciter.dll" "https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll"
|
||||
shell: cmd
|
||||
env:
|
||||
SCITER_DEPS: ${{ runner.workspace }}
|
||||
|
||||
- name: Linux deps
|
||||
if: runner.os == 'Linux'
|
||||
# Linux: download sciter library && install libgtk-3-dev
|
||||
run: |
|
||||
curl -so "$SCITER_DEPS/libsciter-gtk.so" "https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so"
|
||||
sudo apt-get update -y && sudo apt-get install libgtk-3-dev libgtk-3-0 libstdc++-6-pic -y
|
||||
env:
|
||||
SCITER_DEPS: ${{ runner.workspace }}
|
||||
|
||||
- name: macOS deps
|
||||
if: runner.os == 'macOS'
|
||||
# OSX: download sciter library && install rustup
|
||||
run: |
|
||||
curl -so "$SCITER_DEPS/sciter-osx-64.dylib" "https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/sciter-osx-64.dylib"
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- --profile minimal -y
|
||||
test -f $HOME/.cargo/env && source $HOME/.cargo/env
|
||||
echo cargo is at `which cargo`
|
||||
echo rustc is at `which rustc`
|
||||
env:
|
||||
SCITER_DEPS: ${{ runner.workspace }}
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
test -f $HOME/.cargo/env && source $HOME/.cargo/env
|
||||
cargo build --all
|
||||
cargo build --examples
|
||||
|
||||
- name: Tests
|
||||
shell: bash
|
||||
run: |
|
||||
test -f $HOME/.cargo/env && source $HOME/.cargo/env
|
||||
export PATH="$PATH:$SCITER_DEPS"
|
||||
cargo run --example first
|
||||
cargo test -p sciter-rs
|
||||
cargo test -p sciter-serde
|
||||
env:
|
||||
SCITER_DEPS: ${{ runner.workspace }}
|
4
libs/rust-sciter/.gitignore
vendored
Normal file
4
libs/rust-sciter/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
target
|
||||
Cargo.lock
|
||||
.vscode/
|
||||
.vs/
|
6
libs/rust-sciter/.rustfmt.toml
Normal file
6
libs/rust-sciter/.rustfmt.toml
Normal file
@ -0,0 +1,6 @@
|
||||
# `rustfmt --config-help` for formatting options
|
||||
max_width = 140
|
||||
ideal_width = 120
|
||||
tab_spaces = 2
|
||||
hard_tabs = true
|
||||
blank_lines_upper_bound = 2
|
99
libs/rust-sciter/.travis.yml
Normal file
99
libs/rust-sciter/.travis.yml
Normal file
@ -0,0 +1,99 @@
|
||||
# Based on the "trust" template v0.1.2
|
||||
# https://github.com/japaric/trust/tree/v0.1.2
|
||||
|
||||
dist: xenial
|
||||
sudo: false
|
||||
language: rust
|
||||
compiler: gcc
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
rust:
|
||||
- stable
|
||||
- nightly
|
||||
- 1.40.0
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
- os: osx
|
||||
osx_image: xcode11
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- travis
|
||||
|
||||
notifications:
|
||||
email: change
|
||||
|
||||
|
||||
cache: cargo
|
||||
before_cache:
|
||||
# Travis can't cache files that are not readable by "others"
|
||||
- chmod -R a+r $HOME/.cargo
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
packages:
|
||||
- libgtk-3-dev
|
||||
- libgtk-3-0
|
||||
- libstdc++-6-pic
|
||||
|
||||
|
||||
before_install:
|
||||
- set -e
|
||||
- rustup self update
|
||||
|
||||
install:
|
||||
- source ~/.cargo/env || true
|
||||
- export SDK_URL=https://raw.githubusercontent.com/c-smile/sciter-sdk/master
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then export SDK_DLL="$TRAVIS_BUILD_DIR/sciter-osx-64.dylib"; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then export SDK_DLL="$TRAVIS_BUILD_DIR/libsciter-gtk.so"; fi
|
||||
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then curl -so "$SDK_DLL" $SDK_URL/bin.osx/sciter-osx-64.dylib; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -so "$SDK_DLL" $SDK_URL/bin.lnx/x64/libsciter-gtk.so; fi
|
||||
|
||||
before_script:
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:$TRAVIS_BUILD_DIR"; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then cp "$TRAVIS_BUILD_DIR/sciter-osx-64.dylib" "$TRAVIS_BUILD_DIR/libsciter-osx-64.dylib"; fi
|
||||
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$TRAVIS_BUILD_DIR"; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then export RUSTFLAGS='-C link-arg=-Wl,--unresolved-symbols=ignore-in-shared-libs'; fi
|
||||
|
||||
- export PATH="$PATH:$TRAVIS_BUILD_DIR"
|
||||
- export LIBRARY_PATH="$LIBRARY_PATH:$TRAVIS_BUILD_DIR"
|
||||
- export RUST_BACKTRACE=full
|
||||
|
||||
- #ls /usr/lib/x86_64-linux-gnu/libstdc++*
|
||||
- #strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBC
|
||||
- #file $SDK_DLL
|
||||
- gcc --version
|
||||
- rustc --version
|
||||
|
||||
script:
|
||||
- cargo update
|
||||
|
||||
- cargo build --example first --verbose
|
||||
- cargo run --example first
|
||||
- cargo run --example first --features "dynamic"
|
||||
- cargo run --example first --features "dynamic" -- "$SDK_DLL"
|
||||
|
||||
- cargo build --all
|
||||
- cargo build --all --release
|
||||
- cargo build --examples --release
|
||||
- cargo build --example windowless --features windowless
|
||||
|
||||
- cargo test -p sciter-rs
|
||||
- cargo test -p sciter-rs --release
|
||||
|
||||
- cargo test -p sciter-serde
|
||||
- cargo test -p sciter-serde --release
|
||||
|
||||
after_script: set +e
|
111
libs/rust-sciter/Cargo.toml
Normal file
111
libs/rust-sciter/Cargo.toml
Normal file
@ -0,0 +1,111 @@
|
||||
[package]
|
||||
name = "sciter-rs"
|
||||
version = "0.5.53"
|
||||
description = "Rust bindings for Sciter - Embeddable HTML/CSS/script engine (cross-platform desktop GUI toolkit). Also capable with DirectX / OpenGL."
|
||||
keywords = ["gui", "gtk", "cocoa", "opengl", "skia"]
|
||||
categories = ["gui", "web-programming", "rendering::graphics-api", "api-bindings"]
|
||||
|
||||
authors = ["pravic <ehysta@gmail.com>"]
|
||||
repository = "https://github.com/sciter-sdk/rust-sciter"
|
||||
documentation = "https://docs.rs/sciter-rs"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
|
||||
exclude = [".gitignore", ".editorconfig", ".appveyor.yml", "clippy.toml"]
|
||||
|
||||
[badges]
|
||||
appveyor = { repository = "sciter-sdk/rust-sciter" }
|
||||
travis-ci = { repository = "sciter-sdk/rust-sciter" }
|
||||
|
||||
maintenance = { status = "passively-maintained" }
|
||||
|
||||
[lib]
|
||||
name = "sciter"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["rlib"]
|
||||
|
||||
[features]
|
||||
default = ["dynamic"]
|
||||
|
||||
# Enable nightly compiler features (currently doesn't use any).
|
||||
nightly = []
|
||||
|
||||
# Build as a Sciter extension library.
|
||||
# see "examples/extension"
|
||||
# note: this feature can't be tested.
|
||||
extension = []
|
||||
|
||||
# Load Sciter DLL dynamically from the path specified by `sciter::set_library`.
|
||||
# Otherwise, links statically to `libsciter-gtk.so` or `sciter-osx-64.dylib`.
|
||||
dynamic = []
|
||||
|
||||
# Build this crate specifically for Sciter.Lite versions
|
||||
# which are incompatible with the regular ones.
|
||||
windowless = []
|
||||
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
lazy_static = "1.0"
|
||||
|
||||
[target.x86_64-apple-darwin.dependencies]
|
||||
objc = "0.2"
|
||||
objc-foundation = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
winit = "0.19"
|
||||
winapi = { version = "0.3", features = [
|
||||
"impl-default",
|
||||
"winuser",
|
||||
"wingdi",
|
||||
"sysinfoapi",
|
||||
] }
|
||||
raw-window-handle = "0.3"
|
||||
|
||||
[[example]]
|
||||
name = "first"
|
||||
path = "examples/first.rs"
|
||||
|
||||
[[example]]
|
||||
name = "minimal"
|
||||
path = "examples/minimal.rs"
|
||||
|
||||
[[example]]
|
||||
name = "download"
|
||||
path = "examples/download.rs"
|
||||
|
||||
[[example]]
|
||||
name = "dom"
|
||||
path = "examples/dom.rs"
|
||||
|
||||
[[example]]
|
||||
name = "fire_event"
|
||||
path = "examples/fire_event.rs"
|
||||
|
||||
[[example]]
|
||||
name = "interop"
|
||||
path = "examples/interop.rs"
|
||||
|
||||
[[example]]
|
||||
name = "threads"
|
||||
path = "examples/threads.rs"
|
||||
|
||||
[[example]]
|
||||
name = "archived"
|
||||
path = "examples/archived.rs"
|
||||
|
||||
[[example]]
|
||||
name = "video"
|
||||
path = "examples/video.rs"
|
||||
|
||||
[[example]]
|
||||
name = "clock"
|
||||
path = "examples/clock.rs"
|
||||
|
||||
[[example]]
|
||||
name = "windowless"
|
||||
path = "examples/windowless.rs"
|
||||
|
||||
[[example]]
|
||||
name = "som"
|
||||
path = "examples/som.rs"
|
21
libs/rust-sciter/LICENSE
Normal file
21
libs/rust-sciter/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 pravic
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
159
libs/rust-sciter/README.md
Normal file
159
libs/rust-sciter/README.md
Normal file
@ -0,0 +1,159 @@
|
||||
# Rust bindings for Sciter
|
||||
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/cbrisyh792mmmd08/branch/master?svg=true)](https://ci.appveyor.com/project/pravic/rust-sciter)
|
||||
[![Build Status](https://img.shields.io/travis/sciter-sdk/rust-sciter/master.svg)](https://travis-ci.org/sciter-sdk/rust-sciter)
|
||||
[![Minimum supported Rust version](https://img.shields.io/badge/rustc-1.38+-green.svg)](https://github.com/sciter-sdk/rust-sciter/commits/master/.travis.yml)
|
||||
[![Current Version](https://img.shields.io/crates/v/sciter-rs.svg)](https://crates.io/crates/sciter-rs)
|
||||
[![Documentation](https://docs.rs/sciter-rs/badge.svg)](https://docs.rs/sciter-rs)
|
||||
[![License](https://img.shields.io/crates/l/sciter-rs.svg)](https://crates.io/crates/sciter-rs)
|
||||
[![Join the forums at https://sciter.com/forums](https://img.shields.io/badge/forum-sciter.com-orange.svg)](https://sciter.com/forums)
|
||||
|
||||
Check [this page](https://sciter.com/developers/sciter-sdk-bindings/) for other language bindings (Delphi / D / Go / .NET / Python / Rust).
|
||||
|
||||
----
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
Sciter is an embeddable [multiplatform](https://sciter.com/sciter/crossplatform/) HTML/CSS/script engine with GPU accelerated rendering designed to render modern desktop application UI. It's a compact, single dll/dylib/so file (4-8 mb) engine without any additional dependencies.
|
||||
|
||||
|
||||
## Screenshots
|
||||
|
||||
Check the [screenshot gallery](https://github.com/oskca/sciter#sciter-desktop-ui-examples) of desktop UI examples
|
||||
and [DirectX UI integration](https://github.com/pravic/rust-gfx-sciter) via [Rust GFX](https://github.com/gfx-rs/gfx).
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
Physically Sciter is a mono library which contains:
|
||||
|
||||
* [HTML and CSS](https://sciter.com/developers/for-web-programmers/) rendering engine based on the H-SMILE core used in [HTMLayout](https://terrainformatica.com/a-homepage-section/htmlayout/),
|
||||
* JavaScript alike [Scripting engine](https://sciter.com/developers/sciter-docs/) – core of [TIScript](https://sciter.com/developers/for-web-programmers/tiscript-vs-javascript/) which by itself is based on [c-smile](https://c-smile.sourceforge.net/) engine,
|
||||
* Persistent [Database](https://sciter.com/docs/content/script/Storage.htm) (a.k.a. [JSON DB](https://terrainformatica.com/2006/10/what-the-hell-is-that-json-db/)) based on excellent DB products of [Konstantin Knizhnik](http://garret.ru/databases.html).
|
||||
* [Graphics](https://sciter.com/docs/content/sciter/Graphics.htm) module that uses native graphics primitives provided by supported platforms: Direct2D on Windows 7 and above, GDI+ on Windows XP, CoreGraphics on MacOS, Cairo on Linux/GTK. Yet there is an option to use built-in [Skia/OpenGL](https://skia.org/) backend on each platform.
|
||||
* Network communication module, it relies on platform HTTP client primitives and/or [Libcurl](https://curl.haxx.se/).
|
||||
|
||||
|
||||
Internally it contains the following modules:
|
||||
|
||||
* **CSS** – CSS parser and the collection of parsed CSS rules, etc.
|
||||
* **HTML DOM** – HTML parser and DOM tree implementation.
|
||||
* **layout managers** – collection of various layout managers – text layout, default block layout, flex layouts. Support of positioned floating elements is also here. This module does the layout calculations heavy lifting. This module is also responsible for the rendering of layouts.
|
||||
* **input behaviors** – a collection of built-in behaviors – code behind "active" DOM elements: `<input>`, `<select>`, `<textarea>`, etc.
|
||||
* **script module** – source-to-bytecode compiler and virtual machine (VM) with compacting garbage collector (GC). This module also contains runtime implementation of standard classes and objects: Array, Object, Function and others.
|
||||
* **script DOM** – runtime classes that expose DOM and DOM view (a.k.a. window) to the script.
|
||||
* **graphics abstraction layer** – abstract graphics implementation that isolates the modules mentioned above from the particular platform details:
|
||||
* Direct2D/DirectWrite graphics backend (Windows);
|
||||
* GDI+ graphics backend (Windows);
|
||||
* CoreGraphics backend (Mac OS X);
|
||||
* Cairo backend (GTK on all Linux platforms);
|
||||
* Skia/OpenGL backend (all platforms)
|
||||
* **core primitives** – set of common primitives: string, arrays, hash maps and so on.
|
||||
|
||||
|
||||
Sciter supports all standard elements defined in HTML5 specification [with some additions](https://sciter.com/developers/for-web-programmers/). CSS is extended to better support the Desktop UI development, e.g. flow and flex units, vertical and horizontal alignment, OS theming.
|
||||
|
||||
[Sciter SDK](https://sciter.com/download/) comes with a demo "browser" with a builtin DOM inspector, script debugger and documentation viewer:
|
||||
|
||||
![Sciter tools](https://sciter.com/wp-content/uploads/2015/10/dom-tree-in-inspector-640x438.png)
|
||||
|
||||
Check <https://sciter.com> website and its [documentation resources](https://sciter.com/developers/) for engine principles, architecture and more.
|
||||
|
||||
|
||||
## Getting started:
|
||||
|
||||
1. Download the [Sciter SDK](https://sciter.com/download/) and extract it somewhere.
|
||||
2. Add the corresponding target platform binaries to PATH (`bin.win`, `bin.osx` or `bin.lnx`).
|
||||
3. If you do not already have it installed, you need GTK 3 development tools installed to continue:
|
||||
sudo apt-get install libgtk-3-dev
|
||||
4. Build the crate and run a minimal sciter sample: `cargo run --example minimal`.
|
||||
5. For your apps add the following dependency to the Cargo.toml: `sciter-rs = "*"`.
|
||||
|
||||
|
||||
## Brief look:
|
||||
|
||||
Here is a minimal sciter app:
|
||||
|
||||
```rust
|
||||
extern crate sciter;
|
||||
|
||||
fn main() {
|
||||
let mut frame = sciter::Window::new();
|
||||
frame.load_file("minimal.htm");
|
||||
frame.run_app();
|
||||
}
|
||||
```
|
||||
|
||||
It looks similar to this:
|
||||
|
||||
![Minimal sciter sample](https://i.imgur.com/ojcM5JJ.png)
|
||||
|
||||
### Interoperability
|
||||
|
||||
In respect of [tiscript](https://www.codeproject.com/Articles/33662/TIScript-language-a-gentle-extension-of-JavaScript) functions calling:
|
||||
```rust
|
||||
use sciter::{Element, Value};
|
||||
|
||||
let root = Element::from_window(hwnd);
|
||||
let result: Value = root.call_function("namespace.name", &make_args!(1,"2",3));
|
||||
```
|
||||
|
||||
Calling Rust from script can be implemented as following:
|
||||
```rust
|
||||
struct Handler;
|
||||
|
||||
impl Handler {
|
||||
fn calc_sum(&self, a: i32, b: i32) -> i32 {
|
||||
a + b
|
||||
}
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for Handler {
|
||||
dispatch_script_call! {
|
||||
fn calc_sum(i32, i32);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And we can access this function from script:
|
||||
```js
|
||||
// `view` represents window where script is runnung.
|
||||
// `stdout` stream is a standard output stream (shell or debugger console, for example)
|
||||
|
||||
stdout.printf("2 + 3 = %d\n", view.calc_sum(2, 3));
|
||||
```
|
||||
|
||||
_Check [rust-sciter/examples](https://github.com/sciter-sdk/rust-sciter/tree/master/examples) folder for more complex usage_.
|
||||
|
||||
|
||||
## [Library documentation](https://docs.rs/sciter-rs/).
|
||||
|
||||
|
||||
## What is supported right now:
|
||||
|
||||
* [x] [sciter::window](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-window.hpp) which brings together window creation, host and event handlers.
|
||||
* [x] [sciter::host](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-host-callback.h) with basic event handling, needs to be redesigned.
|
||||
* [x] [sciter::event_handler](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-behavior.h) with event handling and auto dispatching script calls to native code.
|
||||
* [x] [sciter::dom](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-dom.hpp) for HTML DOM access and manipulation methods.
|
||||
* [x] [sciter::value](https://github.com/c-smile/sciter-sdk/blob/master/include/value.hpp) Rust wrapper.
|
||||
* [x] [sciter::behavior_factory](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-behavior.h) - global factory for native behaviors.
|
||||
* [x] [sciter::graphics](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-graphics.hpp) - platform independent graphics native interface (can be used in native behaviors).
|
||||
* [x] [sciter::request](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-request.hpp) - resource request object, used for custom resource downloading and handling.
|
||||
* [x] [sciter::video](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-video-api.h) - custom video rendering.
|
||||
* [x] [sciter::archive](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-host-callback.h) - Sciter's compressed archive produced by `sdk/bin/packfolder` tool.
|
||||
* [x] [sciter::msg](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-msg.h) - backend-independent input event processing.
|
||||
* [x] [sciter::om](https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-om.h) - Sciter Object Model, extending Sciter by native code.
|
||||
* [x] [NSE](https://sciter.com/include-library-name-native-extensions/) - native Sciter extensions.
|
||||
|
||||
### Platforms:
|
||||
|
||||
* [x] Windows
|
||||
* [x] OSX
|
||||
* [x] Linux
|
||||
* [x] Raspberry Pi
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Bindings library licensed under [MIT license](https://opensource.org/licenses/MIT). Sciter Engine has the [own license terms](https://sciter.com/prices/) and [end used license agreement](https://github.com/c-smile/sciter-sdk/blob/master/license.htm) for SDK usage.
|
11
libs/rust-sciter/build.rs
Normal file
11
libs/rust-sciter/build.rs
Normal file
@ -0,0 +1,11 @@
|
||||
#[cfg(windows)]
|
||||
fn main() {
|
||||
println!("cargo:rustc-link-search=native=./");
|
||||
println!("cargo:rustc-link-lib=static=sciter.static");
|
||||
println!("cargo:rustc-link-lib=comdlg32");
|
||||
println!("cargo:rustc-link-lib=wininet");
|
||||
println!("cargo:rustc-link-lib=windowscodecs");
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn main() {}
|
BIN
libs/rust-sciter/examples/archived.rc
Normal file
BIN
libs/rust-sciter/examples/archived.rc
Normal file
Binary file not shown.
17
libs/rust-sciter/examples/archived.rs
Normal file
17
libs/rust-sciter/examples/archived.rs
Normal file
@ -0,0 +1,17 @@
|
||||
//! Sciter sample with archived resources.
|
||||
|
||||
extern crate sciter;
|
||||
|
||||
fn main() {
|
||||
let resources = include_bytes!("archived.rc");
|
||||
|
||||
let mut frame = sciter::WindowBuilder::main_window()
|
||||
.fixed()
|
||||
.with_size((600, 400))
|
||||
.create();
|
||||
|
||||
frame.archive_handler(resources).expect("Invalid archive");
|
||||
|
||||
frame.load_file("this://app/index.htm");
|
||||
frame.run_app();
|
||||
}
|
162
libs/rust-sciter/examples/clock.htm
Normal file
162
libs/rust-sciter/examples/clock.htm
Normal file
@ -0,0 +1,162 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Clock</title>
|
||||
<style>
|
||||
body { padding: 5dip; }
|
||||
|
||||
#clocks {
|
||||
size: *;
|
||||
flow: horizontal-flow;
|
||||
}
|
||||
|
||||
.city {
|
||||
flow: vertical;
|
||||
size: *;
|
||||
}
|
||||
|
||||
.city > caption {
|
||||
width: *;
|
||||
padding: 5dip;
|
||||
flow:horizontal;
|
||||
horizontal-align: center;
|
||||
font-size: 11pt;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.city > clock, .edit {
|
||||
margin-right: *;
|
||||
margin-left: *;
|
||||
margin-bottom: 5dip;
|
||||
}
|
||||
|
||||
.city > .edit {
|
||||
flow: horizontal;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
clock {
|
||||
behavior: native-clock;
|
||||
display: block;
|
||||
min-width: 150dip;
|
||||
min-height: 150dip;
|
||||
}
|
||||
|
||||
.native-text {
|
||||
behavior: native-text;
|
||||
display: block;
|
||||
min-height: 100dip;
|
||||
min-width: 100dip;
|
||||
outline: 1px solid orange;
|
||||
}
|
||||
|
||||
.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
|
||||
// called from Rust
|
||||
function getLocalTime() {
|
||||
var d = new Date();
|
||||
return [d.hour, d.minute, d.second];
|
||||
}
|
||||
|
||||
function getUtcTime(offset) {
|
||||
var d = new Date();
|
||||
d.UTChour += offset;
|
||||
return [d.UTChour, d.UTCminute, d.UTCsecond];
|
||||
}
|
||||
|
||||
var timeSet = $(#set-time);
|
||||
var timeEdit = $(#edit-time);
|
||||
var timeShow = $(#show-time);
|
||||
|
||||
timeEdit << event change {
|
||||
var now = this.value;
|
||||
var local = [now.hour, now.minute, now.second];
|
||||
stdout.printf("timeEdit: %v %v\n", now, local);
|
||||
timeShow.value = local;
|
||||
}
|
||||
|
||||
timeSet << event click {
|
||||
var now = new Date();
|
||||
var local = [now.hour, now.minute, now.second];
|
||||
stdout.printf("timeSet: %v %v\n", now, local);
|
||||
timeEdit.value = now;
|
||||
timeShow.value = local;
|
||||
}
|
||||
|
||||
function self.ready() {
|
||||
var now = new Date();
|
||||
var local = [now.hour, now.minute, now.second];
|
||||
stdout.printf("initial time: %v %v\n", now, local);
|
||||
timeShow.value = local;
|
||||
}
|
||||
|
||||
// update window icon
|
||||
function setIcon() {
|
||||
var clock = $(clock);
|
||||
|
||||
// get clock element size
|
||||
var (w, h) = clock.box(#dimension, #border);
|
||||
if (w == 0 || h == 0)
|
||||
return;
|
||||
|
||||
// make a snapshot of it with 32x32 size
|
||||
var img = new Image(clock, w, h, 32, 32);
|
||||
var png = img.toBytes();
|
||||
img.destroy();
|
||||
|
||||
// make an icon from the snapshot
|
||||
var icon = Image.fromBytes(png);
|
||||
view.windowIcon = icon;
|
||||
|
||||
return true; // continue to update icon ;)
|
||||
}
|
||||
self.timer(1000, setIcon);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="clocks" some>
|
||||
<div class="city">
|
||||
<caption>London</caption>
|
||||
<clock utc="0" title="UTC+0"></clock>
|
||||
</div>
|
||||
|
||||
<div class="city">
|
||||
<caption>Tokyo</caption>
|
||||
<clock utc="+9" title="UTC+9"></clock>
|
||||
</div>
|
||||
|
||||
<div class="city">
|
||||
<caption>New York</caption>
|
||||
<clock utc="-4" title="UTC-4"></clock>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="local" some>
|
||||
<div class="city">
|
||||
<caption>Frozen time</caption>
|
||||
<clock frozen id="show-time"></clock>
|
||||
<div class="edit">
|
||||
<widget type="time" value="now" id="edit-time" title="Change time of the drawn clock" />
|
||||
<widget type="button" id="set-time" title="Reset back to local time">=</widget>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="city">
|
||||
<caption>Text</caption>
|
||||
<div class="native-text">static text</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
368
libs/rust-sciter/examples/clock.rs
Normal file
368
libs/rust-sciter/examples/clock.rs
Normal file
@ -0,0 +1,368 @@
|
||||
//#![windows_subsystem = "windows"]
|
||||
|
||||
#[macro_use]
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::dom::event::{MethodParams, DRAW_EVENTS, EVENT_GROUPS};
|
||||
use sciter::dom::{Element, HELEMENT};
|
||||
use sciter::graphics::{self, rgb, Graphics, HGFX};
|
||||
use sciter::types::RECT;
|
||||
use sciter::Value;
|
||||
|
||||
// 24:60:60, will be drawn as analog clock
|
||||
type Time = [u8; 3usize];
|
||||
|
||||
/// Clock native behavior.
|
||||
///
|
||||
/// ## Behavior-specific HTML attributes:
|
||||
///
|
||||
/// * `utc="integer"` - time zone offset, positive or negative.
|
||||
/// * `frozen` - time is not updated automtically.
|
||||
///
|
||||
/// ## Value
|
||||
///
|
||||
/// *read/write* Current time value in `HH::MM::SS` or `[HH, MM, SS]` form.
|
||||
///
|
||||
/// ## Events
|
||||
///
|
||||
/// N/A - this element does not generate any specific events.
|
||||
///
|
||||
#[derive(Default)]
|
||||
struct Clock {
|
||||
element: Option<Element>,
|
||||
now: Time,
|
||||
gmt: i8,
|
||||
is_frozen: bool,
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for Clock {
|
||||
/// Claim what kind of events we want to receive.
|
||||
fn get_subscription(&mut self) -> Option<EVENT_GROUPS> {
|
||||
// we need timer and draw events
|
||||
// also behavior method calls
|
||||
Some(EVENT_GROUPS::HANDLE_TIMER
|
||||
| EVENT_GROUPS::HANDLE_DRAW
|
||||
| EVENT_GROUPS::HANDLE_METHOD_CALL
|
||||
)
|
||||
}
|
||||
|
||||
/// Our element is constructed. But scripts in HTML are not loaded yet.
|
||||
fn attached(&mut self, root: HELEMENT) {
|
||||
self.element = Some(Element::from(root));
|
||||
let me = self.element.as_ref().unwrap();
|
||||
|
||||
// get attributes to initialize our clock
|
||||
if let Some(attr) = me.get_attribute("utc") {
|
||||
if let Ok(v) = attr.parse::<i8>() {
|
||||
self.gmt = v;
|
||||
}
|
||||
}
|
||||
|
||||
// we don't update frozen clocks
|
||||
if let Some(_attr) = me.get_attribute("frozen") {
|
||||
self.is_frozen = true;
|
||||
}
|
||||
|
||||
// timer to redraw our clock
|
||||
if !self.is_frozen {
|
||||
me.start_timer(300, 1).expect("Can't set timer");
|
||||
}
|
||||
}
|
||||
|
||||
/// Our behavior methods.
|
||||
fn on_method_call(&mut self, _root: HELEMENT, params: MethodParams) -> bool {
|
||||
match params {
|
||||
MethodParams::GetValue(retval) => {
|
||||
// engine wants out current value (e.g. `current = element.value`)
|
||||
let v: Value = self.now.iter().map(|v| i32::from(*v)).collect();
|
||||
println!("return current time as {:?}", v);
|
||||
*retval = v;
|
||||
}
|
||||
|
||||
MethodParams::SetValue(v) => {
|
||||
// engine sets our value (e.g. `element.value = new`)
|
||||
println!("set current time from {:?}", v);
|
||||
|
||||
// "10:20:30"
|
||||
if v.is_string() {
|
||||
let s = v.as_string().unwrap();
|
||||
let t = s.split(':').take(3).map(|n| n.parse::<u8>());
|
||||
let mut new_time = Time::default();
|
||||
for (i, n) in t.enumerate() {
|
||||
if let Err(_) = n {
|
||||
eprintln!("clock::set_value({:?}) is invalid", v);
|
||||
return true; // consume this event anyway
|
||||
}
|
||||
new_time[i] = n.unwrap();
|
||||
}
|
||||
// use it as a new time
|
||||
self.set_time(new_time);
|
||||
|
||||
// [10, 20, 30]
|
||||
} else if v.is_varray() {
|
||||
let mut new_time = Time::default();
|
||||
for (i, n) in v.values().take(3).map(|n| n.to_int()).enumerate() {
|
||||
if n.is_none() {
|
||||
eprintln!("clock::set_value({:?}) is invalid", v);
|
||||
return true;
|
||||
}
|
||||
new_time[i] = n.unwrap() as u8
|
||||
}
|
||||
// use it as a new time
|
||||
self.set_time(new_time);
|
||||
} else {
|
||||
// unknown format
|
||||
eprintln!("clock::set_value({:?}) is unsupported", v);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
// unsupported event, skip it
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// mark this event as handled (consume it)
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Redraw our element on each tick.
|
||||
fn on_timer(&mut self, root: HELEMENT, _timer_id: u64) -> bool {
|
||||
if self.update_time() {
|
||||
// redraw our clock
|
||||
Element::from(root).refresh().expect("Can't refresh element");
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Request to draw our element.
|
||||
fn on_draw(&mut self, _root: HELEMENT, gfx: HGFX, area: &RECT, layer: DRAW_EVENTS) -> bool {
|
||||
if layer == DRAW_EVENTS::DRAW_CONTENT {
|
||||
// draw content only
|
||||
// leave the back- and foreground to be default
|
||||
let mut gfx = Graphics::from(gfx);
|
||||
self
|
||||
.draw_clock(&mut gfx, &area)
|
||||
.map_err(|e| println!("error in draw_clock: {:?}", e) )
|
||||
.ok();
|
||||
}
|
||||
|
||||
// allow default drawing anyway
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 360°
|
||||
const PI2: f32 = 2.0 * std::f32::consts::PI;
|
||||
|
||||
impl Clock {
|
||||
/// Update current time and say if changed.
|
||||
fn update_time(&mut self) -> bool {
|
||||
if self.is_frozen {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ask our script for the current time
|
||||
if let Some(now) = self.get_time() {
|
||||
let update = self.now != now;
|
||||
self.now = now;
|
||||
update
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the new time and redraw our element.
|
||||
fn set_time(&mut self, new_time: Time) {
|
||||
// set new time and redraw our clock
|
||||
self.now = new_time;
|
||||
if let Some(el) = self.element.as_ref() {
|
||||
el.refresh().ok();
|
||||
}
|
||||
}
|
||||
|
||||
/// Get current time from script.
|
||||
fn get_time(&self) -> Option<Time> {
|
||||
let el = self.element.as_ref().unwrap();
|
||||
let script_func = if self.is_frozen { "getLocalTime" } else { "getUtcTime" };
|
||||
if let Ok(time) = el.call_function(script_func, &make_args!(self.gmt as i32)) {
|
||||
assert_eq!(time.len(), 3);
|
||||
let mut now = Time::default();
|
||||
for (i, n) in time.values().take(3).map(|n| n.to_int()).enumerate() {
|
||||
now[i] = n.unwrap() as u8;
|
||||
}
|
||||
Some(now)
|
||||
} else {
|
||||
eprintln!("error: can't eval get time script");
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw our element.
|
||||
fn draw_clock(&mut self, gfx: &mut Graphics, area: &RECT) -> graphics::Result<()> {
|
||||
// save previous state
|
||||
let mut gfx = gfx.save_state()?;
|
||||
|
||||
// setup our attributes
|
||||
let left = area.left as f32;
|
||||
let top = area.top as f32;
|
||||
let width = area.width() as f32;
|
||||
let height = area.height() as f32;
|
||||
|
||||
let scale = if width < height { width / 300.0 } else { height / 300.0 };
|
||||
|
||||
// translate to its center and rotate 45° left.
|
||||
gfx
|
||||
.translate((left + width / 2.0, top + height / 2.0))?
|
||||
.scale((scale, scale))?
|
||||
.rotate(-PI2 / 4.)?;
|
||||
|
||||
gfx.line_color(0)?.line_cap(graphics::LINE_CAP::ROUND)?;
|
||||
|
||||
// draw clock background
|
||||
self.draw_outline(&mut *gfx)?;
|
||||
|
||||
// draw clock sticks
|
||||
self.draw_time(&mut *gfx)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Draw clock static area (hour/minute marks).
|
||||
fn draw_outline(&mut self, gfx: &mut Graphics) -> graphics::Result<()> {
|
||||
// hour marks (every 5 ticks)
|
||||
{
|
||||
let mut gfx = gfx.save_state()?;
|
||||
gfx.line_width(8.0)?.line_color(rgb(0x32, 0x5F, 0xA2))?;
|
||||
|
||||
for _ in 0..12 {
|
||||
gfx.rotate(PI2 / 12.)?.line((137., 0.), (144., 0.))?;
|
||||
}
|
||||
}
|
||||
|
||||
// minute marks (every but 5th tick)
|
||||
{
|
||||
let mut gfx = gfx.save_state()?;
|
||||
gfx.line_width(3.0)?.line_color(rgb(0xA5, 0x2A, 0x2A))?;
|
||||
|
||||
for i in 0..60 {
|
||||
if i % 5 != 0 {
|
||||
// skip hours
|
||||
gfx.line((143., 0.), (146., 0.))?;
|
||||
}
|
||||
gfx.rotate(PI2 / 60.)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Draw clock arrows.
|
||||
fn draw_time(&mut self, gfx: &mut Graphics) -> graphics::Result<()> {
|
||||
let time = &self.now;
|
||||
let hours = f32::from(time[0]);
|
||||
let minutes = f32::from(time[1]);
|
||||
let seconds = f32::from(time[2]);
|
||||
|
||||
{
|
||||
// hours
|
||||
let mut gfx = gfx.save_state()?;
|
||||
|
||||
// 2PI*/12, 2PI/720,
|
||||
gfx.rotate(hours * (PI2 / 12 as f32) + minutes * (PI2 / (12 * 60) as f32) + seconds * (PI2 / (12 * 60 * 60) as f32))?;
|
||||
|
||||
gfx
|
||||
.line_width(14.0)?
|
||||
.line_color(rgb(0x32, 0x5F, 0xA2))?
|
||||
.line((-20., 0.), (70., 0.))?;
|
||||
}
|
||||
{
|
||||
// minutes
|
||||
let mut gfx = gfx.save_state()?;
|
||||
|
||||
gfx.rotate(minutes * (PI2 / 60 as f32) + seconds * (PI2 / (60 * 60) as f32))?;
|
||||
|
||||
gfx
|
||||
.line_width(10.0)?
|
||||
.line_color(rgb(0x32, 0x5F, 0xA2))?
|
||||
.line((-28., 0.), (100., 0.))?;
|
||||
}
|
||||
{
|
||||
// seconds
|
||||
let mut gfx = gfx.save_state()?;
|
||||
|
||||
gfx.rotate(seconds * (PI2 / 60 as f32))?;
|
||||
|
||||
gfx
|
||||
.line_width(6.0)?
|
||||
.line_color(rgb(0xD4, 0, 0))?
|
||||
.fill_color(rgb(0xD4, 0, 0))?
|
||||
.line((-30., 0.), (83., 0.))?
|
||||
.circle((0., 0.), 10.)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////
|
||||
#[derive(Default)]
|
||||
struct Text;
|
||||
|
||||
impl sciter::EventHandler for Text {
|
||||
fn get_subscription(&mut self) -> Option<EVENT_GROUPS> {
|
||||
Some(EVENT_GROUPS::HANDLE_DRAW)
|
||||
}
|
||||
|
||||
fn attached(&mut self, _root: HELEMENT) {
|
||||
}
|
||||
|
||||
fn on_draw(&mut self, _root: HELEMENT, gfx: HGFX, area: &RECT, layer: DRAW_EVENTS) -> bool {
|
||||
if layer == DRAW_EVENTS::DRAW_CONTENT {
|
||||
// draw content only
|
||||
// leave the back- and foreground to be default
|
||||
let mut gfx = Graphics::from(gfx);
|
||||
let e = Element::from(_root);
|
||||
self
|
||||
.draw_text(&e, &mut gfx, &area)
|
||||
.map_err(|e| println!("error in draw_clock: {:?}", e) )
|
||||
.ok();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// allow default drawing anyway
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
impl Text {
|
||||
fn draw_text(&mut self, e: &Element, gfx: &mut Graphics, area: &RECT) -> graphics::Result<()> {
|
||||
|
||||
// save previous state
|
||||
let mut gfx = gfx.save_state()?;
|
||||
|
||||
// setup our attributes
|
||||
// let left = area.left as f32;
|
||||
// let top = area.top as f32;
|
||||
// let width = area.width() as f32;
|
||||
// let height = area.height() as f32;
|
||||
|
||||
// println!("text::draw on {} at {} {} {} {}", e, left, top, width, height);
|
||||
|
||||
use sciter::graphics::Text;
|
||||
|
||||
let t = Text::with_style(&e, "native text", "font-style: italic")?;
|
||||
gfx.draw_text(&t, (area.left as f32, area.top as f32), 7)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut frame = sciter::WindowBuilder::main_window().with_size((800, 600)).create();
|
||||
frame.register_behavior("native-clock", || Box::new(Clock::default()));
|
||||
frame.register_behavior("native-text", || Box::new(Text::default()));
|
||||
frame.load_html(include_bytes!("clock.htm"), Some("example://clock.htm"));
|
||||
frame.run_app();
|
||||
}
|
272
libs/rust-sciter/examples/dom.rs
Normal file
272
libs/rust-sciter/examples/dom.rs
Normal file
@ -0,0 +1,272 @@
|
||||
#![allow(unused_variables)]
|
||||
#![allow(unused_must_use)]
|
||||
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::{Value, Element, HELEMENT};
|
||||
use sciter::dom::event::*;
|
||||
|
||||
|
||||
|
||||
#[derive(Default)]
|
||||
struct DocumentHandler;
|
||||
|
||||
impl sciter::EventHandler for DocumentHandler {
|
||||
|
||||
fn attached(&mut self, _root: sciter::HELEMENT) {
|
||||
println!("attached");
|
||||
}
|
||||
|
||||
fn detached(&mut self, root: sciter::HELEMENT) {
|
||||
let root = Element::from(root);
|
||||
println!("detaching from {}", root);
|
||||
}
|
||||
|
||||
fn document_complete(&mut self, root: sciter::HELEMENT, source: sciter::HELEMENT) {
|
||||
|
||||
println!("document is loaded.");
|
||||
|
||||
let root = Element::from(root);
|
||||
assert_eq!(root.get_tag(), "html");
|
||||
println!("root {:?}", root);
|
||||
|
||||
let head = root.first_child().expect("empty <html>?");
|
||||
assert_eq!(head.get_tag(), "head");
|
||||
assert_eq!(head.index(), 0);
|
||||
println!("head {:?}", head);
|
||||
|
||||
let body = head.next_sibling().expect("only <head>?");
|
||||
assert_eq!(body.get_tag(), "body");
|
||||
assert_eq!(body.index(), 1);
|
||||
println!("body {:?}", body);
|
||||
|
||||
assert_eq!(body.first_sibling().expect("must be head"), head);
|
||||
assert_eq!(body.last_sibling().expect("must be body"), body);
|
||||
|
||||
println!("for loop in children");
|
||||
for e in root.children() {
|
||||
println!("child {:?}", e);
|
||||
}
|
||||
|
||||
println!("for loop in ref");
|
||||
for e in &root {
|
||||
println!("child {:?}", e);
|
||||
}
|
||||
|
||||
if let Ok(Some(h1)) = body.find_first("body > h1") {
|
||||
println!("h1 {:?}", h1);
|
||||
|
||||
let h1_parent = h1.parent().expect("come on!");
|
||||
assert_eq!(h1_parent, body);
|
||||
|
||||
let text = h1.get_text();
|
||||
assert_eq!(text, "Herman Melville - Moby-Dick");
|
||||
|
||||
let html = h1.get_html(true);
|
||||
assert_eq!(html.as_slice(), br"<h1>Herman Melville - Moby-Dick</h1>".as_ref());
|
||||
|
||||
let value = h1.get_value();
|
||||
assert!(value.is_string());
|
||||
assert_eq!(value.as_string().unwrap(), text);
|
||||
}
|
||||
|
||||
if let Some(mut h1) = body.first_child() {
|
||||
println!("changing h1 attributes");
|
||||
h1.set_style_attribute("color", "green");
|
||||
h1.set_style_attribute("outline", "1px solid orange");
|
||||
h1.set_attribute("title", "yellow!");
|
||||
}
|
||||
|
||||
{
|
||||
let all: Vec<Element> = body.find_all("div > p").unwrap().expect("must be at least one 'div > p'");
|
||||
assert!(!all.is_empty());
|
||||
assert_eq!(all.len(), 1);
|
||||
all.len();
|
||||
}
|
||||
|
||||
if let Ok(Some(mut body)) = root.find_first("html > body") {
|
||||
let mut div = Element::with_parent("div", &mut body).unwrap();
|
||||
div.set_attribute("id", "requests");
|
||||
div.set_style_attribute("outline", "1px solid orange");
|
||||
div.set_style_attribute("margin", "10dip 0");
|
||||
div.set_style_attribute("padding", "4dip");
|
||||
|
||||
let e = Element::with_text("label", "Requests:").unwrap();
|
||||
div.append(&e).unwrap();
|
||||
|
||||
let d = Element::with_text("div", "data").unwrap();
|
||||
div.append(&d).unwrap();
|
||||
|
||||
let c = Element::with_text("div", "footer").unwrap();
|
||||
div.append(&c).unwrap();
|
||||
|
||||
d.request_html("https://sciter.com/test/text.txt", None).unwrap();
|
||||
|
||||
// d.send_get_request("https://sciter.com/test/text.txt", None).expect("can't send an http request");
|
||||
// d.send_get_request("http://httpbin.org/html", None).expect("can't send an http request");
|
||||
// d.send_get_request("http://httpbin.org/get?one=1&two=2", None).expect("can't send an http request");
|
||||
|
||||
// let params = [("one", "1"), ("two", "2")];
|
||||
// let method = sciter::request::REQUEST_TYPE::AsyncGet;
|
||||
// let data_type = sciter::request::RESOURCE_TYPE::HTML;
|
||||
// d.send_request("http://httpbin.org/html", Some(¶ms), Some(method), Some(data_type)).expect("can't send an http request");
|
||||
}
|
||||
|
||||
if let Ok(Some(mut body)) = root.find_first("html > body") {
|
||||
|
||||
println!("creating some elments");
|
||||
|
||||
// DOM manipulation.
|
||||
// After creating the new Element, we can set only attributes for it until we'll attach it to the DOM.
|
||||
//
|
||||
let mut div = Element::with_parent("div", &mut body).unwrap();
|
||||
div.set_style_attribute("outline", "1px solid orange");
|
||||
div.set_style_attribute("width", "max-content");
|
||||
div.set_style_attribute("padding", "5dip");
|
||||
|
||||
let mut lb = Element::with_text("label", "Output: ").unwrap();
|
||||
div.append(&lb).expect("wtf?"); // push as reference, we can access this `lb` still.
|
||||
|
||||
let mut date = Element::with_type("input", "date").unwrap();
|
||||
date.set_attribute("id", "mydate");
|
||||
date.set_attribute("value", "now");
|
||||
|
||||
lb.append(&date).expect("wtf?");
|
||||
|
||||
date.set_style_attribute("width", "100px");
|
||||
date.set_style_attribute("outline", "1px dotted gray");
|
||||
date.set_style_attribute("margin", "10px");
|
||||
|
||||
|
||||
lb.set_attribute("accesskey", "o");
|
||||
lb.set_style_attribute("color", "lightblue");
|
||||
lb.set_style_attribute("vertical-align", "middle");
|
||||
|
||||
let mut progress = Element::create("progress").unwrap();
|
||||
progress.set_attribute("max", "100");
|
||||
progress.set_attribute("id", "id1");
|
||||
progress.set_attribute("title", "Click to start timer.");
|
||||
|
||||
div.append(&progress).expect("wtf?");
|
||||
|
||||
// after attaching Element to DOM, we can set its styles, text, html or value.
|
||||
progress.set_value(Value::from(42));
|
||||
progress.set_style_attribute("behavior", "progress clickable");
|
||||
|
||||
// attach a new handler to this element;
|
||||
// since timers are not sinking/bubbling, we need to attach
|
||||
// a dedicated handler to that element directly.
|
||||
let handler = ProgressHandler::default();
|
||||
progress.attach_handler(handler).expect("can't attach?");
|
||||
|
||||
let mut e = Element::with_text("span", " <-- check tooltip").unwrap();
|
||||
div.append(&e);
|
||||
|
||||
e.set_style_attribute("font-style", "italic");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ProgressHandler {
|
||||
progress: Option<Element>,
|
||||
start_timer: bool,
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for ProgressHandler {
|
||||
|
||||
fn get_subscription(&mut self) -> Option<EVENT_GROUPS> {
|
||||
Some(default_events() | EVENT_GROUPS::HANDLE_TIMER)
|
||||
}
|
||||
|
||||
fn attached(&mut self, root: sciter::HELEMENT) {
|
||||
let root = Element::from(root);
|
||||
println!("attached an element event handler to {}", root);
|
||||
if root.test("progress") {
|
||||
self.progress = Some(root.clone());
|
||||
self.start_timer = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn detached(&mut self, root: sciter::HELEMENT) {
|
||||
let root = Element::from(root);
|
||||
println!("detaching from {}", root);
|
||||
}
|
||||
|
||||
fn on_event(&mut self, root: HELEMENT, source: HELEMENT, target: HELEMENT, code: BEHAVIOR_EVENTS, phase: PHASE_MASK, reason: EventReason) -> bool {
|
||||
if phase != PHASE_MASK::BUBBLING {
|
||||
return false;
|
||||
}
|
||||
|
||||
match code {
|
||||
BEHAVIOR_EVENTS::BUTTON_CLICK => {
|
||||
|
||||
let source = Element::from(source);
|
||||
let mut target = Element::from(target);
|
||||
|
||||
println!("button click on target {}", target);
|
||||
|
||||
if self.progress.is_some() && *self.progress.as_ref().unwrap() == target {
|
||||
self.start_timer = !self.start_timer;
|
||||
|
||||
if self.start_timer {
|
||||
println!("starting timer");
|
||||
target.set_value(Value::from(0));
|
||||
target.start_timer(1000, 1).ok();
|
||||
} else {
|
||||
println!("stopping timer");
|
||||
target.stop_timer(1);
|
||||
|
||||
let cur = target.get_value();
|
||||
target.set_attribute("title", &format!("Current value is {}. Click to start the timer again.", cur));
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn on_timer(&mut self, root: HELEMENT, timer_id: u64) -> bool {
|
||||
println!("timer {} tick on {}", timer_id, Element::from(root));
|
||||
if timer_id == 1 && self.progress.is_some() {
|
||||
let e = self.progress.as_mut().unwrap();
|
||||
let max_attr = e.get_attribute("max").unwrap();
|
||||
let max: f64 = max_attr.parse().unwrap();
|
||||
|
||||
let v = e.get_value();
|
||||
let next = v.to_float().unwrap() + 5.0;
|
||||
|
||||
if next > max {
|
||||
println!("that's enough, finish.");
|
||||
self.start_timer = false;
|
||||
e.stop_timer(1);
|
||||
}
|
||||
|
||||
e.set_value(Value::from(next));
|
||||
e.set_attribute("title", &format!("Current value is {}. Click to stop the timer if need.", next));
|
||||
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut frame = sciter::WindowBuilder::main_window()
|
||||
.with_size((750, 950))
|
||||
.debug()
|
||||
.create();
|
||||
|
||||
println!("attaching an event handler for the whole window");
|
||||
frame.event_handler(DocumentHandler::default());
|
||||
frame.set_title("DOM sample");
|
||||
|
||||
println!("loading the page...");
|
||||
frame.load_file("http://httpbin.org/html");
|
||||
|
||||
println!("running the app");
|
||||
frame.run_app();
|
||||
}
|
69
libs/rust-sciter/examples/download.rs
Normal file
69
libs/rust-sciter/examples/download.rs
Normal file
@ -0,0 +1,69 @@
|
||||
//! Download http content (Go sciter example port).
|
||||
#![allow(dead_code)]
|
||||
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::dom::HELEMENT;
|
||||
use sciter::host;
|
||||
use sciter::utf;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
||||
struct Handler {
|
||||
host: Weak<sciter::Host>,
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for Handler {
|
||||
fn document_complete(&mut self, _root: HELEMENT, _target: HELEMENT) {
|
||||
if let Some(host) = self.host.upgrade() {
|
||||
// eval script inside the document to receive a "user@machine" string.
|
||||
let result = host.eval_script("[Sciter.userName(), Sciter.machineName(true)].join(`@`)");
|
||||
match result {
|
||||
Ok(name) => {
|
||||
println!("running on {}", name);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("error! {}", e.as_string().unwrap_or("?".to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sciter::HostHandler for Handler {
|
||||
fn on_data_loaded(&mut self, pnm: &host::SCN_DATA_LOADED) {
|
||||
println!("data loaded, uri: `{}`, {} bytes.", utf::w2s(pnm.uri), pnm.dataSize);
|
||||
}
|
||||
|
||||
fn on_attach_behavior(&mut self, pnm: &mut host::SCN_ATTACH_BEHAVIOR) -> bool {
|
||||
let el = sciter::Element::from(pnm.element);
|
||||
let name = utf::u2s(pnm.name);
|
||||
println!("{}: behavior {}", el, name);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Handler {
|
||||
fn drop(&mut self) {
|
||||
// called 2 times because it is created 2 times
|
||||
println!("Good bye, window");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut frame = sciter::WindowBuilder::main_window().with_size((1024, 768)).create();
|
||||
|
||||
// Can't use something like `frame.sciter_handler(Rc::new(handler))` yet.
|
||||
let handler = Handler {
|
||||
host: Rc::downgrade(&frame.get_host()),
|
||||
};
|
||||
frame.sciter_handler(handler);
|
||||
|
||||
let handler = Handler {
|
||||
host: Rc::downgrade(&frame.get_host()),
|
||||
};
|
||||
frame.event_handler(handler);
|
||||
|
||||
frame.set_title("Download sample");
|
||||
frame.load_file("http://httpbin.org/html");
|
||||
frame.run_app();
|
||||
}
|
18
libs/rust-sciter/examples/extension.htm
Normal file
18
libs/rust-sciter/examples/extension.htm
Normal file
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>extension test</title>
|
||||
<style type="text/css">
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
// copy "extension.dll" next to the "sciter.dll"
|
||||
const ext = include library "extension";
|
||||
debug: ext;
|
||||
debug: ext.add(1,2);
|
||||
debug: ext.sub(1,2);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h4>see logs in Inspector</h4>
|
||||
</body>
|
||||
</html>
|
17
libs/rust-sciter/examples/extension/Cargo.toml
Normal file
17
libs/rust-sciter/examples/extension/Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "extension"
|
||||
version = "0.1.0"
|
||||
description = "A simple Sciter extension library"
|
||||
authors = ["pravic <ehysta@gmail.com>"]
|
||||
homepage = "https://sciter.com/include-library-name-native-extensions/"
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
path = "src/extension.rs"
|
||||
crate-type = ["cdylib"]
|
||||
test = false
|
||||
bench = false
|
||||
|
||||
[dependencies]
|
||||
sciter-rs = { version = "0.5", path="../../", features = ["extension"] }
|
50
libs/rust-sciter/examples/extension/src/extension.rs
Normal file
50
libs/rust-sciter/examples/extension/src/extension.rs
Normal file
@ -0,0 +1,50 @@
|
||||
//! Sciter extension library example.
|
||||
//!
|
||||
//! See the [blog post](https://sciter.com/include-library-name-native-extensions/).
|
||||
|
||||
#[macro_use]
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::types::{BOOL, VALUE};
|
||||
use sciter::Value;
|
||||
|
||||
/// Extension entry point.
|
||||
#[no_mangle]
|
||||
pub extern "system" fn SciterLibraryInit(api: &'static sciter::ISciterAPI, exported: &mut VALUE) -> BOOL {
|
||||
sciter::set_host_api(api);
|
||||
|
||||
let ext_api = vmap! {
|
||||
"add" => add,
|
||||
"sub" => sub,
|
||||
};
|
||||
|
||||
ext_api.pack_to(exported);
|
||||
|
||||
true as BOOL
|
||||
}
|
||||
|
||||
/// Calculate the sum of all the given arguments.
|
||||
pub fn add(args: &[Value]) -> Value {
|
||||
let sum: i32 = args
|
||||
.iter()
|
||||
.map(|v| v.to_int())
|
||||
.filter(|v| v.is_some())
|
||||
.map(|v| v.unwrap())
|
||||
.sum();
|
||||
|
||||
sum.into()
|
||||
}
|
||||
|
||||
/// `function sub(a, b) { return a - b; }`
|
||||
pub fn sub(args: &[Value]) -> std::result::Result<Value, String> {
|
||||
if let [a, b] = args {
|
||||
let a = a.to_int().ok_or("`a` is not an int")?;
|
||||
let b = b.to_int().ok_or("`b` is not an int")?;
|
||||
|
||||
let result = a - b;
|
||||
|
||||
Ok(result.into())
|
||||
} else {
|
||||
Err(format!("sub(a,b) expects 2 parameters, given {} instead.", args.len()))
|
||||
}
|
||||
}
|
50
libs/rust-sciter/examples/fire_event.htm
Normal file
50
libs/rust-sciter/examples/fire_event.htm
Normal file
@ -0,0 +1,50 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Fire event demo</title>
|
||||
<style>
|
||||
|
||||
html {
|
||||
background: radial-gradient(75% 75%, circle farthest-side, white, orange, rgb(0, 0, 204));
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#message {
|
||||
margin: 10dip 0dip;
|
||||
padding: 5dip;
|
||||
width: 60%%;
|
||||
min-height: 60dip;
|
||||
|
||||
color: black;
|
||||
background: #ccc;
|
||||
outline: 1px solid orange;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
view.caption = $(head > title).value;
|
||||
|
||||
$(#machine).text = Sciter.machineName();
|
||||
|
||||
$(#post).on("click", : {
|
||||
$(#message).postEvent(Event.CHANGE, 0, this, "hello?");
|
||||
});
|
||||
|
||||
$(#message).on("change", function(e) {
|
||||
this.text = String.printf("Event from `%s`: %v\n", e.source.id, e.data);
|
||||
});
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Fire event</h1>
|
||||
<p>Running on <em #machine/> machine</p>
|
||||
|
||||
<button id="post">Post event</button>
|
||||
<button id="send">Send event</button>
|
||||
<button id="fire">Fire event</button>
|
||||
|
||||
<div id="message"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
60
libs/rust-sciter/examples/fire_event.rs
Normal file
60
libs/rust-sciter/examples/fire_event.rs
Normal file
@ -0,0 +1,60 @@
|
||||
//! Fire event Sciter sample.
|
||||
#![allow(unused_variables)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::Element;
|
||||
use self::sciter::dom::event::*;
|
||||
use self::sciter::dom::HELEMENT;
|
||||
use self::sciter::value::Value;
|
||||
|
||||
struct FireEvent;
|
||||
|
||||
impl sciter::EventHandler for FireEvent {
|
||||
|
||||
fn on_event(&mut self, root: HELEMENT, source: HELEMENT, target: HELEMENT, code: BEHAVIOR_EVENTS, phase: PHASE_MASK, reason: EventReason) -> bool {
|
||||
if phase != PHASE_MASK::BUBBLING {
|
||||
return false;
|
||||
}
|
||||
|
||||
if code == BEHAVIOR_EVENTS::BUTTON_CLICK {
|
||||
|
||||
// `root` points to attached element, usually it is an `<html>`.
|
||||
|
||||
let root = Element::from(root).root();
|
||||
|
||||
let message = root.find_first("#message").unwrap().expect("div#message not found");
|
||||
let source = Element::from(source);
|
||||
|
||||
println!("our root is {:?}, message is {:?} and source is {:?}", root, message, source);
|
||||
|
||||
if let Some(id) = source.get_attribute("id") {
|
||||
if id == "send" {
|
||||
|
||||
// just send a simple event
|
||||
source.send_event(BEHAVIOR_EVENTS::CHANGE, None, Some(message.as_ptr())).expect("Failed to send event");
|
||||
return true;
|
||||
|
||||
} else if id == "fire" {
|
||||
|
||||
// fire event with specified params
|
||||
let data = Value::from("Rusty param");
|
||||
|
||||
source.fire_event(BEHAVIOR_EVENTS::CHANGE, None, Some(message.as_ptr()), false, Some(data)).expect("Failed to fire event");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let html = include_bytes!("fire_event.htm");
|
||||
let mut frame = sciter::Window::new();
|
||||
frame.event_handler(FireEvent);
|
||||
frame.load_html(html, Some("example://fire_event.htm"));
|
||||
frame.run_app();
|
||||
}
|
35
libs/rust-sciter/examples/first.rs
Normal file
35
libs/rust-sciter/examples/first.rs
Normal file
@ -0,0 +1,35 @@
|
||||
//! An example showing various information about Sciter.
|
||||
|
||||
extern crate sciter;
|
||||
|
||||
fn main() {
|
||||
// can be called as `examples/first ~/lib/libsciter.so`
|
||||
if cfg!(feature = "dynamic") {
|
||||
if let Some(arg) = std::env::args().nth(1) {
|
||||
println!("using {:?}", arg);
|
||||
if let Err(e) = sciter::set_library(&arg) {
|
||||
panic!("Invalid library path specified: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let arch = if cfg!(target_arch = "x86_64") { "x64" } else { "x86" };
|
||||
println!("calling SciterAPI {}", arch);
|
||||
|
||||
// bypass the ABI compatability checks (e.g. in windowless builds)
|
||||
let scapi = sciter::SciterAPI_unchecked();
|
||||
|
||||
let abi_version = scapi.version;
|
||||
println!("sciter abi version: {:#0x}, windowless: {}", abi_version, abi_version >= 0x0001_0001);
|
||||
|
||||
let class_name = sciter::utf::w2s((scapi.SciterClassName)());
|
||||
println!("sciter class name: {:?}", class_name);
|
||||
|
||||
// Sciter library version
|
||||
use sciter::types::BOOL;
|
||||
let v1 = (scapi.SciterVersion)(true as BOOL);
|
||||
let v2 = (scapi.SciterVersion)(false as BOOL);
|
||||
let num = [v1 >> 16, v1 & 0xFFFF, v2 >> 16, v2 & 0xFFFF];
|
||||
let version = num.iter().map(|&x| x.to_string()).collect::<Vec<_>>().join(".");
|
||||
println!("sciter version: {} {:?}", version, num);
|
||||
}
|
BIN
libs/rust-sciter/examples/icon.png
Normal file
BIN
libs/rust-sciter/examples/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
90
libs/rust-sciter/examples/interop.htm
Normal file
90
libs/rust-sciter/examples/interop.htm
Normal file
@ -0,0 +1,90 @@
|
||||
<html window-icon="https://sciter.com/wp-content/themes/sciter/!images/favicon.ico">
|
||||
<head>
|
||||
<title>Rust-sciter sample</title>
|
||||
<style>
|
||||
|
||||
html {
|
||||
background: radial-gradient(75% 75%, circle farthest-side, white, orange, rgb(0,0,204));
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
html:rtl {
|
||||
mapping: left-to-right(background);
|
||||
}
|
||||
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
|
||||
view.caption = $(head > title).value;
|
||||
|
||||
$(#machine).text = Sciter.machineName();
|
||||
$(#backend).text = view.backendName;
|
||||
$(#version).text = String.printf("%d.%d.%d.%d",
|
||||
(Sciter.VERSION >> 16) & 0xffff, Sciter.VERSION & 0xffff,
|
||||
(Sciter.REVISION >> 16) & 0xffff, Sciter.REVISION & 0xffff);
|
||||
|
||||
var counter = 0;
|
||||
$(button#append).on("click", function() {
|
||||
$(body).$append(<h1#test>{ ++counter }</h1>);
|
||||
});
|
||||
|
||||
$(button#open).on("click", function() {
|
||||
|
||||
var fn = view.selectFile(#open,
|
||||
"HTML Files (*.htm,*.html)|*.HTM;*.HTML|All Files (*.*)|*.*" , "html" );
|
||||
|
||||
stdout.println("selected file: " + fn);
|
||||
|
||||
if (fn) {
|
||||
$(body).$append(<h1#test>{fn}</h1>);
|
||||
}
|
||||
});
|
||||
|
||||
$(button#ti2py).on("click", function() {
|
||||
var answer = view.NativeCall(view.caption);
|
||||
$(body).$append(<h1#test>script -> native: {answer}</h1>);
|
||||
})
|
||||
|
||||
$(button#py2ti).on("click", function() {
|
||||
var answer = view.ScriptCallTest("call arg");
|
||||
})
|
||||
|
||||
$(button#sum).on("click", function() {
|
||||
stdout.printf("2 + 3 = %d\n", view.calc_sum(2, 3));
|
||||
})
|
||||
|
||||
function hello(who) {
|
||||
$(body).$append(<h1#test>native -> script: {who}</h1>);
|
||||
return "its working!";
|
||||
}
|
||||
|
||||
function raise_error(arg1, arg2, arg3) {
|
||||
throw new Error(String.$(Unexpected type of input: {typeof arg1}, {typeof arg2}, {typeof arg3}.));
|
||||
}
|
||||
|
||||
self.timer(2000, function() {
|
||||
|
||||
if(!view.api)
|
||||
view.api = view.GetNativeApi();
|
||||
// {add: function(a,b) { return a + b; }};
|
||||
|
||||
stdout.printf("2 + 3 = %d\n", view.api.add(2, 3));
|
||||
stdout.printf("2 * 3 = %d\n", view.api.mul(2, 3));
|
||||
stdout.printf("2 - 3 = %d\n", view.api.sub(2, 3));
|
||||
});
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Rust Sciter Application</h1>
|
||||
<p>Running on <strong #machine /> machine via <strong #backend/> (<strong #version/>).</p>
|
||||
|
||||
<button #append>Append</button>
|
||||
<button #open>Open</button>
|
||||
<button #ti2py>Call native</button>
|
||||
<button #py2ti>Call script</button>
|
||||
<button #sum>Calc sum</button>
|
||||
|
||||
</body>
|
||||
</html>
|
180
libs/rust-sciter/examples/interop.rs
Normal file
180
libs/rust-sciter/examples/interop.rs
Normal file
@ -0,0 +1,180 @@
|
||||
//! Sciter interop with native code and vice versa.
|
||||
|
||||
#![allow(unused_variables)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::{HELEMENT, Element, Value};
|
||||
|
||||
struct EventHandler {
|
||||
root: Option<Element>,
|
||||
}
|
||||
|
||||
impl Drop for EventHandler {
|
||||
fn drop(&mut self) {
|
||||
println!("interop::EventHandler: Bye bye, HTML!");
|
||||
}
|
||||
}
|
||||
|
||||
impl EventHandler {
|
||||
|
||||
fn script_call_test(&self, args: &[Value], root: &Element) -> Option<Value> {
|
||||
|
||||
println!("root: {:?}", root);
|
||||
// return None;
|
||||
|
||||
println!("calling 'hello'");
|
||||
let answer = root.call_function("hello", &make_args!("hello, rust!"));
|
||||
println!(" answer {:?}", answer);
|
||||
|
||||
println!("get and call 'hello'");
|
||||
let answer = root.eval_script(r"hello");
|
||||
if answer.is_err() {
|
||||
return None;
|
||||
}
|
||||
let obj = answer.unwrap();
|
||||
let answer = obj.call(None, &make_args!("argument"), None);
|
||||
println!(" answer is {:?}", answer);
|
||||
|
||||
println!("eval 'hello'");
|
||||
let answer = root.eval_script(r#"hello("42");"#);
|
||||
println!(" answer is {:?}", answer);
|
||||
|
||||
println!("calling 'raise_error'; the following exceptions are expected then:");
|
||||
let answer = root.call_function("raise_error", &make_args!(17, "42", false));
|
||||
println!(" answer is {:?}", answer);
|
||||
|
||||
println!("calling inexisting function");
|
||||
let answer = root.call_function("raise_error2", &[]);
|
||||
println!(" answer is {:?}", answer);
|
||||
|
||||
Some(Value::from(true))
|
||||
}
|
||||
|
||||
fn NativeCall(&mut self, arg: String) -> Value {
|
||||
Value::from(format!("Rust window ({})", arg))
|
||||
}
|
||||
|
||||
fn GetNativeApi(&mut self) -> Value {
|
||||
|
||||
fn on_add(args: &[Value]) -> Value {
|
||||
let ints = args.iter().map(|x| x.to_int().unwrap());
|
||||
// let sum: i32 = ints.sum(); // error: issue #27739
|
||||
let sum: i32 = ints.sum();
|
||||
Value::from(sum)
|
||||
}
|
||||
|
||||
fn on_sub(args: &[Value]) -> Value {
|
||||
if args.len() != 2 || args.iter().any(|x| !x.is_int()) {
|
||||
return Value::error("sub requires 2 integer arguments!");
|
||||
}
|
||||
let ints: Vec<_> = args.iter().map(|x| x.to_int().unwrap()).collect();
|
||||
let (a,b) = (ints[0], ints[1]);
|
||||
Value::from(a - b)
|
||||
}
|
||||
|
||||
let on_mul = |args: &[Value]| -> Value {
|
||||
let prod: i32 = args.iter().map(|x| x.to_int().unwrap()).product();
|
||||
Value::from(prod)
|
||||
};
|
||||
|
||||
let mut api = Value::new();
|
||||
|
||||
api.set_item("add", on_add);
|
||||
api.set_item("sub", on_sub);
|
||||
api.set_item("mul", on_mul);
|
||||
|
||||
println!("returning {:?}", api);
|
||||
|
||||
api
|
||||
}
|
||||
|
||||
fn calc_sum(&mut self, a: i32, b: i32) -> i32 {
|
||||
a + b
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
impl sciter::EventHandler for EventHandler {
|
||||
|
||||
fn attached(&mut self, root: HELEMENT) {
|
||||
self.root = Some(Element::from(root));
|
||||
}
|
||||
|
||||
dispatch_script_call! {
|
||||
|
||||
fn NativeCall(String);
|
||||
|
||||
fn GetNativeApi();
|
||||
|
||||
fn calc_sum(i32, i32);
|
||||
}
|
||||
|
||||
fn on_script_call(&mut self, root: HELEMENT, name: &str, argv: &[Value]) -> Option<Value> {
|
||||
|
||||
let args = argv.iter().map(|x| format!("{:?}", &x)).collect::<Vec<String>>().join(", ");
|
||||
println!("script->native: {}({}), root {:?}", name, args, Element::from(root));
|
||||
|
||||
let handled = self.dispatch_script_call(root, name, argv);
|
||||
if handled.is_some() {
|
||||
return handled;
|
||||
}
|
||||
|
||||
if name == "ScriptCallTest" {
|
||||
return self.script_call_test(argv, &Element::from(root));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn check_options() {
|
||||
sciter::set_options(sciter::RuntimeOptions::ScriptFeatures(
|
||||
sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_SYSINFO as u8 // Enables `Sciter.machineName()`
|
||||
| sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_FILE_IO as u8 // Enables opening file dialog (`view.selectFile()`)
|
||||
)).ok();
|
||||
|
||||
for arg in std::env::args() {
|
||||
if arg.starts_with("--sciter-gfx=") {
|
||||
use sciter::GFX_LAYER;
|
||||
let backend = match arg.split_at("--sciter-gfx=".len()).1.trim() {
|
||||
"auto" => GFX_LAYER::AUTO,
|
||||
"cpu" => GFX_LAYER::CPU,
|
||||
"skia" | "skia-cpu" => GFX_LAYER::SKIA_CPU,
|
||||
"skia-opengl" => GFX_LAYER::SKIA_OPENGL,
|
||||
|
||||
#[cfg(windows)]
|
||||
"d2d" => GFX_LAYER::D2D,
|
||||
#[cfg(windows)]
|
||||
"warp" => GFX_LAYER::WARP,
|
||||
|
||||
_ => GFX_LAYER::AUTO,
|
||||
};
|
||||
println!("setting {:?} backend", backend);
|
||||
let ok = sciter::set_options(sciter::RuntimeOptions::GfxLayer(backend));
|
||||
if let Err(e) = ok {
|
||||
println!("failed to set backend: {:?}", e);
|
||||
}
|
||||
|
||||
} else if arg.starts_with("--ux-theme") {
|
||||
#[cfg(windows)]
|
||||
sciter::set_options(sciter::RuntimeOptions::UxTheming(true)).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// interop --sciter-gfx=cpu --ux-theme
|
||||
check_options();
|
||||
|
||||
let html = include_bytes!("interop.htm");
|
||||
let handler = EventHandler { root: None };
|
||||
let mut frame = sciter::Window::new();
|
||||
frame.event_handler(handler);
|
||||
frame.load_html(html, Some("example://interop.htm"));
|
||||
frame.run_app();
|
||||
}
|
88
libs/rust-sciter/examples/minimal.htm
Normal file
88
libs/rust-sciter/examples/minimal.htm
Normal file
@ -0,0 +1,88 @@
|
||||
<html window-icon="https://sciter.com/wp-content/themes/sciter/!images/favicon.ico">
|
||||
<head>
|
||||
<title>Minimalistic Sciter demo</title>
|
||||
<style>
|
||||
|
||||
html {
|
||||
background: radial-gradient(75% 75%, circle farthest-side, white, orange, rgb(0,0,204));
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
html:rtl {
|
||||
mapping: left-to-right(background);
|
||||
}
|
||||
|
||||
a { color: white; }
|
||||
code { font-weight: bold; }
|
||||
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
view.caption = $(head > title).value;
|
||||
|
||||
$(#machine).text = Sciter.machineName();
|
||||
$(#version).text = String.printf("%d.%d.%d.%d",
|
||||
(Sciter.VERSION >> 16) & 0xffff, Sciter.VERSION & 0xffff,
|
||||
(Sciter.REVISION >> 16) & 0xffff, Sciter.REVISION & 0xffff);
|
||||
|
||||
try {
|
||||
// since 4.2.5.0
|
||||
$(#revision).text = Sciter.BUILD.toString();
|
||||
} catch(e) {
|
||||
$(#revision).text = "N/A";
|
||||
}
|
||||
|
||||
var counter = 0;
|
||||
|
||||
$(button#append).on("click", function() {
|
||||
$(body).$append(<h1#test>{ ++counter }</h1>);
|
||||
});
|
||||
|
||||
$(button#open).on("click", function() {
|
||||
|
||||
var fn = view.selectFile(#open,
|
||||
"HTML Files (*.htm,*.html)|*.HTM;*.HTML|All Files (*.*)|*.*" , "html" );
|
||||
|
||||
// if the dialog was closed or
|
||||
// filesystem interaction was disabled via `ALLOW_FILE_IO`
|
||||
// the selected file `fn` would be `undefined`.
|
||||
stdout.println("selected file: " + fn);
|
||||
|
||||
if (fn) {
|
||||
$(body).$append(<h1#test>{fn}</h1>);
|
||||
}
|
||||
});
|
||||
|
||||
// Some tricks with hyperlinks:
|
||||
$(a).on("click", function() {
|
||||
Sciter.launch(this.attributes["href"]);
|
||||
return true;
|
||||
});
|
||||
|
||||
for (var a in $$(a)) {
|
||||
a.attributes["title"] = a.attributes["href"];
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Minimal Sciter Application</h1>
|
||||
<p>Running on <em #machine /> machine</p>
|
||||
<p>Sciter version <span #version /> rev <span #revision /></p>
|
||||
|
||||
<button #append>Append</button>
|
||||
<button #open>Open</button>
|
||||
<select>
|
||||
<option>Some</option>
|
||||
<option>Items</option>
|
||||
<option>in select</option>
|
||||
</select>
|
||||
|
||||
<section class=footer>
|
||||
<p>You can inspect this window in the <a href="https://sciter.com/developers/development-tools/">Inspector tool</a>
|
||||
from the <a href="https://sciter.com/download/">Sciter SDK</a>.</p>
|
||||
<p>Run the Inspector first and then press <code>CTRL+SHIFT+I</code> in this window.</p>
|
||||
</section>
|
||||
|
||||
</body>
|
||||
</html>
|
43
libs/rust-sciter/examples/minimal.rs
Normal file
43
libs/rust-sciter/examples/minimal.rs
Normal file
@ -0,0 +1,43 @@
|
||||
//! Minimalistic Sciter sample.
|
||||
|
||||
// Specify the Windows subsystem to eliminate console window.
|
||||
// Requires Rust 1.18.
|
||||
#![windows_subsystem="windows"]
|
||||
|
||||
extern crate sciter;
|
||||
|
||||
fn main() {
|
||||
// Step 1: Include the 'minimal.html' file as a byte array.
|
||||
// Hint: Take a look into 'minimal.html' which contains some tiscript code.
|
||||
let html = include_bytes!("minimal.htm");
|
||||
|
||||
// Step 2: Enable the features we need in our tiscript code.
|
||||
sciter::set_options(sciter::RuntimeOptions::ScriptFeatures(
|
||||
sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_SYSINFO as u8 // Enables `Sciter.machineName()`
|
||||
| sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_FILE_IO as u8 // Enables opening file dialog (`view.selectFile()`)
|
||||
)).unwrap();
|
||||
|
||||
// Enable debug mode for all windows, so that we can inspect them via Inspector.
|
||||
sciter::set_options(sciter::RuntimeOptions::DebugMode(true)).unwrap();
|
||||
|
||||
// Step 3: Create a new main sciter window of type `sciter::Window`.
|
||||
// Hint: The sciter Window wrapper (src/window.rs) contains more
|
||||
// interesting functions to open or attach to another existing window.
|
||||
let mut frame = sciter::Window::new();
|
||||
|
||||
if cfg!(target_os="macos") {
|
||||
// a temporary workaround for OSX, see
|
||||
// https://sciter.com/forums/topic/global-sciter_set_debug_mode-does-not-work-in-osx/
|
||||
frame.set_options(sciter::window::Options::DebugMode(true)).unwrap();
|
||||
}
|
||||
|
||||
// Step 4: Load HTML byte array from memory to `sciter::Window`.
|
||||
// Hint: second parameter is an optional uri, it can be `None` in simple cases,
|
||||
// but it is useful for debugging purposes (check the Inspector tool from the Sciter SDK).
|
||||
// Also you can use a `load_file` method, but it requires an absolute path
|
||||
// of the main document to resolve HTML resources properly.
|
||||
frame.load_html(html, Some("example://minimal.htm"));
|
||||
|
||||
// Step 5: Show window and run the main app message loop until window been closed.
|
||||
frame.run_app();
|
||||
}
|
67
libs/rust-sciter/examples/som.htm
Normal file
67
libs/rust-sciter/examples/som.htm
Normal file
@ -0,0 +1,67 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>SOM test</title>
|
||||
<style type="text/css">
|
||||
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
if(0) {
|
||||
debug(asset traits);
|
||||
debug: Asset.typeOf(TestGlobal);
|
||||
debug: Asset.hasProperty(TestGlobal, #age);
|
||||
debug: Asset.hasMethod(TestGlobal, #print);
|
||||
|
||||
debug(asset globals);
|
||||
debug: TestGlobal;
|
||||
debug: view.TestGlobal;
|
||||
debug: view.root.TestGlobal;
|
||||
|
||||
debug(asset properties);
|
||||
debug: TestGlobal.age;
|
||||
|
||||
TestGlobal.age = 17;
|
||||
debug: TestGlobal.age;
|
||||
|
||||
TestGlobal.name = "Demogor";
|
||||
debug: TestGlobal.name;
|
||||
|
||||
debug: TestGlobal.print();
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
if(1) {
|
||||
debug(event handler);
|
||||
|
||||
debug(implicit access);
|
||||
var prop = view.TestGlobal;
|
||||
debug: prop;
|
||||
|
||||
var int_prop = prop.age;
|
||||
debug: int_prop;
|
||||
|
||||
debug(explicit access);
|
||||
debug: view.TestGlobal;
|
||||
|
||||
var val = view.TestGlobal.age;
|
||||
debug: val;
|
||||
|
||||
debug: view.TestGlobal.age;
|
||||
|
||||
view.TestGlobal.age = 12;
|
||||
debug: view.TestGlobal.age;
|
||||
|
||||
debug: view.TestGlobal.print();
|
||||
|
||||
debug: view.TestGlobal.add_year(12);
|
||||
debug: view.TestGlobal.age;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div>Hello, body</div>
|
||||
<p>but open Inspector to see the logs</p>
|
||||
|
||||
</body>
|
||||
</html>
|
193
libs/rust-sciter/examples/som.rs
Normal file
193
libs/rust-sciter/examples/som.rs
Normal file
@ -0,0 +1,193 @@
|
||||
// there are logs in console window
|
||||
// #![windows_subsystem="windows"]
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::{HELEMENT, types::{BOOL, VALUE}};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Object {
|
||||
age: i32,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl Object {
|
||||
pub fn print(&self) -> String {
|
||||
format!("name: {}, age: {}", self.name, self.age)
|
||||
}
|
||||
|
||||
pub fn add_year(&mut self, v: i32) -> i32 {
|
||||
self.age += v;
|
||||
self.age
|
||||
}
|
||||
}
|
||||
|
||||
// SOM Passport of the asset.
|
||||
// TODO: should be auto-generated.
|
||||
impl sciter::om::Passport for Object {
|
||||
fn get_passport(&self) -> &'static sciter::om::som_passport_t {
|
||||
use sciter::om::*;
|
||||
|
||||
extern "C" fn on_print(thing: *mut som_asset_t, _argc: u32, _argv: *const VALUE, p_result: &mut VALUE) -> BOOL
|
||||
{
|
||||
let me = IAsset::<Object>::from_raw(&thing);
|
||||
let r = me.print();
|
||||
let r: sciter::Value = r.into();
|
||||
r.pack_to(p_result);
|
||||
return true as BOOL;
|
||||
}
|
||||
extern "C" fn on_add_year(thing: *mut som_asset_t, argc: u32, argv: *const VALUE, p_result: &mut VALUE) -> BOOL
|
||||
{
|
||||
let me = IAsset::<Object>::from_raw(&thing);
|
||||
|
||||
let args = unsafe { sciter::Value::unpack_from(argv, argc) };
|
||||
let required = 1;
|
||||
if args.len() != required {
|
||||
let r = sciter::Value::error(&format!("{} error: {} of {} arguments provided.", "Object::add_year", args.len(), required));
|
||||
r.pack_to(p_result);
|
||||
return true as BOOL;
|
||||
}
|
||||
|
||||
let r = me.add_year(
|
||||
match sciter::FromValue::from_value(&args[0]) {
|
||||
Some(arg) => arg,
|
||||
None => {
|
||||
let r = sciter::Value::error(&format!("{} error: invalid type of {} argument ({} expected, {:?} provided).",
|
||||
"Object::add_year", 0, "i32", &args[0]
|
||||
));
|
||||
r.pack_to(p_result);
|
||||
return true as BOOL;
|
||||
}
|
||||
},
|
||||
);
|
||||
let r: sciter::Value = r.into();
|
||||
r.pack_to(p_result);
|
||||
return true as BOOL;
|
||||
}
|
||||
|
||||
extern "C" fn on_get_age(thing: *mut som_asset_t, p_value: &mut VALUE) -> BOOL
|
||||
{
|
||||
let me = IAsset::<Object>::from_raw(&thing);
|
||||
let r = sciter::Value::from(&me.age);
|
||||
r.pack_to(p_value);
|
||||
return true as BOOL;
|
||||
}
|
||||
extern "C" fn on_set_age(thing: *mut som_asset_t, p_value: &VALUE) -> BOOL
|
||||
{
|
||||
let me = IAsset::<Object>::from_raw(&thing);
|
||||
use sciter::FromValue;
|
||||
let v = sciter::Value::from(p_value);
|
||||
if let Some(v) = FromValue::from_value(&v) {
|
||||
me.age = v;
|
||||
true as BOOL
|
||||
} else {
|
||||
false as BOOL
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn on_get_name(thing: *mut som_asset_t, p_value: &mut VALUE) -> BOOL
|
||||
{
|
||||
let me = IAsset::<Object>::from_raw(&thing);
|
||||
let r = sciter::Value::from(&me.name);
|
||||
r.pack_to(p_value);
|
||||
return true as BOOL;
|
||||
}
|
||||
extern "C" fn on_set_name(thing: *mut som_asset_t, p_value: &VALUE) -> BOOL
|
||||
{
|
||||
let me = IAsset::<Object>::from_raw(&thing);
|
||||
use sciter::FromValue;
|
||||
let v = sciter::Value::from(p_value);
|
||||
if let Some(v) = FromValue::from_value(&v) {
|
||||
me.name = v;
|
||||
true as BOOL
|
||||
} else {
|
||||
false as BOOL
|
||||
}
|
||||
}
|
||||
|
||||
type ObjectMethods = [som_method_def_t; 2];
|
||||
|
||||
let mut methods = Box::new(ObjectMethods::default());
|
||||
|
||||
let mut method = &mut methods[0];
|
||||
method.name = atom("print");
|
||||
method.func = Some(on_print);
|
||||
method.params = 0;
|
||||
|
||||
let mut method = &mut methods[1];
|
||||
method.name = atom("add_year");
|
||||
method.func = Some(on_add_year);
|
||||
method.params = 1;
|
||||
|
||||
type ObjectProps = [som_property_def_t; 2];
|
||||
|
||||
let mut props = Box::new(ObjectProps::default());
|
||||
|
||||
let mut prop = &mut props[0];
|
||||
prop.name = atom("age");
|
||||
prop.getter = Some(on_get_age);
|
||||
prop.setter = Some(on_set_age);
|
||||
|
||||
let mut prop = &mut props[1];
|
||||
prop.name = atom("name");
|
||||
prop.getter = Some(on_get_name);
|
||||
prop.setter = Some(on_set_name);
|
||||
|
||||
let mut pst = Box::new(som_passport_t::default());
|
||||
pst.name = atom("TestGlobal");
|
||||
|
||||
pst.n_methods = 2;
|
||||
pst.methods = Box::into_raw(methods) as *const _;
|
||||
|
||||
pst.n_properties = 2;
|
||||
pst.properties = Box::into_raw(props) as *const _;
|
||||
|
||||
Box::leak(pst)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Handler {
|
||||
asset: sciter::om::IAssetRef<Object>,
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for Handler {
|
||||
fn attached(&mut self, _root: HELEMENT) {
|
||||
println!("attached");
|
||||
}
|
||||
fn detached(&mut self, _root: HELEMENT) {
|
||||
println!("detached");
|
||||
}
|
||||
fn document_complete(&mut self, _root: HELEMENT, _target: HELEMENT) {
|
||||
println!("loaded");
|
||||
}
|
||||
|
||||
fn get_asset(&mut self) -> Option<&sciter::om::som_asset_t> {
|
||||
Some(self.asset.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
sciter::set_options(sciter::RuntimeOptions::DebugMode(true)).unwrap();
|
||||
|
||||
let mut frame = sciter::Window::new();
|
||||
|
||||
let object = Object::default();
|
||||
let object = sciter::om::IAsset::new(object);
|
||||
sciter::om::into_global(object);
|
||||
|
||||
let object2 = Object::default();
|
||||
let object2 = sciter::om::IAsset::new(object2);
|
||||
let object2 = sciter::om::IAssetRef::from(object2);
|
||||
let ptr = object2.as_ptr();
|
||||
let psp = object2.get_passport();
|
||||
println!{"asset {:?} psp {:?}", ptr, psp as *const _};
|
||||
println!("asset: {:?}", object2);
|
||||
|
||||
let handler = Handler { asset: object2 };
|
||||
frame.event_handler(handler);
|
||||
|
||||
let html = include_bytes!("som.htm");
|
||||
frame.load_html(html, Some("example://som.htm"));
|
||||
frame.run_app();
|
||||
}
|
82
libs/rust-sciter/examples/threads.htm
Normal file
82
libs/rust-sciter/examples/threads.htm
Normal file
@ -0,0 +1,82 @@
|
||||
<html window-icon="https://cdn2.iconfinder.com/data/icons/arts-crafts-sewing/24/sewing_thread_handcraft_craft_1-32.png">
|
||||
<head>
|
||||
<title>Threads demo</title>
|
||||
<style>
|
||||
div#content { flow:horizontal; size:*; }
|
||||
div#explanation { size:*; padding:20px; overflow:auto; }
|
||||
div#explanation > pre { padding:10px; border:1px dotted #999; background:#ffffef; }
|
||||
|
||||
div#tasks { width:300px; height:*; }
|
||||
div#tasks > select { size:*; display:block; }
|
||||
div#tasks > select progress { margin-left: 5px; }
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
|
||||
var taskNo = 0;
|
||||
|
||||
$(#start-task).onClick = function()
|
||||
{
|
||||
++taskNo;
|
||||
|
||||
var taskElem = $(div#tasks > select).$append(<option>Task { taskNo }<progress max=100 /> <span.result /></option>);
|
||||
|
||||
function onProgress(p100) { taskElem.$(progress).value = p100; }
|
||||
function onDone(taskId) {
|
||||
taskElem.$(span.result).text = "Done!";
|
||||
taskElem.$(progress).remove();
|
||||
}
|
||||
|
||||
view.exec_task(taskNo, onProgress, onDone);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Sciter UI, threads demo</h2>
|
||||
<div id="content">
|
||||
<div id="tasks">
|
||||
<button id="start-task">Start Task</button>
|
||||
<select type="select"></select>
|
||||
</div>
|
||||
<div id="explanation">
|
||||
<p>The Start Task onClick handler is defined as</p>
|
||||
<pre>
|
||||
$(#start-task).onClick = function()
|
||||
{
|
||||
var taskElem = $(div#tasks > select)
|
||||
.$append(<option>Task { ++taskNo }
|
||||
<progress max=100 />
|
||||
<span.result /></option>);
|
||||
function onProgress(p100) {
|
||||
taskElem.$(progress).value = p100;
|
||||
}
|
||||
function onDone(taskId) {
|
||||
taskElem.$(span.result).text = "Done!";
|
||||
taskElem.$(progress).remove();
|
||||
}
|
||||
view.exec_task(taskId, onProgress, onDone);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>It defines couple of callback functions and calls <code>view.exec_task()</code> with them.</p>
|
||||
<p>The <code>view.exec_task()</code> native method is implemented in <code>EventHandler::exec_task()</code>.</p>
|
||||
<p>The <code>EventHandler::exec_task()</code> starts worker thread passing <em>taskNo</em>, <em>onProgress</em> and
|
||||
<em>onDone</em> parameters to it.</p>
|
||||
<p>Worker thread body is defined in Rust code as:</p>
|
||||
<pre>
|
||||
// worker thread body, simulate time consuming task
|
||||
fn thread_body(task_no: i32, progress: Value, done: Value)
|
||||
{
|
||||
for i in 1..100 {
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
progress.call(None, &make_args!(i), None).unwrap(); // report task progress
|
||||
}
|
||||
// report task completion,
|
||||
// we can pass some result data here, for now just taskId
|
||||
done.call(None, &make_args!(task_no), None).unwrap();
|
||||
}
|
||||
</pre>
|
||||
<p>As you see it calls passed callback functions.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
42
libs/rust-sciter/examples/threads.rs
Normal file
42
libs/rust-sciter/examples/threads.rs
Normal file
@ -0,0 +1,42 @@
|
||||
#[macro_use]
|
||||
extern crate sciter;
|
||||
use sciter::Value;
|
||||
|
||||
struct EventHandler;
|
||||
|
||||
impl EventHandler {
|
||||
// script handler
|
||||
fn exec_task(&self, task_no: i32, progress: sciter::Value, done: sciter::Value) -> bool {
|
||||
|
||||
use std::{thread, time};
|
||||
thread::spawn(move || {
|
||||
|
||||
for i in 1..100 {
|
||||
// call `onProgress` callback
|
||||
thread::sleep(time::Duration::from_millis(100));
|
||||
progress.call(None, &make_args!(i), None).unwrap();
|
||||
}
|
||||
|
||||
// call `onDone` callback
|
||||
done.call(None, &make_args!(task_no), None).unwrap();
|
||||
});
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for EventHandler {
|
||||
// route script calls to our handler
|
||||
dispatch_script_call! {
|
||||
fn exec_task(i32, Value, Value);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let html = include_bytes!("threads.htm");
|
||||
let mut frame = sciter::WindowBuilder::main_window()
|
||||
.with_size((1200, 900))
|
||||
.create();
|
||||
frame.event_handler(EventHandler);
|
||||
frame.load_html(html, None);
|
||||
frame.run_app();
|
||||
}
|
122
libs/rust-sciter/examples/video.htm
Normal file
122
libs/rust-sciter/examples/video.htm
Normal file
@ -0,0 +1,122 @@
|
||||
<html window-icon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB1UlEQVR4nJWTP2hTcRDHP3epS4TqqHHtVNNCFzNFaZD8sxQkKQrOUnCLBoIoOIkG0nYQBbO4OiRLadpEIQ6dxEGxcdclg6Ngpt/vPZd78vqwBQ+O3933vtz97o4TEvKodDkP3ADyQNbgCXAIDJ6Ovh3G+RIZD0vZDNAENoF0MrHJDHgNdJ6NJlMABWiVljIBshUgjQBJB8iHANkMEAKkZu/QYo0A2WqVljJ/E3i06dHbHv3u0QceXWuPjroexaP99uhIPFqz2NS4TQBplFfywPCUb0fS2xl+3miUV+4CXWunnLqycOleiKyGSC1EboUIJ+hibiEzDZFiiCyGyJkQ+Tnn0LxV6Ccq/gBemv0YmAeKQB2oGT+vDs06FIcuvxp+ErNx6HmHVhxadui8YRcc2nNo3/ysOklhKgAx/5yT1KqTVCGGvegOP244SS1HmHp0YtO+ZhuJ9ItHczbxCHtinK/mT+RO5epzoAX8sj6TkgPenxBrq0MHDp3F+kyqOvTNP/CZQwcCUK8UtoFGbLpnewfjWbxUvVJIA79jnJ3ewfj+HIAX7QAXY6vcu1m9vguMzS94WI+t+y3QgdgxrVeL/3VMu/vvpscSRLJWLZ16znv7o2Pn/AeeJco8j/W3vQAAAABJRU5ErkJggg==">
|
||||
<head>
|
||||
<title>Video behavior demo</title>
|
||||
<style>
|
||||
body { background: gold; padding: 5dip; margin: 0; }
|
||||
|
||||
form { margin: 5dip; }
|
||||
|
||||
p { padding: 4dip; }
|
||||
|
||||
video.generator {
|
||||
behavior: video-generator video;
|
||||
border: 1px solid orange;
|
||||
size: *;
|
||||
foreground-size: contain;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
|
||||
$(video).onSize = function() {
|
||||
var (w,h) = this.box(#dimension);
|
||||
$(form).value = { width: w, height: h };
|
||||
}
|
||||
|
||||
function self.ready() {
|
||||
var (w,h) = this.box(#dimension);
|
||||
$(form).value = { width: w, height: h };
|
||||
}
|
||||
|
||||
event click $(#snapshot) {
|
||||
var curframe = $(video).style.foregroundImage;
|
||||
var fname = view.selectFile(#save, "Images|*.png;*.jpg|All files|*.*", "png");
|
||||
if (fname) {
|
||||
var image = curframe.toBytes();
|
||||
image.save(fname);
|
||||
}
|
||||
}
|
||||
|
||||
var video = $(video);
|
||||
var host;
|
||||
var body = $(body);
|
||||
|
||||
event click $(#show-detached) {
|
||||
|
||||
if (body && !video.parent) {
|
||||
// recreate element
|
||||
video = body.$append(<video class="generator" />);
|
||||
}
|
||||
|
||||
// It creates a new window and moves the current video element to it.
|
||||
if( this.value )
|
||||
{
|
||||
host = view.window {
|
||||
type: View.TOOL_WINDOW,
|
||||
html: $(#templates).text,
|
||||
width: 640,
|
||||
height: 480,
|
||||
alignment: 5,
|
||||
};
|
||||
video.detach();
|
||||
host.root.$(body).append(video);
|
||||
|
||||
host.on("closing", function(evt) {
|
||||
// detach
|
||||
video.detach();
|
||||
body.append(video);
|
||||
$(#show-detached).value = false;
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
// and back
|
||||
video.detach();
|
||||
body.append(video);
|
||||
host.close();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script id="templates" type="text/html+template">
|
||||
|
||||
<html window-resizable>
|
||||
<head>
|
||||
<title>Hosted element</title>
|
||||
<style>
|
||||
body { margin: 0; padding: 0; }
|
||||
|
||||
video.generator {
|
||||
display: block;
|
||||
behavior: video-generator video;
|
||||
size: *;
|
||||
foreground-size: contain;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>This demo simulates partial video frame update.
|
||||
On each frame (24 FPS) it updates another portion of the frame.</p>
|
||||
|
||||
<div>
|
||||
<button id="snapshot">Save the current frame</button>
|
||||
<button type=checkbox id="show-detached">Show video in a separate window</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<form>frame size: <output name=width /> x <output name=height /></form>
|
||||
</div>
|
||||
|
||||
<video class="generator" />
|
||||
|
||||
</body>
|
||||
</html>
|
177
libs/rust-sciter/examples/video.rs
Normal file
177
libs/rust-sciter/examples/video.rs
Normal file
@ -0,0 +1,177 @@
|
||||
#![allow(unused_variables, unused_must_use)]
|
||||
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::dom::event::*;
|
||||
use sciter::{Element, HELEMENT};
|
||||
|
||||
use sciter::video::{fragmented_video_destination, AssetPtr};
|
||||
|
||||
struct VideoGen {
|
||||
thread: Option<std::thread::JoinHandle<()>>,
|
||||
}
|
||||
|
||||
impl Drop for VideoGen {
|
||||
fn drop(&mut self) {
|
||||
println!("[video] behavior is destroyed");
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoGen {
|
||||
fn new() -> Self {
|
||||
Self { thread: None }
|
||||
}
|
||||
|
||||
fn generation_thread(site: AssetPtr<fragmented_video_destination>) {
|
||||
println!("[video] thread is started");
|
||||
|
||||
// our video frame size and its part to update
|
||||
const FRAME: (i32, i32) = (1200, 800);
|
||||
const UPDATE: (i32, i32) = (256, 32);
|
||||
|
||||
// our frame data (RGBA)
|
||||
let figure = [0xFF_FFA500u32; (UPDATE.0 * UPDATE.1) as usize];
|
||||
|
||||
// configure video output
|
||||
let mut site = site;
|
||||
let ok = site.start_streaming(FRAME, sciter::video::COLOR_SPACE::Rgb32, None);
|
||||
println!("[video] initialized: {:?}", ok);
|
||||
|
||||
let mut x = 0;
|
||||
let mut xd = 1;
|
||||
let mut y = 0;
|
||||
let mut yd = 1;
|
||||
while site.is_alive() {
|
||||
// send an update portion
|
||||
let buf: &[u8] = unsafe { std::mem::transmute(figure.as_ref()) };
|
||||
site.render_frame_part(buf, (x, y), UPDATE);
|
||||
|
||||
// set the next position
|
||||
x += xd;
|
||||
y += yd;
|
||||
|
||||
if x == 0 {
|
||||
xd = 1;
|
||||
} else if x + UPDATE.0 == FRAME.0 {
|
||||
xd = -1;
|
||||
}
|
||||
if y == 0 {
|
||||
yd = 1;
|
||||
} else if y + UPDATE.1 == FRAME.1 {
|
||||
yd = -1;
|
||||
}
|
||||
|
||||
// simulate 25 FPS
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000 / 25));
|
||||
}
|
||||
|
||||
site.stop_streaming();
|
||||
println!("[video] thread is finished");
|
||||
}
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for VideoGen {
|
||||
fn get_subscription(&mut self) -> Option<EVENT_GROUPS> {
|
||||
Some(EVENT_GROUPS::HANDLE_BEHAVIOR_EVENT)
|
||||
}
|
||||
|
||||
fn detached(&mut self, _root: HELEMENT) {
|
||||
println!("[video] <video> element is detached");
|
||||
if let Some(h) = self.thread.take() {
|
||||
h.join();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
root: HELEMENT,
|
||||
source: HELEMENT,
|
||||
target: HELEMENT,
|
||||
code: BEHAVIOR_EVENTS,
|
||||
phase: PHASE_MASK,
|
||||
reason: EventReason,
|
||||
) -> bool {
|
||||
if phase != PHASE_MASK::BUBBLING {
|
||||
return false;
|
||||
}
|
||||
|
||||
match code {
|
||||
BEHAVIOR_EVENTS::VIDEO_BIND_RQ => {
|
||||
let source = Element::from(source);
|
||||
println!("[video] {:?} {} ({:?})", code, source, reason);
|
||||
|
||||
if let EventReason::VideoBind(ptr) = reason {
|
||||
if ptr.is_null() {
|
||||
// first, consume the event to announce us as a video producer.
|
||||
return true;
|
||||
}
|
||||
|
||||
use sciter::video::*;
|
||||
|
||||
// `VideoBind` comes with a video_destination interface
|
||||
let mut site = AssetPtr::from(ptr as *mut video_destination);
|
||||
|
||||
// query a fragmented video destination interface
|
||||
if let Ok(fragmented) = AssetPtr::<fragmented_video_destination>::try_from(&mut site) {
|
||||
// and use it
|
||||
println!("[video] start video thread");
|
||||
|
||||
let tid = ::std::thread::spawn(|| VideoGen::generation_thread(fragmented));
|
||||
self.thread = Some(tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BEHAVIOR_EVENTS::VIDEO_INITIALIZED => {
|
||||
println!("[video] {:?}", code);
|
||||
}
|
||||
|
||||
BEHAVIOR_EVENTS::VIDEO_STARTED => {
|
||||
println!("[video] {:?}", code);
|
||||
|
||||
let source = Element::from(source);
|
||||
use sciter::dom::ELEMENT_AREAS;
|
||||
let flags = ELEMENT_AREAS::CONTENT_BOX as u32 | ELEMENT_AREAS::SELF_RELATIVE as u32;
|
||||
let rc = source.get_location(flags).unwrap();
|
||||
println!("[video] start video thread on <{}> which is about {:?} pixels", source, rc.size());
|
||||
}
|
||||
|
||||
BEHAVIOR_EVENTS::VIDEO_STOPPED => {
|
||||
println!("[video] {:?}", code);
|
||||
}
|
||||
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if cfg!(all(target_os = "windows", target_arch = "x86")) {
|
||||
println!("\nerror: Sciter video will not work on Windows x86.");
|
||||
println!("error: Consider using a nightly Rust version to enable `abi_thiscall`,");
|
||||
println!("error: see https://github.com/rust-lang/rust/issues/42202");
|
||||
println!("");
|
||||
std::process::exit(126);
|
||||
}
|
||||
|
||||
if sciter::version_num() < 0x04_04_02_0E {
|
||||
// since 4.4.2.14
|
||||
println!("\nerror: `sciter::video` requires SOM support.");
|
||||
println!("error: Sciter API was changed in '4.4.2.14'");
|
||||
println!("error: Sciter version is '{}' now", sciter::version());
|
||||
println!("error: see https://sciter.com/native-code-exposure-to-script/");
|
||||
println!("error: and https://sciter.com/developers/for-native-gui-programmers/sciter-object-model/");
|
||||
println!("");
|
||||
std::process::exit(126);
|
||||
}
|
||||
|
||||
let mut frame = sciter::WindowBuilder::main_window()
|
||||
.with_size((750, 750))
|
||||
.create();
|
||||
frame.set_title("Video renderer sample");
|
||||
frame.register_behavior("video-generator", || Box::new(VideoGen::new()));
|
||||
frame.load_html(include_bytes!("video.htm"), Some("example://video.htm"));
|
||||
frame.run_app();
|
||||
}
|
320
libs/rust-sciter/examples/windowless.rs
Normal file
320
libs/rust-sciter/examples/windowless.rs
Normal file
@ -0,0 +1,320 @@
|
||||
//! Windowless mode example (for Sciter.Lite build).
|
||||
extern crate sciter;
|
||||
extern crate winit;
|
||||
extern crate winapi;
|
||||
extern crate raw_window_handle;
|
||||
|
||||
|
||||
fn main() {
|
||||
// "Windowless" Sciter builds are incompatible with the regular ones.
|
||||
if !cfg!(feature = "windowless") {
|
||||
panic!("This example requires \"windowless\" feature!");
|
||||
}
|
||||
|
||||
// We need this to explicitly set path to the windowless sciter dll.
|
||||
if !cfg!(feature = "dynamic") {
|
||||
panic!("This example requires the \"dynamic\" feature enabled.")
|
||||
}
|
||||
|
||||
if let Some(arg) = std::env::args().nth(1) {
|
||||
println!("loading sciter from {:?}", arg);
|
||||
if let Err(_) = sciter::set_options(sciter::RuntimeOptions::LibraryPath(&arg)) {
|
||||
panic!("Invalid sciter-lite dll specified.");
|
||||
}
|
||||
}
|
||||
|
||||
// prepare and create a new window
|
||||
println!("create window");
|
||||
let mut events = winit::EventsLoop::new();
|
||||
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
let wnd = winit::WindowBuilder::new();
|
||||
let wnd = wnd.build(&events).expect("Failed to create window");
|
||||
let window_handle = wnd.raw_window_handle();
|
||||
|
||||
// configure Sciter
|
||||
println!("create sciter instance");
|
||||
sciter::set_options(sciter::RuntimeOptions::UxTheming(true)).unwrap();
|
||||
sciter::set_options(sciter::RuntimeOptions::DebugMode(true)).unwrap();
|
||||
sciter::set_options(sciter::RuntimeOptions::ScriptFeatures(0xFF)).unwrap();
|
||||
|
||||
// create an engine instance with an opaque pointer as an identifier
|
||||
use sciter::windowless::{Message, handle_message};
|
||||
let scwnd = { &wnd as *const _ as sciter::types::HWINDOW };
|
||||
handle_message(scwnd, Message::Create { backend: sciter::types::GFX_LAYER::SKIA_OPENGL, transparent: false, });
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
// Windows-specific: we need to redraw window in responce to the corresponding notification.
|
||||
// winit 0.20 has an explicit `Window::request_redraw` method,
|
||||
// here we use `winapi::InvalidateRect` for this.
|
||||
struct WindowlessHandler {
|
||||
hwnd: winapi::shared::windef::HWND,
|
||||
}
|
||||
|
||||
impl sciter::HostHandler for WindowlessHandler {
|
||||
fn on_invalidate(&mut self, pnm: &sciter::host::SCN_INVALIDATE_RECT) {
|
||||
unsafe {
|
||||
let rc = &pnm.invalid_rect;
|
||||
let dst = winapi::shared::windef::RECT {
|
||||
left: rc.left,
|
||||
top: rc.top,
|
||||
right: rc.right,
|
||||
bottom: rc.bottom,
|
||||
};
|
||||
winapi::um::winuser::InvalidateRect(self.hwnd, &dst as *const _, 0);
|
||||
// println!("- {} {}", rc.width(), rc.height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let handler = WindowlessHandler {
|
||||
hwnd: match window_handle {
|
||||
raw_window_handle::RawWindowHandle::Windows(data) => data.hwnd as winapi::shared::windef::HWND,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
|
||||
let instance = sciter::Host::attach_with(scwnd, handler);
|
||||
|
||||
let html = include_bytes!("minimal.htm");
|
||||
instance.load_html(html, Some("example://minimal.htm"));
|
||||
}
|
||||
|
||||
// events processing
|
||||
use sciter::windowless::{MouseEvent, KeyboardEvent, RenderEvent};
|
||||
use sciter::windowless::{MOUSE_BUTTONS, MOUSE_EVENTS, KEYBOARD_STATES, KEY_EVENTS};
|
||||
|
||||
let mut mouse_button = MOUSE_BUTTONS::NONE;
|
||||
let mut mouse_pos = (0, 0);
|
||||
|
||||
let as_keys = |modifiers: winit::ModifiersState| {
|
||||
let mut keys = 0;
|
||||
if modifiers.ctrl {
|
||||
keys |= 0x01;
|
||||
}
|
||||
if modifiers.shift {
|
||||
keys |= 0x02;
|
||||
}
|
||||
if modifiers.alt {
|
||||
keys |= 0x04;
|
||||
}
|
||||
KEYBOARD_STATES::from(keys)
|
||||
};
|
||||
|
||||
println!("running...");
|
||||
use winit::{Event, WindowEvent};
|
||||
let skip = ();
|
||||
let mut poll_break = false;
|
||||
let startup = std::time::Instant::now();
|
||||
loop {
|
||||
// release CPU a bit, hackish
|
||||
std::thread::sleep(std::time::Duration::from_millis(0));
|
||||
|
||||
// Sciter processes timers and fading effects here
|
||||
handle_message(scwnd, Message::Heartbit {
|
||||
milliseconds: std::time::Instant::now().duration_since(startup).as_millis() as u32,
|
||||
});
|
||||
|
||||
// the actual event loop polling
|
||||
events.poll_events(|event: winit::Event| {
|
||||
match event {
|
||||
Event::WindowEvent { event, window_id: _ } => {
|
||||
match event {
|
||||
WindowEvent::Destroyed => {
|
||||
// never called due to loop break on close
|
||||
println!("destroy");
|
||||
handle_message(scwnd, Message::Destroy);
|
||||
poll_break = true;
|
||||
},
|
||||
|
||||
WindowEvent::CloseRequested => {
|
||||
println!("close");
|
||||
poll_break = true;
|
||||
},
|
||||
|
||||
WindowEvent::Resized(size) => {
|
||||
// println!("{:?}, size: {:?}", event, size);
|
||||
let (width, height): (u32, u32) = size.into();
|
||||
handle_message(scwnd, Message::Size { width, height });
|
||||
skip
|
||||
},
|
||||
|
||||
WindowEvent::Refresh => {
|
||||
|
||||
let on_render = move |bitmap_area: &sciter::types::RECT, bitmap_data: &[u8]|
|
||||
{
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let _ = bitmap_area;
|
||||
let _ = bitmap_data;
|
||||
let _ = window_handle;
|
||||
}
|
||||
|
||||
// Windows-specific bitmap rendering on the window
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use winapi::um::winuser::*;
|
||||
use winapi::um::wingdi::*;
|
||||
use winapi::shared::minwindef::LPVOID;
|
||||
|
||||
let hwnd = match window_handle {
|
||||
raw_window_handle::RawWindowHandle::Windows(data) => data.hwnd as winapi::shared::windef::HWND,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
unsafe {
|
||||
// NOTE: we use `GetDC` here instead of `BeginPaint`, because the way
|
||||
// winit 0.19 processed the `WM_PAINT` message (it always calls `DefWindowProcW`).
|
||||
|
||||
// let mut ps = PAINTSTRUCT::default();
|
||||
// let hdc = BeginPaint(hwnd, &mut ps as *mut _);
|
||||
|
||||
let hdc = GetDC(hwnd);
|
||||
|
||||
let (w, h) = (bitmap_area.width(), bitmap_area.height());
|
||||
|
||||
let mem_dc = CreateCompatibleDC(hdc);
|
||||
let mem_bm = CreateCompatibleBitmap(hdc, w, h);
|
||||
|
||||
let mut bmi = BITMAPINFO::default();
|
||||
{
|
||||
let mut info = &mut bmi.bmiHeader;
|
||||
info.biSize = std::mem::size_of::<BITMAPINFO>() as u32;
|
||||
info.biWidth = w;
|
||||
info.biHeight = -h;
|
||||
info.biPlanes = 1;
|
||||
info.biBitCount = 32;
|
||||
}
|
||||
|
||||
let old_bm = SelectObject(mem_dc, mem_bm as LPVOID);
|
||||
|
||||
let _copied = StretchDIBits(mem_dc, 0, 0, w, h, 0, 0, w, h, bitmap_data.as_ptr() as *const _, &bmi as *const _, 0, SRCCOPY);
|
||||
let _ok = BitBlt(hdc, 0, 0, w, h, mem_dc, 0, 0, SRCCOPY);
|
||||
|
||||
SelectObject(mem_dc, old_bm);
|
||||
|
||||
// EndPaint(hwnd, &ps as *const _);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
|
||||
// println!("+ {} {}", w, h);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
let cb = RenderEvent {
|
||||
layer: None,
|
||||
callback: Box::new(on_render),
|
||||
};
|
||||
|
||||
handle_message(scwnd, Message::RenderTo(cb));
|
||||
skip
|
||||
},
|
||||
|
||||
WindowEvent::Focused(enter) => {
|
||||
println!("focus {}", enter);
|
||||
handle_message(scwnd, Message::Focus { enter });
|
||||
skip
|
||||
},
|
||||
|
||||
WindowEvent::CursorEntered { device_id: _ } => {
|
||||
println!("mouse enter");
|
||||
let event = MouseEvent {
|
||||
event: MOUSE_EVENTS::MOUSE_ENTER,
|
||||
button: mouse_button,
|
||||
modifiers: KEYBOARD_STATES::from(0),
|
||||
pos: sciter::types::POINT {
|
||||
x: mouse_pos.0,
|
||||
y: mouse_pos.1,
|
||||
},
|
||||
};
|
||||
|
||||
handle_message(scwnd, Message::Mouse(event));
|
||||
skip
|
||||
},
|
||||
|
||||
WindowEvent::CursorLeft { device_id: _ } => {
|
||||
println!("mouse leave");
|
||||
let event = MouseEvent {
|
||||
event: MOUSE_EVENTS::MOUSE_LEAVE,
|
||||
button: mouse_button,
|
||||
modifiers: KEYBOARD_STATES::from(0),
|
||||
pos: sciter::types::POINT {
|
||||
x: mouse_pos.0,
|
||||
y: mouse_pos.1,
|
||||
},
|
||||
};
|
||||
|
||||
handle_message(scwnd, Message::Mouse(event));
|
||||
skip
|
||||
},
|
||||
|
||||
WindowEvent::CursorMoved { device_id: _, position, modifiers } => {
|
||||
mouse_pos = position.into();
|
||||
|
||||
let event = MouseEvent {
|
||||
event: MOUSE_EVENTS::MOUSE_MOVE,
|
||||
button: mouse_button,
|
||||
modifiers: as_keys(modifiers),
|
||||
pos: sciter::types::POINT {
|
||||
x: mouse_pos.0,
|
||||
y: mouse_pos.1,
|
||||
},
|
||||
};
|
||||
|
||||
handle_message(scwnd, Message::Mouse(event));
|
||||
skip
|
||||
},
|
||||
|
||||
WindowEvent::MouseInput { device_id: _, state, button, modifiers } => {
|
||||
mouse_button = match button {
|
||||
winit::MouseButton::Left => MOUSE_BUTTONS::MAIN,
|
||||
winit::MouseButton::Right => MOUSE_BUTTONS::PROP,
|
||||
winit::MouseButton::Middle => MOUSE_BUTTONS::MIDDLE,
|
||||
_ => MOUSE_BUTTONS::NONE,
|
||||
};
|
||||
println!("mouse {:?} as {:?}", mouse_button, mouse_pos);
|
||||
|
||||
let event = MouseEvent {
|
||||
event: if state == winit::ElementState::Pressed { MOUSE_EVENTS::MOUSE_DOWN } else { MOUSE_EVENTS::MOUSE_UP },
|
||||
button: mouse_button,
|
||||
modifiers: as_keys(modifiers),
|
||||
pos: sciter::types::POINT {
|
||||
x: mouse_pos.0,
|
||||
y: mouse_pos.1,
|
||||
},
|
||||
};
|
||||
|
||||
handle_message(scwnd, Message::Mouse(event));
|
||||
skip
|
||||
},
|
||||
|
||||
WindowEvent::KeyboardInput { device_id: _, input } => {
|
||||
println!("key {} {}", input.scancode, if input.state == winit::ElementState::Pressed { "down" } else { "up" });
|
||||
|
||||
let event = KeyboardEvent {
|
||||
event: if input.state == winit::ElementState::Pressed { KEY_EVENTS::KEY_DOWN } else { KEY_EVENTS::KEY_UP },
|
||||
code: input.scancode,
|
||||
modifiers: as_keys(input.modifiers),
|
||||
};
|
||||
|
||||
handle_message(scwnd, Message::Keyboard(event));
|
||||
skip
|
||||
},
|
||||
|
||||
_ => (),
|
||||
}
|
||||
},
|
||||
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
|
||||
if poll_break {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
println!("done, quit");
|
||||
}
|
25
libs/rust-sciter/serde/Cargo.toml
Normal file
25
libs/rust-sciter/serde/Cargo.toml
Normal file
@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "sciter-serde"
|
||||
version = "0.3.2"
|
||||
description = "Serde support for Sciter engine."
|
||||
keywords = ["serde", "gui", "gtk", "opengl", "skia"]
|
||||
categories = ["gui", "web-programming", "rendering::graphics-api", "api-bindings"]
|
||||
|
||||
authors = ["pravic <ehysta@gmail.com>"]
|
||||
repository = "https://github.com/sciter-sdk/rust-sciter"
|
||||
documentation = "https://docs.rs/sciter-serde"
|
||||
license = "MIT"
|
||||
|
||||
exclude = [".gitignore", ".editorconfig", ".appveyor.yml"]
|
||||
|
||||
[badges]
|
||||
appveyor = { repository = "sciter-sdk/rust-sciter" }
|
||||
travis-ci = { repository = "sciter-sdk/rust-sciter" }
|
||||
|
||||
[dependencies]
|
||||
sciter-rs = { version = "0.5" }
|
||||
serde = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
serde_derive = "1"
|
||||
serde_bytes = "0.10"
|
278
libs/rust-sciter/serde/src/de.rs
Normal file
278
libs/rust-sciter/serde/src/de.rs
Normal file
@ -0,0 +1,278 @@
|
||||
/// Deserialization.
|
||||
use serde::de::{self, Deserialize, Visitor};
|
||||
|
||||
use error::{Error, Result};
|
||||
use sciter::{Value};
|
||||
|
||||
|
||||
/// Deserializes a Sciter value to the specific Rust type.
|
||||
pub fn from_value<'a, T>(input: &'a Value) -> Result<T>
|
||||
where T: Deserialize<'a>
|
||||
{
|
||||
let p = Deserializer::from_value(input.clone());
|
||||
T::deserialize(p)
|
||||
}
|
||||
|
||||
|
||||
/// Implementation of deserialization.
|
||||
pub struct Deserializer {
|
||||
input: Value,
|
||||
}
|
||||
|
||||
|
||||
impl<'de> Deserializer {
|
||||
|
||||
pub fn from_value(input: Value) -> Self {
|
||||
Deserializer { input: input }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'de, 'a> ::serde::de::Deserializer<'de> for Deserializer {
|
||||
type Error = Error;
|
||||
|
||||
|
||||
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value>
|
||||
{
|
||||
use sciter::value::VALUE_TYPE;
|
||||
match self.input.get_type() {
|
||||
VALUE_TYPE::T_UNDEFINED|VALUE_TYPE::T_NULL => visitor.visit_none(),
|
||||
VALUE_TYPE::T_BOOL => visitor.visit_bool(self.input.to_bool().unwrap()),
|
||||
VALUE_TYPE::T_INT => visitor.visit_i32(self.input.to_int().unwrap()),
|
||||
VALUE_TYPE::T_FLOAT => visitor.visit_f64(self.input.to_float().unwrap()),
|
||||
VALUE_TYPE::T_STRING => visitor.visit_str(&self.input.as_string().unwrap()),
|
||||
VALUE_TYPE::T_ARRAY => visitor.visit_seq(SeqAccess::new(self)),
|
||||
VALUE_TYPE::T_MAP => self.deserialize_map(visitor),
|
||||
VALUE_TYPE::T_BYTES => visitor.visit_bytes(self.input.as_bytes().unwrap()),
|
||||
VALUE_TYPE::T_OBJECT => self.deserialize_map(visitor),
|
||||
_ => Err(Error::UnsupportedType),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||
if let Some(v) = self.input.to_bool() {
|
||||
visitor.visit_bool(v)
|
||||
} else {
|
||||
Err(Error::ExpectedType(format!("expected {:?}, given {:?}", "bool", self.input)))
|
||||
}
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf
|
||||
}
|
||||
|
||||
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||
if self.input.is_undefined() || self.input.is_null() {
|
||||
visitor.visit_none()
|
||||
} else {
|
||||
visitor.visit_some(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||
if self.input.is_undefined() || self.input.is_null() {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
Err(Error::ExpectedType(format!("expected {:?}, given {:?}", "null", self.input)))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_unit_struct<V: Visitor<'de>>(self, _name: &'static str, visitor: V) -> Result<V::Value> {
|
||||
self.deserialize_unit(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_newtype_struct<V: Visitor<'de>>(self, _name: &str, visitor: V) -> Result<V::Value> {
|
||||
visitor.visit_newtype_struct(self)
|
||||
}
|
||||
|
||||
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||
if self.input.is_array() {
|
||||
let it = self.input.values();
|
||||
let sq = de::value::SeqDeserializer::new(it);
|
||||
visitor.visit_seq(sq)
|
||||
} else {
|
||||
Err(Error::ExpectedType(format!("expected {:?}, given {:?}", "sequence", self.input)))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value> {
|
||||
self.deserialize_seq(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_tuple_struct<V: Visitor<'de>>(self, _name: &'static str, _len: usize, visitor: V) -> Result<V::Value> {
|
||||
self.deserialize_seq(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||
if self.input.is_map() {
|
||||
let it = self.input.items().into_iter();
|
||||
let sq = de::value::MapDeserializer::new(it);
|
||||
visitor.visit_map(sq)
|
||||
} else {
|
||||
Err(Error::ExpectedType(format!("expected {:?}, given {:?}", "map", self.input)))
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_struct<V: Visitor<'de>>(self, _name: &'static str, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
|
||||
{
|
||||
self.deserialize_map(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value>
|
||||
{
|
||||
self.deserialize_str(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_enum<V: Visitor<'de>>(self, _name: &'static str, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
|
||||
{
|
||||
// it can be `"A"`, `{"T": u8}`, `{S: {"x": u8}}`
|
||||
match (self.input.is_string(), self.input.is_map()) {
|
||||
|
||||
(true, _) => {
|
||||
use self::de::IntoDeserializer;
|
||||
visitor.visit_enum(self.input.as_string().unwrap().into_deserializer())
|
||||
},
|
||||
|
||||
(_, true) => {
|
||||
visitor.visit_enum(SeqAccess::new(self))
|
||||
},
|
||||
|
||||
_ => {
|
||||
Err(Error::ExpectedType(format!("expected enum (as string or map), given {:?}", self.input)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'de> de::IntoDeserializer<'de, Error> for Value {
|
||||
type Deserializer = Deserializer;
|
||||
|
||||
fn into_deserializer(self) -> Self::Deserializer {
|
||||
Deserializer::from_value(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[doc(hidden)]
|
||||
struct SeqAccess {
|
||||
de: Deserializer,
|
||||
pos: usize,
|
||||
len: usize,
|
||||
key: Option<Value>,
|
||||
}
|
||||
|
||||
impl SeqAccess {
|
||||
fn new(d: Deserializer) -> Self {
|
||||
let len = d.input.len();
|
||||
SeqAccess {
|
||||
de: d,
|
||||
pos: 0,
|
||||
len: len,
|
||||
key: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::SeqAccess<'de> for SeqAccess {
|
||||
type Error = Error;
|
||||
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
Some(self.len)
|
||||
}
|
||||
|
||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||
where T: de::DeserializeSeed<'de>
|
||||
{
|
||||
if self.pos < self.len {
|
||||
self.pos += 1;
|
||||
let v = self.de.input.get(self.pos - 1);
|
||||
let inner = Deserializer::from_value(v);
|
||||
seed.deserialize(inner).map(Some)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::MapAccess<'de> for SeqAccess {
|
||||
type Error = Error;
|
||||
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
Some(self.len)
|
||||
}
|
||||
|
||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
|
||||
where K: de::DeserializeSeed<'de>
|
||||
{
|
||||
if self.pos < self.len {
|
||||
self.pos += 1;
|
||||
let v = self.de.input.key_at(self.pos - 1);
|
||||
let inner = Deserializer::from_value(v);
|
||||
seed.deserialize(inner).map(Some)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
|
||||
where V: de::DeserializeSeed<'de>
|
||||
{
|
||||
let v = self.de.input.get(self.pos - 1);
|
||||
let inner = Deserializer::from_value(v);
|
||||
seed.deserialize(inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::EnumAccess<'de> for SeqAccess {
|
||||
type Error = Error;
|
||||
type Variant = Self;
|
||||
|
||||
fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, Self::Variant)>
|
||||
where V: de::DeserializeSeed<'de>
|
||||
{
|
||||
// `{ "N": ... }`
|
||||
// Here I suppose to deserialize the variant key.
|
||||
let v = self.de.input.key_at(0);
|
||||
self.key = Some(v.clone());
|
||||
let vkey = seed.deserialize( Deserializer::from_value(v) )?;
|
||||
Ok((vkey, self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::VariantAccess<'de> for SeqAccess {
|
||||
type Error = Error;
|
||||
|
||||
fn unit_variant(self) -> Result<()> {
|
||||
de::Deserialize::deserialize(self.de)
|
||||
}
|
||||
|
||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
|
||||
where T: de::DeserializeSeed<'de>
|
||||
{
|
||||
// `{ "N": u8 }`
|
||||
let v = self.de.input.get_item(self.key.unwrap());
|
||||
seed.deserialize( Deserializer::from_value(v) )
|
||||
}
|
||||
|
||||
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value>
|
||||
where V: de::Visitor<'de>
|
||||
{
|
||||
// `{ "T": [u8, u8] }`
|
||||
let v = self.de.input.get_item(self.key.unwrap());
|
||||
de::Deserializer::deserialize_tuple(Deserializer::from_value(v), len, visitor)
|
||||
}
|
||||
|
||||
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
|
||||
where V: de::Visitor<'de>
|
||||
{
|
||||
// `{ "S": {r: u8, g: u8, b: u8} }`
|
||||
let v = self.de.input.get_item(self.key.unwrap());
|
||||
de::Deserializer::deserialize_struct(Deserializer::from_value(v), "", fields, visitor)
|
||||
}
|
||||
|
||||
}
|
51
libs/rust-sciter/serde/src/error.rs
Normal file
51
libs/rust-sciter/serde/src/error.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use std;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
use serde::{ser, de};
|
||||
|
||||
|
||||
/// Result type for serialization.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Error type for serialization.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Error {
|
||||
Message(String),
|
||||
Unimplemented,
|
||||
UnsupportedType,
|
||||
ExpectedType(String),
|
||||
}
|
||||
|
||||
impl ser::Error for Error {
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error::Message(msg.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl de::Error for Error {
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error::Message(msg.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
Error::Message(ref msg) => msg,
|
||||
Error::ExpectedType(ref msg) => msg,
|
||||
Error::Unimplemented => "unimplemented",
|
||||
Error::UnsupportedType => "unsupported",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Error::Message(ref msg) => write!(f, "error: {}", msg),
|
||||
Error::ExpectedType(ref msg) => write!(f, "expected: {}", msg),
|
||||
Error::UnsupportedType => write!(f, "unsupported type"),
|
||||
Error::Unimplemented => write!(f, "unimplemented"),
|
||||
}
|
||||
}
|
||||
}
|
155
libs/rust-sciter/serde/src/lib.rs
Normal file
155
libs/rust-sciter/serde/src/lib.rs
Normal file
@ -0,0 +1,155 @@
|
||||
// This component uses Sciter Engine,
|
||||
// copyright Terra Informatica Software, Inc.
|
||||
// (http://terrainformatica.com/).
|
||||
|
||||
/*!
|
||||
|
||||
[Serde](https://docs.rs/serde) support for [Sciter](https://docs.rs/sciter-rs) engine.
|
||||
|
||||
While technically you could just use the `serde_json` crate and perform serialization via
|
||||
an intermediate string (something like `sciter::Value::from_str(&serde_json::to_string(<your data>)?)?`),
|
||||
you can also use direct serialization between your data and `sciter::Value`.
|
||||
|
||||
## Supported types of Sciter value
|
||||
|
||||
+ Bool (`bool`)
|
||||
+ Integer (`i8`-`i32`)
|
||||
+ Float (`f32`-`f64`)
|
||||
+ String (`&str`, `String`)
|
||||
+ Bytes (`&[u8]`)
|
||||
+ Array (`&[T]`, `Vec<T>`)
|
||||
+ Object (key-value mapping like `struct` or `HashMap`, `BTreeMap`, etc.)
|
||||
|
||||
Unsupported:
|
||||
|
||||
- Date
|
||||
- Currency
|
||||
- Length
|
||||
- Range
|
||||
- Duration
|
||||
- Angle
|
||||
- Color
|
||||
|
||||
## Supported types of the Serde data model
|
||||
|
||||
* [x] `bool`
|
||||
* [x] integer types except the following:
|
||||
* [-] `i64`/`u64` - 64-bit integers stored as `f64` in Sciter
|
||||
* [x] strings
|
||||
* [x] byte arrays
|
||||
* [x] option
|
||||
* [x] unit (stored as `null`)
|
||||
* [x] unit struct (stored as `null`)
|
||||
* [x] unit variant (aka `enum`, stored just as enum index of `i32` type)
|
||||
* [x] newtype struct (aka `struct Io(u32)`, stored as underlaying value)
|
||||
* [-] newtype variant
|
||||
* [x] seq, like vector (stored as array)
|
||||
* [x] tuple (stored as array)
|
||||
* [x] tuple struct (stored as array)
|
||||
* [-] tuple variant
|
||||
* [x] map (stored as map)
|
||||
* [x] struct (stored as map)
|
||||
* [-] struct variant
|
||||
|
||||
See the [Serde data model](https://serde.rs/data-model.html) for reference.
|
||||
|
||||
# Examples
|
||||
|
||||
```rust
|
||||
extern crate sciter;
|
||||
extern crate sciter_serde;
|
||||
|
||||
use sciter::Value;
|
||||
use sciter_serde::{from_value, to_value};
|
||||
|
||||
fn back_and_forth() {
|
||||
let v: Value = to_value(&true).unwrap();
|
||||
let b: bool = from_value(&v).unwrap();
|
||||
assert_eq!(b, true);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
// bool
|
||||
let v: Value = to_value(&true).unwrap();
|
||||
assert!(v.is_bool());
|
||||
assert_eq!(v, Value::from(true));
|
||||
|
||||
// numbers
|
||||
let v = to_value(&12u32).unwrap();
|
||||
assert_eq!(v, 12.into());
|
||||
|
||||
let v = to_value(& 42.0f64).unwrap();
|
||||
assert_eq!(v, 42.0f64.into());
|
||||
|
||||
// strings
|
||||
let v = to_value("hello").unwrap();
|
||||
assert_eq!(v, "hello".into());
|
||||
|
||||
// arrays
|
||||
let a = [1,2,3];
|
||||
let v = to_value(&a).unwrap();
|
||||
assert_eq!(v, a.iter().cloned().collect());
|
||||
|
||||
// maps
|
||||
let m = {
|
||||
use std::collections::BTreeMap;
|
||||
let mut m = BTreeMap::new();
|
||||
m.insert("17", 17);
|
||||
m.insert("42", 42);
|
||||
m
|
||||
};
|
||||
let v = to_value(&m).unwrap();
|
||||
assert_eq!(v, Value::parse(r#"{ "17": 17, "42": 42 }"#).unwrap());
|
||||
}
|
||||
```
|
||||
|
||||
With derived serialization:
|
||||
|
||||
```rust
|
||||
# #![doc(test(no_crate_inject))]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde;
|
||||
|
||||
extern crate sciter;
|
||||
extern crate sciter_serde;
|
||||
|
||||
use sciter::Value;
|
||||
use sciter_serde::to_value;
|
||||
|
||||
fn main() {
|
||||
|
||||
// structs
|
||||
#[derive(Serialize)]
|
||||
struct Test {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
let v = to_value(&Test {x: 1, y: 2}).unwrap();
|
||||
assert_eq!(v, Value::parse(r#"{ "x": 1, "y": 2 }"#).unwrap());
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
*/
|
||||
#![allow(clippy::redundant_field_names)]
|
||||
#![allow(clippy::tabs_in_doc_comments)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
extern crate sciter;
|
||||
|
||||
|
||||
mod error;
|
||||
mod ser;
|
||||
mod de;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ser::to_value;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use de::from_value;
|
||||
|
||||
pub use error::{Result, Error};
|
345
libs/rust-sciter/serde/src/ser.rs
Normal file
345
libs/rust-sciter/serde/src/ser.rs
Normal file
@ -0,0 +1,345 @@
|
||||
/// Serialization.
|
||||
use serde::ser::{self, Serialize};
|
||||
|
||||
use error::{Error, Result};
|
||||
use sciter::{Value};
|
||||
|
||||
|
||||
/// Serialize the given data structure into Sciter value.
|
||||
pub fn to_value<T: ?Sized + Serialize>(value: &T) -> Result<Value> {
|
||||
let mut p = Serializer { output: Value::new() };
|
||||
value.serialize(&mut p)?;
|
||||
Ok(p.output)
|
||||
}
|
||||
|
||||
/// Implementation of serialization.
|
||||
pub struct Serializer {
|
||||
output: Value,
|
||||
}
|
||||
|
||||
// Helper structure for serialization of sequence data types (array, map, tuple ans so on).
|
||||
#[doc(hidden)]
|
||||
pub struct SeqSerializer<'a> {
|
||||
ser: &'a mut Serializer,
|
||||
output: Value,
|
||||
key: Option<Value>,
|
||||
outer: Option<Value>,
|
||||
}
|
||||
|
||||
impl<'a> SeqSerializer<'a> {
|
||||
fn typed(ser: &'a mut Serializer, typed: Value) -> Self {
|
||||
SeqSerializer {
|
||||
ser: ser,
|
||||
output: typed,
|
||||
key: None,
|
||||
outer: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_outer(ser: &'a mut Serializer, outer: Value, typed: Value) -> Self {
|
||||
SeqSerializer {
|
||||
ser: ser,
|
||||
output: typed,
|
||||
key: None,
|
||||
outer: Some(outer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// serde traits implementation
|
||||
|
||||
impl<'a> ser::SerializeSeq for SeqSerializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn end(self) -> Result<()> {
|
||||
self.ser.output = self.output;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
|
||||
let dst = to_value(value)?;
|
||||
self.output.push(dst);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeMap for SeqSerializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn end(self) -> Result<()> {
|
||||
ser::SerializeSeq::end(self)
|
||||
}
|
||||
|
||||
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<()> where K: ?Sized + Serialize, V: ?Sized + Serialize {
|
||||
self.output.set_item(to_value(key)?, to_value(value)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<()> {
|
||||
self.key = Some(to_value(key)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
|
||||
let key = self.key.take();
|
||||
self.output.set_item(key.unwrap(), to_value(value)?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeStruct for SeqSerializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn end(self) -> Result<()> {
|
||||
ser::SerializeSeq::end(self)
|
||||
}
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) -> Result<()> {
|
||||
self.output.set_item(key, to_value(value)?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeStructVariant for SeqSerializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn end(self) -> Result<()> {
|
||||
// self.output: map
|
||||
// self.outer: left key
|
||||
let mut result = Value::new();
|
||||
result.set_item(self.outer.unwrap(), self.output);
|
||||
self.ser.output = result;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) -> Result<()> {
|
||||
self.output.set_item(key, to_value(value)?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeTuple for SeqSerializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn end(self) -> Result<()> {
|
||||
ser::SerializeSeq::end(self)
|
||||
}
|
||||
|
||||
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
|
||||
ser::SerializeSeq::serialize_element(self, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeTupleStruct for SeqSerializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn end(self) -> Result<()> {
|
||||
ser::SerializeSeq::end(self)
|
||||
}
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
|
||||
ser::SerializeSeq::serialize_element(self, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::SerializeTupleVariant for SeqSerializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn end(self) -> Result<()> {
|
||||
// self.output: array
|
||||
// self.outer: left key
|
||||
let mut result = Value::new();
|
||||
result.set_item(self.outer.unwrap(), self.output);
|
||||
self.ser.output = result;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
|
||||
ser::SerializeSeq::serialize_element(self, value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> ser::Serializer for &'a mut Serializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
type SerializeSeq = SeqSerializer<'a>;
|
||||
type SerializeTuple = SeqSerializer<'a>;
|
||||
type SerializeTupleStruct = SeqSerializer<'a>;
|
||||
type SerializeTupleVariant = SeqSerializer<'a>;
|
||||
type SerializeMap = SeqSerializer<'a>;
|
||||
type SerializeStruct = SeqSerializer<'a>;
|
||||
type SerializeStructVariant = SeqSerializer<'a>;
|
||||
|
||||
|
||||
fn serialize_bool(self, v: bool) -> Result<()> {
|
||||
self.output = v.into();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_i8(self, v: i8) -> Result<()> {
|
||||
self.serialize_i32(v as i32)
|
||||
}
|
||||
|
||||
fn serialize_i16(self, v: i16) -> Result<()> {
|
||||
self.serialize_i32(v as i32)
|
||||
}
|
||||
|
||||
fn serialize_i32(self, v: i32) -> Result<()> {
|
||||
self.output = v.into();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_u8(self, v: u8) -> Result<()> {
|
||||
self.serialize_i32(v as i32)
|
||||
}
|
||||
|
||||
fn serialize_u16(self, v: u16) -> Result<()> {
|
||||
self.serialize_i32(v as i32)
|
||||
}
|
||||
|
||||
fn serialize_u32(self, v: u32) -> Result<()> {
|
||||
if v <= i32::max_value() as u32 {
|
||||
self.serialize_i32(v as i32)
|
||||
} else {
|
||||
self.serialize_f64(v as f64)
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_i64(self, _v: i64) -> Result<()> {
|
||||
Err(Error::UnsupportedType)
|
||||
}
|
||||
|
||||
fn serialize_u64(self, _v: u64) -> Result<()> {
|
||||
Err(Error::UnsupportedType)
|
||||
}
|
||||
|
||||
// Float values.
|
||||
fn serialize_f32(self, v: f32) -> Result<()> {
|
||||
self.serialize_f64(v as f64)
|
||||
}
|
||||
|
||||
fn serialize_f64(self, v: f64) -> Result<()> {
|
||||
self.output = v.into();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// A single character is passed as a string.
|
||||
fn serialize_char(self, v: char) -> Result<()> {
|
||||
self.serialize_str(&v.to_string())
|
||||
}
|
||||
|
||||
// String itself.
|
||||
fn serialize_str(self, v: &str) -> Result<()> {
|
||||
self.output = v.into();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Binary bytes.
|
||||
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
|
||||
self.output = Value::from(v);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// A `None` value of `Option` type in Rust.
|
||||
fn serialize_none(self) -> Result<()> {
|
||||
self.output = Value::null();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Some value of `Option` type in Rust.
|
||||
fn serialize_some<T>(self, v: &T) -> Result<()> where T: ?Sized + Serialize {
|
||||
v.serialize(self)
|
||||
}
|
||||
|
||||
// The type of `()` in Rust.
|
||||
fn serialize_unit(self) -> Result<()> {
|
||||
self.serialize_none()
|
||||
}
|
||||
|
||||
// A named value containing no data, like `struct Unit;`.
|
||||
fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
|
||||
self.serialize_none()
|
||||
}
|
||||
|
||||
// Enums. Serialized as an externally tagged enum representation,
|
||||
// see https://serde.rs/enum-representations.html.
|
||||
|
||||
// A unit variant of enum, like `E::A` of `enum E { A, B }`.
|
||||
fn serialize_unit_variant(self, _name: &'static str, _index: u32, value: &'static str)
|
||||
-> Result<()>
|
||||
{
|
||||
// `"A"`
|
||||
self.serialize_str(value)
|
||||
}
|
||||
|
||||
// For example the `E::N` in `enum E { N(u8) }`.
|
||||
fn serialize_newtype_variant<T>(self, _name: &'static str, _index: u32, variant: &'static str, value: &T)
|
||||
-> Result<()> where T: ?Sized + Serialize
|
||||
{
|
||||
// `{ "N": u8 }`
|
||||
self.output.set_item(to_value(variant)?, to_value(value)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// For example the `E::T` in `enum E { T(u8, u8) }`.
|
||||
fn serialize_tuple_variant(self, _name: &'static str, _index: u32, value: &'static str, _len: usize)
|
||||
-> Result<Self::SerializeTupleVariant>
|
||||
{
|
||||
// `{ "T": [u8, u8] }`
|
||||
let left = to_value(value)?;
|
||||
Ok(SeqSerializer::with_outer(self, left, Value::array(0)))
|
||||
}
|
||||
|
||||
// For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`.
|
||||
fn serialize_struct_variant(self, _name: &'static str, _index: u32, value: &'static str, _len: usize)
|
||||
-> Result<Self::SerializeStructVariant>
|
||||
{
|
||||
// `{ "S": {r: u8, g: u8, b: u8} }`
|
||||
let left = to_value(value)?;
|
||||
Ok(SeqSerializer::with_outer(self, left, Value::map()))
|
||||
}
|
||||
|
||||
// New-type struct, like `struct Celcius(u32)`.
|
||||
fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
// Serialize the inner itself.
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
// A variably sized heterogeneous sequence of values, for example `Vec<T>` or `HashSet<T>`.
|
||||
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
|
||||
// let init = if let Some(size) = len { Value::array(size) } else { Value::new() };
|
||||
Ok(SeqSerializer::typed(self, Value::array(0)))
|
||||
}
|
||||
|
||||
// A statically sized heterogeneous sequence of values, `[u64; 10]`, `(u8,)` or `(String, u64, Vec<T>)`.
|
||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
|
||||
self.serialize_seq(Some(len))
|
||||
}
|
||||
|
||||
// A named tuple, for example `struct Rgb(u8, u8, u8)`.
|
||||
fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeTupleStruct> {
|
||||
self.serialize_seq(Some(len))
|
||||
}
|
||||
|
||||
// A heterogeneous key-value pairing, for example `BTreeMap<K, V>`.
|
||||
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
|
||||
Ok(SeqSerializer::typed(self, Value::map()))
|
||||
}
|
||||
|
||||
// A heterogeneous key-value pairing , for example `struct S { r: u8, g: u8, b: u8 }`.
|
||||
fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
|
||||
self.serialize_map(Some(len))
|
||||
}
|
||||
|
||||
}
|
201
libs/rust-sciter/serde/tests/both.rs
Normal file
201
libs/rust-sciter/serde/tests/both.rs
Normal file
@ -0,0 +1,201 @@
|
||||
#![allow(unused_variables)]
|
||||
|
||||
extern crate sciter;
|
||||
extern crate sciter_serde;
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_bytes;
|
||||
extern crate serde;
|
||||
|
||||
use sciter_serde::{from_value, to_value};
|
||||
|
||||
|
||||
// serialize, deserialize and compare with the original value.
|
||||
// taken from [serde_bincode](https://github.com/TyOverby/bincode/blob/master/tests/test.rs)
|
||||
fn the_same<V>(actual: V, expr: &'static str)
|
||||
where V: serde::Serialize + serde::de::DeserializeOwned + PartialEq + std::fmt::Debug + 'static
|
||||
{
|
||||
let sv = to_value(&actual).expect(&format!("to_value({})", expr));
|
||||
let dv = from_value(&sv).expect(&format!("from_value({})", expr));
|
||||
let decoded = dv;
|
||||
assert_eq!(actual, decoded, "the_same({:?})", expr);
|
||||
}
|
||||
|
||||
macro_rules! the_same {
|
||||
($e:expr) => {
|
||||
the_same($e, stringify!($e))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_types() {
|
||||
the_same!(true);
|
||||
the_same!(false);
|
||||
|
||||
the_same!(7i8);
|
||||
the_same!(7i16);
|
||||
the_same!(7i32);
|
||||
// the_same!(7i64); there are no 64-bit integers in Sciter, only floats.
|
||||
|
||||
the_same!(7u8);
|
||||
the_same!(7u16);
|
||||
the_same!(7u32);
|
||||
// the_same!(7u64); ditto
|
||||
|
||||
the_same!(7f32);
|
||||
the_same!(7f64);
|
||||
|
||||
the_same!(-7i32);
|
||||
// the_same!(-7isize);
|
||||
|
||||
|
||||
the_same!(Box::new(7));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn strings() {
|
||||
the_same!("7".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuples() {
|
||||
the_same!( (1,) );
|
||||
the_same!( (1,2) );
|
||||
the_same!( (1,2,3) );
|
||||
|
||||
the_same!( (1, "7".to_string(), ()) );
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn structs() {
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
struct Test {
|
||||
x: bool,
|
||||
y: i32,
|
||||
z: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
struct Nested {
|
||||
inner: Test,
|
||||
payload: Option<String>,
|
||||
}
|
||||
|
||||
let t = Test { x: true, y: 7, z: "42".to_string() };
|
||||
|
||||
the_same!(t.clone());
|
||||
|
||||
let n = Nested { inner: t.clone(), payload: Some("Some".to_string()) };
|
||||
the_same!(n.clone());
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtypes() {
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
struct Test(u32);
|
||||
|
||||
the_same!(Test(7));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtuples() {
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
struct Test(u32, bool);
|
||||
|
||||
the_same!(Test(7, false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn options() {
|
||||
the_same!(None::<bool>);
|
||||
the_same!(Some(true));
|
||||
the_same!(Some(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enums() {
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
enum Test {
|
||||
Zero,
|
||||
One(u32),
|
||||
Two(u32, u32),
|
||||
Three { x: u32, y: u32, z: u32 },
|
||||
Five,
|
||||
}
|
||||
|
||||
the_same!(Test::Zero);
|
||||
// the_same!(Test::One(7));
|
||||
// the_same!(Test::Two(7, 7));
|
||||
// the_same!(Test::Three { x: 1, y: 2, z: 3});
|
||||
the_same!(Test::Five);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arrays() {
|
||||
let v = [1,2,3];
|
||||
the_same!(v);
|
||||
|
||||
let v = vec![1,2,3];
|
||||
the_same!(v);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn unsupported_u64() {
|
||||
the_same!(7u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn unsupported_i64() {
|
||||
the_same!(-7i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn unsupported_usize() {
|
||||
the_same!(7usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtype_variant() {
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
enum Test {
|
||||
Zero,
|
||||
One(u32),
|
||||
Two(u32, u32),
|
||||
Three { x: u32, y: u32, z: u32 },
|
||||
}
|
||||
|
||||
the_same!(Test::One(7));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_variant() {
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
enum Test {
|
||||
Zero,
|
||||
One(u32),
|
||||
Two(u32, u32),
|
||||
Three { x: u32, y: u32, z: u32 },
|
||||
}
|
||||
|
||||
the_same!(Test::Two(7, 7));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn struct_variant() {
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
enum Test {
|
||||
Zero,
|
||||
One(u32),
|
||||
Two(u32, u32),
|
||||
Three { x: u32, y: u32, z: u32 },
|
||||
}
|
||||
|
||||
the_same!(Test::Three { x: 1, y: 2, z: 3 });
|
||||
}
|
94
libs/rust-sciter/serde/tests/deserialization.rs
Normal file
94
libs/rust-sciter/serde/tests/deserialization.rs
Normal file
@ -0,0 +1,94 @@
|
||||
#![allow(unused_variables)]
|
||||
|
||||
extern crate sciter;
|
||||
extern crate sciter_serde;
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_bytes;
|
||||
extern crate serde;
|
||||
|
||||
use sciter::{Value};
|
||||
use sciter_serde::{from_value, to_value};
|
||||
|
||||
|
||||
#[test]
|
||||
fn basic_types() {
|
||||
// bool
|
||||
let v: bool = from_value(&Value::from(true)).unwrap();
|
||||
assert_eq!(v, true);
|
||||
|
||||
// integer types
|
||||
let v: i32 = from_value(&Value::from(0)).unwrap();
|
||||
assert_eq!(v, 0);
|
||||
|
||||
let v: i32 = from_value(&Value::from(7i32)).unwrap();
|
||||
assert_eq!(v, 7i32);
|
||||
|
||||
// float
|
||||
let v: f32 = from_value(&Value::from(7.0)).unwrap();
|
||||
assert_eq!(v, 7.0);
|
||||
|
||||
let v: f64 = from_value(&Value::from(7.0)).unwrap();
|
||||
assert_eq!(v, 7.0);
|
||||
|
||||
// Option
|
||||
let v = Value::null();
|
||||
let v: Option<i32> = from_value(&v).unwrap();
|
||||
assert_eq!(v, None);
|
||||
|
||||
let v = Value::from(7);
|
||||
let v: Option<i32> = from_value(&v).unwrap();
|
||||
assert_eq!(v, Some(7));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn strings() {
|
||||
let v: char = from_value(&Value::from("7")).unwrap();
|
||||
assert_eq!(v, '7');
|
||||
|
||||
let v: String = from_value(&Value::from("7")).unwrap();
|
||||
assert_eq!(v, "7");
|
||||
|
||||
let v: serde_bytes::ByteBuf = from_value(&Value::from(b"hello".as_ref())).unwrap();
|
||||
let v: &[u8] = &v;
|
||||
assert_eq!(v, b"hello".as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arrays() {
|
||||
let it = [1,2,3].iter();
|
||||
let v: Value = it.cloned().collect();
|
||||
let v: Vec<i32> = from_value(&v).unwrap();
|
||||
assert_eq!(v, &[1,2,3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn structs() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Test {
|
||||
int: u32,
|
||||
seq: Vec<String>,
|
||||
}
|
||||
|
||||
println!("");
|
||||
|
||||
let a = Test { int: 7, seq: vec!["a".to_owned(), "b".to_owned()]};
|
||||
|
||||
let v: Value = to_value(&a).unwrap();
|
||||
println!("serialized Test:\n {:?}", v);
|
||||
|
||||
println!("keys:");
|
||||
v.keys().inspect(|i| println!(" {:?}", i)).count();
|
||||
|
||||
println!("values:");
|
||||
v.values().inspect(|i| println!(" {:?}", i)).count();
|
||||
|
||||
println!("items:");
|
||||
v.items().iter().inspect(|i| println!(" {:?}", i)).count();
|
||||
|
||||
let e: Test = from_value(&v).unwrap();
|
||||
println!("deserialized Test:\n {:?}", e);
|
||||
|
||||
assert_eq!(a, e);
|
||||
}
|
113
libs/rust-sciter/serde/tests/serialization.rs
Normal file
113
libs/rust-sciter/serde/tests/serialization.rs
Normal file
@ -0,0 +1,113 @@
|
||||
#![allow(unused_variables)]
|
||||
|
||||
extern crate sciter;
|
||||
extern crate sciter_serde;
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_bytes;
|
||||
extern crate serde;
|
||||
|
||||
use sciter::{Value};
|
||||
use sciter_serde::{to_value};
|
||||
|
||||
|
||||
#[test]
|
||||
fn basic_types() {
|
||||
// bool
|
||||
let v = to_value(&true).unwrap();
|
||||
assert!(v.is_bool());
|
||||
assert_eq!(v, Value::from(true));
|
||||
|
||||
// integer types
|
||||
let v = to_value(&0).unwrap();
|
||||
assert!(v.is_int());
|
||||
assert_eq!(v.to_int(), Some(0));
|
||||
|
||||
let v = to_value(&7u8).unwrap();
|
||||
assert_eq!(v, Value::from(7));
|
||||
|
||||
let v = to_value(&7u16).unwrap();
|
||||
assert_eq!(v, Value::from(7));
|
||||
|
||||
let v = to_value(&7u32).unwrap();
|
||||
assert_eq!(v, Value::from(7));
|
||||
|
||||
let v = to_value(&7i8).unwrap();
|
||||
assert_eq!(v, Value::from(7));
|
||||
|
||||
let v = to_value(&7i16).unwrap();
|
||||
assert_eq!(v, Value::from(7));
|
||||
|
||||
let v = to_value(&7i32).unwrap();
|
||||
assert_eq!(v, Value::from(7));
|
||||
|
||||
let v = to_value(&7.0).unwrap();
|
||||
assert!(v.is_float());
|
||||
|
||||
// 64-bit
|
||||
// let v = to_value(&7u64).unwrap();
|
||||
// assert!(v.is_float());
|
||||
// assert_eq!(v, Value::from(7.0));
|
||||
|
||||
// Option
|
||||
// let v = to_value(&Some(7)).unwrap();
|
||||
// assert!(v.is_int());
|
||||
|
||||
// let v = to_value(&None).unwrap();
|
||||
// assert!(v.is_null());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn strings() {
|
||||
// strings
|
||||
let v = to_value(&'h').unwrap();
|
||||
assert!(v.is_string());
|
||||
assert_eq!(v, Value::from("h"));
|
||||
|
||||
let v = to_value("hello").unwrap();
|
||||
assert!(v.is_string());
|
||||
assert_eq!(v, Value::from("hello"));
|
||||
|
||||
// doesn't work because Rust doesn't have specialization yet (https://github.com/rust-lang/rust#31844)
|
||||
// let v = to_value(b"hello").unwrap();
|
||||
// println!("b'hello': {:?}", v);
|
||||
// assert!(v.is_bytes());
|
||||
// assert_eq!(v.as_bytes(), Some(b"hello".as_ref()));
|
||||
|
||||
use serde_bytes::Bytes;
|
||||
|
||||
let v = to_value(&Bytes::new(b"hello")).unwrap();
|
||||
assert!(v.is_bytes());
|
||||
assert_eq!(v.as_bytes(), Some(b"hello".as_ref()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arrays() {
|
||||
let a = [1,2,3];
|
||||
let v = to_value(&a).unwrap();
|
||||
assert!(v.is_array());
|
||||
assert_eq!(v.len(), a.len());
|
||||
|
||||
let a = vec![1,2,3];
|
||||
let v = to_value(&a).unwrap();
|
||||
assert!(v.is_array());
|
||||
assert_eq!(v.len(), a.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn structs() {
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Test {
|
||||
int: u32,
|
||||
seq: Vec<&'static str>,
|
||||
}
|
||||
|
||||
let a = Test { int: 7, seq: vec!["a", "b"]};
|
||||
let v = to_value(&a).unwrap();
|
||||
assert!(v.is_map());
|
||||
assert_eq!(v.len(), 2);
|
||||
assert_eq!(v.get_item("int"), Value::from(7) );
|
||||
assert_eq!(v.get_item("seq").len(), 2);
|
||||
}
|
14
libs/rust-sciter/src/capi/mod.rs
Normal file
14
libs/rust-sciter/src/capi/mod.rs
Normal file
@ -0,0 +1,14 @@
|
||||
/*! C interface headers */
|
||||
|
||||
pub mod scapi;
|
||||
pub mod scbehavior;
|
||||
pub mod scdef;
|
||||
pub mod scdom;
|
||||
pub mod scgraphics;
|
||||
pub mod screquest;
|
||||
pub mod sctiscript;
|
||||
pub mod sctypes;
|
||||
pub mod scvalue;
|
||||
pub mod schandler;
|
||||
pub mod scmsg;
|
||||
pub mod scom;
|
279
libs/rust-sciter/src/capi/scapi.rs
Normal file
279
libs/rust-sciter/src/capi/scapi.rs
Normal file
@ -0,0 +1,279 @@
|
||||
//! Sciter C API interface.
|
||||
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::*;
|
||||
use capi::scdom::*;
|
||||
use capi::scvalue::*;
|
||||
use capi::sctiscript::{HVM, tiscript_value, tiscript_native_interface};
|
||||
use capi::scbehavior::*;
|
||||
use capi::scgraphics::SciterGraphicsAPI;
|
||||
use capi::screquest::{SciterRequestAPI, HREQUEST, REQUEST_PARAM};
|
||||
use capi::scmsg::{SCITER_X_MSG};
|
||||
use capi::scom::som_asset_t;
|
||||
|
||||
|
||||
/// Sciter API functions.
|
||||
#[repr(C)]
|
||||
#[allow(missing_docs)]
|
||||
#[doc(hidden)]
|
||||
pub struct ISciterAPI
|
||||
{
|
||||
pub version: UINT,
|
||||
|
||||
pub SciterClassName: extern "system" fn () -> LPCWSTR,
|
||||
pub SciterVersion: extern "system" fn (major: BOOL) -> UINT,
|
||||
|
||||
pub SciterDataReady: extern "system" fn (hwnd: HWINDOW, uri: LPCWSTR, data: LPCBYTE, dataLength: UINT) -> BOOL,
|
||||
pub SciterDataReadyAsync: extern "system" fn (hwnd: HWINDOW, uri: LPCWSTR, data: LPCBYTE, dataLength: UINT, requestId: HREQUEST) -> BOOL,
|
||||
|
||||
// #ifdef WINDOWS
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterProc: extern "system" fn (hwnd: HWINDOW, msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterProcND: extern "system" fn (hwnd: HWINDOW, msg: UINT, wParam: WPARAM, lParam: LPARAM, pbHandled: * mut BOOL) -> LRESULT,
|
||||
// #endif
|
||||
|
||||
pub SciterLoadFile: extern "system" fn (hWndSciter: HWINDOW, filename: LPCWSTR) -> BOOL,
|
||||
|
||||
pub SciterLoadHtml: extern "system" fn (hWndSciter: HWINDOW, html: LPCBYTE, htmlSize: UINT, baseUrl: LPCWSTR) -> BOOL,
|
||||
pub SciterSetCallback: extern "system" fn (hWndSciter: HWINDOW, cb: SciterHostCallback, cbParam: LPVOID) -> VOID,
|
||||
pub SciterSetMasterCSS: extern "system" fn (utf8: LPCBYTE, numBytes: UINT) -> BOOL,
|
||||
pub SciterAppendMasterCSS: extern "system" fn (utf8: LPCBYTE, numBytes: UINT) -> BOOL,
|
||||
pub SciterSetCSS: extern "system" fn (hWndSciter: HWINDOW, utf8: LPCBYTE, numBytes: UINT, baseUrl: LPCWSTR, mediaType: LPCWSTR) -> BOOL,
|
||||
pub SciterSetMediaType: extern "system" fn (hWndSciter: HWINDOW, mediaType: LPCWSTR) -> BOOL,
|
||||
pub SciterSetMediaVars: extern "system" fn (hWndSciter: HWINDOW, mediaVars: * const VALUE) -> BOOL,
|
||||
pub SciterGetMinWidth: extern "system" fn (hWndSciter: HWINDOW) -> UINT,
|
||||
pub SciterGetMinHeight: extern "system" fn (hWndSciter: HWINDOW, width: UINT) -> UINT,
|
||||
pub SciterCall: extern "system" fn (hWnd: HWINDOW, functionName: LPCSTR, argc: UINT, argv: * const VALUE, retval: * mut VALUE) -> BOOL,
|
||||
pub SciterEval: extern "system" fn (hwnd: HWINDOW, script: LPCWSTR, scriptLength: UINT, pretval: * mut VALUE) -> BOOL,
|
||||
pub SciterUpdateWindow: extern "system" fn (hwnd: HWINDOW) -> VOID,
|
||||
|
||||
// #ifdef WINDOWS
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterTranslateMessage: extern "system" fn (lpMsg: * mut MSG) -> BOOL,
|
||||
// #endif
|
||||
|
||||
pub SciterSetOption: extern "system" fn (hWnd: HWINDOW, option: SCITER_RT_OPTIONS, value: UINT_PTR) -> BOOL,
|
||||
pub SciterGetPPI: extern "system" fn (hWndSciter: HWINDOW, px: * mut UINT, py: * mut UINT) -> VOID,
|
||||
pub SciterGetViewExpando: extern "system" fn (hwnd: HWINDOW, pval: * mut VALUE) -> BOOL,
|
||||
|
||||
// #ifdef WINDOWS
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterRenderD2D: extern "system" fn (hWndSciter: HWINDOW, prt: * mut ID2D1RenderTarget) -> BOOL,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterD2DFactory: extern "system" fn (ppf: * mut* mut ID2D1Factory) -> BOOL,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterDWFactory: extern "system" fn (ppf: * mut* mut IDWriteFactory) -> BOOL,
|
||||
// #endif
|
||||
|
||||
pub SciterGraphicsCaps: extern "system" fn (pcaps: LPUINT) -> BOOL,
|
||||
pub SciterSetHomeURL: extern "system" fn (hWndSciter: HWINDOW, baseUrl: LPCWSTR) -> BOOL,
|
||||
|
||||
// #if defined(OSX)
|
||||
#[cfg(all(target_os="macos", not(feature = "windowless")))]
|
||||
pub SciterCreateNSView: extern "system" fn (frame: LPRECT) -> HWINDOW, // returns NSView*
|
||||
// #endif
|
||||
|
||||
// #if defined(LINUX)
|
||||
#[cfg(all(target_os="linux", not(feature = "windowless")))]
|
||||
pub SciterCreateWidget: extern "system" fn (frame: LPRECT) -> HWINDOW, // returns GtkWidget
|
||||
// #endif
|
||||
|
||||
#[cfg(not(feature = "windowless"))]
|
||||
pub SciterCreateWindow: extern "system" fn (creationFlags: UINT, frame: LPCRECT, delegate: * const SciterWindowDelegate, delegateParam: LPVOID, parent: HWINDOW) -> HWINDOW,
|
||||
|
||||
pub SciterSetupDebugOutput: extern "system" fn (hwndOrNull: HWINDOW, param: LPVOID, pfOutput: DEBUG_OUTPUT_PROC),
|
||||
|
||||
//|
|
||||
//| DOM Element API
|
||||
//|
|
||||
pub Sciter_UseElement: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub Sciter_UnuseElement: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetRootElement: extern "system" fn (hwnd: HWINDOW, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetFocusElement: extern "system" fn (hwnd: HWINDOW, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterFindElement: extern "system" fn (hwnd: HWINDOW, pt: POINT, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetChildrenCount: extern "system" fn (he: HELEMENT, count: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetNthChild: extern "system" fn (he: HELEMENT, n: UINT, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetParentElement: extern "system" fn (he: HELEMENT, p_parent_he: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementHtmlCB: extern "system" fn (he: HELEMENT, outer: BOOL, rcv: LPCBYTE_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterGetElementTextCB: extern "system" fn (he: HELEMENT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSetElementText: extern "system" fn (he: HELEMENT, utf16: LPCWSTR, length: UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetAttributeCount: extern "system" fn (he: HELEMENT, p_count: LPUINT) -> SCDOM_RESULT,
|
||||
pub SciterGetNthAttributeNameCB: extern "system" fn (he: HELEMENT, n: UINT, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterGetNthAttributeValueCB: extern "system" fn (he: HELEMENT, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterGetAttributeByNameCB: extern "system" fn (he: HELEMENT, name: LPCSTR, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSetAttributeByName: extern "system" fn (he: HELEMENT, name: LPCSTR, value: LPCWSTR) -> SCDOM_RESULT,
|
||||
pub SciterClearAttributes: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementIndex: extern "system" fn (he: HELEMENT, p_index: LPUINT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementType: extern "system" fn (he: HELEMENT, p_type: * mut LPCSTR) -> SCDOM_RESULT,
|
||||
pub SciterGetElementTypeCB: extern "system" fn (he: HELEMENT, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterGetStyleAttributeCB: extern "system" fn (he: HELEMENT, name: LPCSTR, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSetStyleAttribute: extern "system" fn (he: HELEMENT, name: LPCSTR, value: LPCWSTR) -> SCDOM_RESULT,
|
||||
pub SciterGetElementLocation: extern "system" fn (he: HELEMENT, p_location: LPRECT, areas: UINT /*ELEMENT_AREAS*/) -> SCDOM_RESULT,
|
||||
pub SciterScrollToView: extern "system" fn (he: HELEMENT, SciterScrollFlags: UINT) -> SCDOM_RESULT,
|
||||
pub SciterUpdateElement: extern "system" fn (he: HELEMENT, andForceRender: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterRefreshElementArea: extern "system" fn (he: HELEMENT, rc: RECT) -> SCDOM_RESULT,
|
||||
pub SciterSetCapture: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterReleaseCapture: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementHwnd: extern "system" fn (he: HELEMENT, p_hwnd: * mut HWINDOW, rootWindow: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterCombineURL: extern "system" fn (he: HELEMENT, szUrlBuffer: LPWSTR, UrlBufferSize: UINT) -> SCDOM_RESULT,
|
||||
pub SciterSelectElements: extern "system" fn (he: HELEMENT, CSS_selectors: LPCSTR, callback: SciterElementCallback, param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSelectElementsW: extern "system" fn (he: HELEMENT, CSS_selectors: LPCWSTR, callback: SciterElementCallback, param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSelectParent: extern "system" fn (he: HELEMENT, selector: LPCSTR, depth: UINT, heFound: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterSelectParentW: extern "system" fn (he: HELEMENT, selector: LPCWSTR, depth: UINT, heFound: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterSetElementHtml: extern "system" fn (he: HELEMENT, html: * const BYTE, htmlLength: UINT, how: UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementUID: extern "system" fn (he: HELEMENT, puid: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementByUID: extern "system" fn (hwnd: HWINDOW, uid: UINT, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterShowPopup: extern "system" fn (hePopup: HELEMENT, heAnchor: HELEMENT, placement: UINT) -> SCDOM_RESULT,
|
||||
pub SciterShowPopupAt: extern "system" fn (hePopup: HELEMENT, pos: POINT, placement: UINT) -> SCDOM_RESULT,
|
||||
pub SciterHidePopup: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementState: extern "system" fn (he: HELEMENT, pstateBits: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterSetElementState: extern "system" fn (he: HELEMENT, stateBitsToSet: UINT, stateBitsToClear: UINT, updateView: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterCreateElement: extern "system" fn (tagname: LPCSTR, textOrNull: LPCWSTR, /*out*/ phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterCloneElement: extern "system" fn (he: HELEMENT, /*out*/ phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterInsertElement: extern "system" fn (he: HELEMENT, hparent: HELEMENT, index: UINT) -> SCDOM_RESULT,
|
||||
pub SciterDetachElement: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterDeleteElement: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterSetTimer: extern "system" fn (he: HELEMENT, milliseconds: UINT, timer_id: UINT_PTR) -> SCDOM_RESULT,
|
||||
pub SciterDetachEventHandler: extern "system" fn (he: HELEMENT, pep: ElementEventProc, tag: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterAttachEventHandler: extern "system" fn (he: HELEMENT, pep: ElementEventProc, tag: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterWindowAttachEventHandler: extern "system" fn (hwndLayout: HWINDOW, pep: ElementEventProc, tag: LPVOID, subscription: UINT) -> SCDOM_RESULT,
|
||||
pub SciterWindowDetachEventHandler: extern "system" fn (hwndLayout: HWINDOW, pep: ElementEventProc, tag: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSendEvent: extern "system" fn (he: HELEMENT, appEventCode: UINT, heSource: HELEMENT, reason: UINT_PTR, /*out*/ handled: * mut BOOL) -> SCDOM_RESULT,
|
||||
pub SciterPostEvent: extern "system" fn (he: HELEMENT, appEventCode: UINT, heSource: HELEMENT, reason: UINT_PTR) -> SCDOM_RESULT,
|
||||
pub SciterCallBehaviorMethod: extern "system" fn (he: HELEMENT, params: * const METHOD_PARAMS) -> SCDOM_RESULT,
|
||||
pub SciterRequestElementData: extern "system" fn (he: HELEMENT, url: LPCWSTR, dataType: UINT, initiator: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterHttpRequest: extern "system" fn (he: HELEMENT, url: LPCWSTR, dataType: UINT, requestType: UINT, requestParams: * const REQUEST_PARAM, nParams: UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetScrollInfo: extern "system" fn (he: HELEMENT, scrollPos: LPPOINT, viewRect: LPRECT, contentSize: LPSIZE) -> SCDOM_RESULT,
|
||||
pub SciterSetScrollPos: extern "system" fn (he: HELEMENT, scrollPos: POINT, smooth: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterGetElementIntrinsicWidths: extern "system" fn (he: HELEMENT, pMinWidth: * mut INT, pMaxWidth: * mut INT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementIntrinsicHeight: extern "system" fn (he: HELEMENT, forWidth: INT, pHeight: * mut INT) -> SCDOM_RESULT,
|
||||
pub SciterIsElementVisible: extern "system" fn (he: HELEMENT, pVisible: * mut BOOL) -> SCDOM_RESULT,
|
||||
pub SciterIsElementEnabled: extern "system" fn (he: HELEMENT, pEnabled: * mut BOOL) -> SCDOM_RESULT,
|
||||
pub SciterSortElements: extern "system" fn (he: HELEMENT, firstIndex: UINT, lastIndex: UINT, cmpFunc: * mut ELEMENT_COMPARATOR, cmpFuncParam: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSwapElements: extern "system" fn (he1: HELEMENT, he2: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterTraverseUIEvent: extern "system" fn (evt: UINT, eventCtlStruct: LPVOID, bOutProcessed: * mut BOOL) -> SCDOM_RESULT,
|
||||
pub SciterCallScriptingMethod: extern "system" fn (he: HELEMENT, name: LPCSTR, argv: * const VALUE, argc: UINT, retval: * mut VALUE) -> SCDOM_RESULT,
|
||||
pub SciterCallScriptingFunction: extern "system" fn (he: HELEMENT, name: LPCSTR, argv: * const VALUE, argc: UINT, retval: * mut VALUE) -> SCDOM_RESULT,
|
||||
pub SciterEvalElementScript: extern "system" fn (he: HELEMENT, script: LPCWSTR, scriptLength: UINT, retval: * mut VALUE) -> SCDOM_RESULT,
|
||||
pub SciterAttachHwndToElement: extern "system" fn (he: HELEMENT, hwnd: HWINDOW) -> SCDOM_RESULT,
|
||||
pub SciterControlGetType: extern "system" fn (he: HELEMENT, /*CTL_TYPE*/ pType: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetValue: extern "system" fn (he: HELEMENT, pval: * mut VALUE) -> SCDOM_RESULT,
|
||||
pub SciterSetValue: extern "system" fn (he: HELEMENT, pval: * const VALUE) -> SCDOM_RESULT,
|
||||
pub SciterGetExpando: extern "system" fn (he: HELEMENT, pval: * mut VALUE, forceCreation: BOOL) -> SCDOM_RESULT,
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub SciterGetObject: extern "system" fn (he: HELEMENT, pval: * mut tiscript_value, forceCreation: BOOL) -> SCDOM_RESULT,
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub SciterGetElementNamespace: extern "system" fn (he: HELEMENT, pval: * mut tiscript_value) -> SCDOM_RESULT,
|
||||
|
||||
pub SciterGetHighlightedElement: extern "system" fn (hwnd: HWINDOW, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterSetHighlightedElement: extern "system" fn (hwnd: HWINDOW, he: HELEMENT) -> SCDOM_RESULT,
|
||||
//|
|
||||
//| DOM Node API
|
||||
//|
|
||||
pub SciterNodeAddRef: extern "system" fn (hn: HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeRelease: extern "system" fn (hn: HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeCastFromElement: extern "system" fn (he: HELEMENT, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeCastToElement: extern "system" fn (hn: HNODE, he: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterNodeFirstChild: extern "system" fn (hn: HNODE, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeLastChild: extern "system" fn (hn: HNODE, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeNextSibling: extern "system" fn (hn: HNODE, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodePrevSibling: extern "system" fn (hn: HNODE, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeParent: extern "system" fn (hnode: HNODE, pheParent: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterNodeNthChild: extern "system" fn (hnode: HNODE, n: UINT, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeChildrenCount: extern "system" fn (hnode: HNODE, pn: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterNodeType: extern "system" fn (hnode: HNODE, pNodeType: * mut UINT /*NODE_TYPE*/) -> SCDOM_RESULT,
|
||||
pub SciterNodeGetText: extern "system" fn (hnode: HNODE, rcv: * mut LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterNodeSetText: extern "system" fn (hnode: HNODE, text: LPCWSTR, textLength: UINT) -> SCDOM_RESULT,
|
||||
pub SciterNodeInsert: extern "system" fn (hnode: HNODE, how: UINT /*NODE_INS_TARGET*/, what: HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeRemove: extern "system" fn (hnode: HNODE, finalize: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterCreateTextNode: extern "system" fn (text: LPCWSTR, textLength: UINT, phnode: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterCreateCommentNode: extern "system" fn (text: LPCWSTR, textLength: UINT, phnode: * mut HNODE) -> SCDOM_RESULT,
|
||||
//|
|
||||
//| Value API
|
||||
//|
|
||||
pub ValueInit: extern "system" fn (pval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueClear: extern "system" fn (pval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueCompare: extern "system" fn (pval1: * const VALUE, pval2: * const VALUE) -> VALUE_RESULT,
|
||||
pub ValueCopy: extern "system" fn (pdst: * mut VALUE, psrc: * const VALUE) -> VALUE_RESULT,
|
||||
pub ValueIsolate: extern "system" fn (pdst: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueType: extern "system" fn (pval: * const VALUE, pType: * mut UINT, pUnits: * mut UINT) -> VALUE_RESULT,
|
||||
pub ValueStringData: extern "system" fn (pval: * const VALUE, pChars: * mut LPCWSTR, pNumChars: * mut UINT) -> VALUE_RESULT,
|
||||
pub ValueStringDataSet: extern "system" fn (pval: * mut VALUE, chars: LPCWSTR, numChars: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueIntData: extern "system" fn (pval: * const VALUE, pData: * mut INT) -> VALUE_RESULT,
|
||||
pub ValueIntDataSet: extern "system" fn (pval: * mut VALUE, data: INT, vtype: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueInt64Data: extern "system" fn (pval: * const VALUE, pData: * mut INT64) -> VALUE_RESULT,
|
||||
pub ValueInt64DataSet: extern "system" fn (pval: * mut VALUE, data: INT64, vtype: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueFloatData: extern "system" fn (pval: * const VALUE, pData: * mut FLOAT_VALUE) -> VALUE_RESULT,
|
||||
pub ValueFloatDataSet: extern "system" fn (pval: * mut VALUE, data: FLOAT_VALUE, vtype: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueBinaryData: extern "system" fn (pval: * const VALUE, pBytes: * mut LPCBYTE, pnBytes: * mut UINT) -> VALUE_RESULT,
|
||||
pub ValueBinaryDataSet: extern "system" fn (pval: * mut VALUE, pBytes: LPCBYTE, nBytes: UINT, vtype: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueElementsCount: extern "system" fn (pval: * const VALUE, pn: * mut INT) -> VALUE_RESULT,
|
||||
pub ValueNthElementValue: extern "system" fn (pval: * const VALUE, n: INT, pretval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueNthElementValueSet: extern "system" fn (pval: * mut VALUE, n: INT, pval_to_set: * const VALUE) -> VALUE_RESULT,
|
||||
pub ValueNthElementKey: extern "system" fn (pval: * const VALUE, n: INT, pretval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueEnumElements: extern "system" fn (pval: * const VALUE, penum: KeyValueCallback, param: LPVOID) -> VALUE_RESULT,
|
||||
pub ValueSetValueToKey: extern "system" fn (pval: * mut VALUE, pkey: * const VALUE, pval_to_set: * const VALUE) -> VALUE_RESULT,
|
||||
pub ValueGetValueOfKey: extern "system" fn (pval: * const VALUE, pkey: * const VALUE, pretval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueToString: extern "system" fn (pval: * mut VALUE, how: VALUE_STRING_CVT_TYPE) -> VALUE_RESULT,
|
||||
pub ValueFromString: extern "system" fn (pval: * mut VALUE, str: LPCWSTR, strLength: UINT, how: VALUE_STRING_CVT_TYPE) -> UINT,
|
||||
pub ValueInvoke: extern "system" fn (pval: * const VALUE, pthis: * mut VALUE, argc: UINT, argv: * const VALUE, pretval: * mut VALUE, url: LPCWSTR) -> VALUE_RESULT,
|
||||
pub ValueNativeFunctorSet: extern "system" fn (pval: * mut VALUE, pinvoke: NATIVE_FUNCTOR_INVOKE, prelease: NATIVE_FUNCTOR_RELEASE, tag: LPVOID) -> VALUE_RESULT,
|
||||
pub ValueIsNativeFunctor: extern "system" fn (pval: * const VALUE) -> BOOL,
|
||||
|
||||
// tiscript VM API
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub TIScriptAPI: extern "system" fn () -> * mut tiscript_native_interface,
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub SciterGetVM: extern "system" fn (hwnd: HWINDOW) -> HVM,
|
||||
|
||||
// since 3.1.0.12
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub Sciter_v2V: extern "system" fn (vm: HVM, script_value: tiscript_value, value: * mut VALUE, isolate: BOOL) -> BOOL,
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub Sciter_V2v: extern "system" fn (vm: HVM, valuev: * const VALUE, script_value: * mut tiscript_value) -> BOOL,
|
||||
|
||||
// since 3.1.0.18
|
||||
pub SciterOpenArchive: extern "system" fn (archiveData: LPCBYTE, archiveDataLength: UINT) -> HSARCHIVE,
|
||||
pub SciterGetArchiveItem: extern "system" fn (harc: HSARCHIVE, path: LPCWSTR, pdata: * mut LPCBYTE, pdataLength: * mut UINT) -> BOOL,
|
||||
pub SciterCloseArchive: extern "system" fn (harc: HSARCHIVE) -> BOOL,
|
||||
|
||||
// since 3.2.0.0
|
||||
pub SciterFireEvent: extern "system" fn (evt: * const BEHAVIOR_EVENT_PARAMS, post: BOOL, handled: * mut BOOL) -> SCDOM_RESULT,
|
||||
|
||||
pub SciterGetCallbackParam: extern "system" fn (hwnd: HWINDOW) -> LPVOID,
|
||||
pub SciterPostCallback: extern "system" fn (hwnd: HWINDOW, wparam: UINT_PTR, lparam: UINT_PTR, timeoutms: UINT) -> UINT_PTR,
|
||||
|
||||
// since 3.3.1.0
|
||||
pub GetSciterGraphicsAPI: extern "system" fn () -> * const SciterGraphicsAPI,
|
||||
|
||||
// since 3.3.1.6
|
||||
pub GetSciterRequestAPI: extern "system" fn () -> * const SciterRequestAPI,
|
||||
|
||||
// #ifdef WINDOWS
|
||||
// since 3.3.1.4
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterCreateOnDirectXWindow: extern "system" fn (hwnd: HWINDOW, pSwapChain: * mut IDXGISwapChain) -> BOOL,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterRenderOnDirectXWindow: extern "system" fn (hwnd: HWINDOW, elementToRenderOrNull: HELEMENT, frontLayer: BOOL) -> BOOL,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterRenderOnDirectXTexture: extern "system" fn (hwnd: HWINDOW, elementToRenderOrNull: HELEMENT, surface: * mut IDXGISurface) -> BOOL,
|
||||
// #endif
|
||||
|
||||
// since 4.0.0.0
|
||||
pub SciterProcX: extern "system" fn(hwnd: HWINDOW, msg: * const SCITER_X_MSG) -> BOOL,
|
||||
|
||||
// since 4.4.2.14
|
||||
pub SciterAtomValue: extern "system" fn(name: LPCSTR) -> UINT64,
|
||||
pub SciterAtomNameCB: extern "system" fn(atomv: UINT64, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> BOOL,
|
||||
|
||||
// since 4.4.2.16
|
||||
pub SciterSetGlobalAsset: extern "system" fn(pass: *mut som_asset_t) -> BOOL,
|
||||
}
|
0
libs/rust-sciter/src/capi/scarchive.rs
Normal file
0
libs/rust-sciter/src/capi/scarchive.rs
Normal file
543
libs/rust-sciter/src/capi/scbehavior.rs
Normal file
543
libs/rust-sciter/src/capi/scbehavior.rs
Normal file
@ -0,0 +1,543 @@
|
||||
//! C interface for behaviors support (a.k.a windowless controls).
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scdom::*;
|
||||
use capi::scvalue::{VALUE};
|
||||
use capi::scgraphics::{HGFX};
|
||||
use capi::scom::{som_asset_t, som_passport_t};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct BEHAVIOR_EVENT_PARAMS
|
||||
{
|
||||
/// Behavior event code. See [`BEHAVIOR_EVENTS`](enum.BEHAVIOR_EVENTS.html).
|
||||
pub cmd: UINT,
|
||||
|
||||
/// Target element handler.
|
||||
pub heTarget: HELEMENT,
|
||||
|
||||
/// Source element.
|
||||
pub he: HELEMENT,
|
||||
|
||||
/// UI action causing change.
|
||||
pub reason: UINT_PTR,
|
||||
|
||||
/// Auxiliary data accompanied with the event.
|
||||
pub data: VALUE,
|
||||
|
||||
/// Name of the custom event (when `cmd` is [`BEHAVIOR_EVENTS::CUSTOM`](enum.BEHAVIOR_EVENTS.html#variant.CUSTOM)).
|
||||
/// Since 4.2.8.
|
||||
pub name: LPCWSTR,
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum INITIALIZATION_EVENTS
|
||||
{
|
||||
BEHAVIOR_DETACH = 0,
|
||||
BEHAVIOR_ATTACH = 1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct INITIALIZATION_PARAMS
|
||||
{
|
||||
pub cmd: INITIALIZATION_EVENTS,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum SOM_EVENTS
|
||||
{
|
||||
SOM_GET_PASSPORT = 0,
|
||||
SOM_GET_ASSET = 1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub union SOM_PARAMS_DATA
|
||||
{
|
||||
pub asset: *const som_asset_t,
|
||||
pub passport: *const som_passport_t,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SOM_PARAMS
|
||||
{
|
||||
pub cmd: SOM_EVENTS,
|
||||
pub result: SOM_PARAMS_DATA,
|
||||
}
|
||||
|
||||
/// Identifiers of methods currently supported by intrinsic behaviors.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub enum BEHAVIOR_METHOD_IDENTIFIERS {
|
||||
/// Raise a click event.
|
||||
DO_CLICK = 1,
|
||||
|
||||
/// `IS_EMPTY_PARAMS::is_empty` reflects the `:empty` state of the element.
|
||||
IS_EMPTY = 0xFC,
|
||||
|
||||
/// `VALUE_PARAMS`
|
||||
GET_VALUE = 0xFD,
|
||||
/// `VALUE_PARAMS`
|
||||
SET_VALUE = 0xFE,
|
||||
|
||||
/// User method identifier used in custom behaviors.
|
||||
///
|
||||
/// All custom event codes shall be greater than this number.
|
||||
/// All codes below this will be used solely by application - Sciter will not intrepret it
|
||||
/// and will do just dispatching. To send event notifications with these codes use
|
||||
/// `SciterCallBehaviorMethod` API.
|
||||
FIRST_APPLICATION_METHOD_ID = 0x100,
|
||||
}
|
||||
|
||||
/// Method arguments used in `SciterCallBehaviorMethod()` or `HANDLE_METHOD_CALL`.
|
||||
#[repr(C)]
|
||||
pub struct METHOD_PARAMS {
|
||||
/// [`BEHAVIOR_METHOD_IDENTIFIERS`](enum.BEHAVIOR_METHOD_IDENTIFIERS.html) or user identifiers.
|
||||
pub method: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct IS_EMPTY_PARAMS {
|
||||
pub method: UINT,
|
||||
pub is_empty: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct VALUE_PARAMS {
|
||||
pub method: UINT,
|
||||
pub value: VALUE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SCRIPTING_METHOD_PARAMS
|
||||
{
|
||||
pub name: LPCSTR,
|
||||
pub argv: *const VALUE,
|
||||
pub argc: UINT,
|
||||
pub result: VALUE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct TIMER_PARAMS
|
||||
{
|
||||
pub timerId: UINT_PTR,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DRAW_PARAMS {
|
||||
/// Element layer to draw.
|
||||
pub layer: DRAW_EVENTS,
|
||||
|
||||
/// Graphics context.
|
||||
pub gfx: HGFX,
|
||||
|
||||
/// Element area.
|
||||
pub area: RECT,
|
||||
|
||||
/// Zero at the moment.
|
||||
pub reserved: UINT,
|
||||
}
|
||||
|
||||
/// Layer to draw.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DRAW_EVENTS {
|
||||
DRAW_BACKGROUND = 0,
|
||||
DRAW_CONTENT,
|
||||
DRAW_FOREGROUND,
|
||||
/// Note: since 4.2.3.
|
||||
DRAW_OUTLINE,
|
||||
}
|
||||
|
||||
|
||||
/// Event groups for subscription.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum EVENT_GROUPS
|
||||
{ /// Attached/detached.
|
||||
HANDLE_INITIALIZATION = 0x0000,
|
||||
/// Mouse events.
|
||||
HANDLE_MOUSE = 0x0001,
|
||||
/// Key events.
|
||||
HANDLE_KEY = 0x0002,
|
||||
/// Focus events, if this flag is set it also means that element it attached to is focusable.
|
||||
HANDLE_FOCUS = 0x0004,
|
||||
/// Scroll events.
|
||||
HANDLE_SCROLL = 0x0008,
|
||||
/// Timer event.
|
||||
HANDLE_TIMER = 0x0010,
|
||||
/// Size changed event.
|
||||
HANDLE_SIZE = 0x0020,
|
||||
/// Drawing request (event).
|
||||
HANDLE_DRAW = 0x0040,
|
||||
/// Requested data has been delivered.
|
||||
HANDLE_DATA_ARRIVED = 0x080,
|
||||
|
||||
/// Logical, synthetic events:
|
||||
/// `BUTTON_CLICK`, `HYPERLINK_CLICK`, etc.,
|
||||
/// a.k.a. notifications from intrinsic behaviors.
|
||||
HANDLE_BEHAVIOR_EVENT = 0x0100,
|
||||
/// Behavior specific methods.
|
||||
HANDLE_METHOD_CALL = 0x0200,
|
||||
/// Behavior specific methods.
|
||||
HANDLE_SCRIPTING_METHOD_CALL = 0x0400,
|
||||
|
||||
/// Behavior specific methods using direct `tiscript::value`'s.
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
HANDLE_TISCRIPT_METHOD_CALL = 0x0800,
|
||||
|
||||
/// System drag-n-drop.
|
||||
HANDLE_EXCHANGE = 0x1000,
|
||||
/// Touch input events.
|
||||
HANDLE_GESTURE = 0x2000,
|
||||
/// SOM passport and asset requests.
|
||||
HANDLE_SOM = 0x8000,
|
||||
|
||||
/// All of them.
|
||||
HANDLE_ALL = 0xFFFF,
|
||||
|
||||
/// Special value for getting subscription flags.
|
||||
SUBSCRIPTIONS_REQUEST = -1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Event propagation schema.
|
||||
pub enum PHASE_MASK
|
||||
{
|
||||
/// Bubbling phase – direction: from a child element to all its containers.
|
||||
BUBBLING = 0,
|
||||
/// Sinking phase – direction: from containers to target child element.
|
||||
SINKING = 0x0_8000,
|
||||
/// Bubbling event consumed by some child.
|
||||
BUBBLING_HANDLED= 0x1_0000,
|
||||
/// Sinking event consumed by some child.
|
||||
SINKING_HANDLED = 0x1_8000,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Mouse buttons.
|
||||
pub enum MOUSE_BUTTONS
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
/// Left button.
|
||||
MAIN = 1,
|
||||
/// Right button.
|
||||
PROP = 2,
|
||||
/// Middle button.
|
||||
MIDDLE = 3,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Keyboard modifier buttons state.
|
||||
pub enum KEYBOARD_STATES
|
||||
{
|
||||
CONTROL_KEY_PRESSED = 0x01,
|
||||
SHIFT_KEY_PRESSED = 0x02,
|
||||
ALT_KEY_PRESSED = 0x04,
|
||||
}
|
||||
|
||||
impl std::convert::From<u32> for KEYBOARD_STATES {
|
||||
fn from(u: u32) -> Self {
|
||||
unsafe { std::mem::transmute(u) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Keyboard input events.
|
||||
pub enum KEY_EVENTS
|
||||
{
|
||||
KEY_DOWN = 0,
|
||||
KEY_UP,
|
||||
KEY_CHAR,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Mouse events.
|
||||
pub enum MOUSE_EVENTS
|
||||
{
|
||||
MOUSE_ENTER = 0,
|
||||
MOUSE_LEAVE,
|
||||
MOUSE_MOVE,
|
||||
MOUSE_UP,
|
||||
MOUSE_DOWN,
|
||||
MOUSE_DCLICK,
|
||||
MOUSE_WHEEL,
|
||||
/// mouse pressed ticks
|
||||
MOUSE_TICK,
|
||||
/// mouse stay idle for some time
|
||||
MOUSE_IDLE,
|
||||
|
||||
/// item dropped, target is that dropped item
|
||||
DROP = 9,
|
||||
/// drag arrived to the target element that is one of current drop targets.
|
||||
DRAG_ENTER = 0xA,
|
||||
/// drag left one of current drop targets. target is the drop target element.
|
||||
DRAG_LEAVE = 0xB,
|
||||
/// drag src notification before drag start. To cancel - return true from handler.
|
||||
DRAG_REQUEST = 0xC,
|
||||
|
||||
/// mouse click event
|
||||
MOUSE_CLICK = 0xFF,
|
||||
|
||||
/// This flag is `OR`ed with `MOUSE_ENTER..MOUSE_DOWN` codes if dragging operation is in effect.
|
||||
/// E.g. event `DRAGGING | MOUSE_MOVE` is sent to underlying DOM elements while dragging.
|
||||
DRAGGING = 0x100,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
#[allow(missing_docs)]
|
||||
/// General event source triggers
|
||||
pub enum CLICK_REASON
|
||||
{
|
||||
/// By mouse button.
|
||||
BY_MOUSE_CLICK,
|
||||
/// By keyboard (e.g. spacebar).
|
||||
BY_KEY_CLICK,
|
||||
/// Synthesized, by code.
|
||||
SYNTHESIZED,
|
||||
/// Icon click, e.g. arrow icon on drop-down select.
|
||||
BY_MOUSE_ON_ICON,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Edit control change trigger.
|
||||
pub enum EDIT_CHANGED_REASON
|
||||
{
|
||||
/// Single char insertion.
|
||||
BY_INS_CHAR,
|
||||
/// Character range insertion, clipboard.
|
||||
BY_INS_CHARS,
|
||||
/// Single char deletion.
|
||||
BY_DEL_CHAR,
|
||||
/// Character range (selection) deletion.
|
||||
BY_DEL_CHARS,
|
||||
/// Undo/redo.
|
||||
BY_UNDO_REDO,
|
||||
/// Single char insertion, previous character was inserted in previous position.
|
||||
CHANGE_BY_INS_CONSECUTIVE_CHAR,
|
||||
/// Single char removal, previous character was removed in previous position
|
||||
CHANGE_BY_DEL_CONSECUTIVE_CHAR,
|
||||
CHANGE_BY_CODE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Behavior event codes.
|
||||
pub enum BEHAVIOR_EVENTS
|
||||
{
|
||||
/// click on button
|
||||
BUTTON_CLICK = 0,
|
||||
/// mouse down or key down in button
|
||||
BUTTON_PRESS,
|
||||
/// checkbox/radio/slider changed its state/value
|
||||
BUTTON_STATE_CHANGED,
|
||||
/// before text change
|
||||
EDIT_VALUE_CHANGING,
|
||||
/// after text change
|
||||
EDIT_VALUE_CHANGED,
|
||||
/// selection in `<select>` changed
|
||||
SELECT_SELECTION_CHANGED,
|
||||
/// node in select expanded/collapsed, heTarget is the node
|
||||
SELECT_STATE_CHANGED,
|
||||
|
||||
/// request to show popup just received,
|
||||
/// here DOM of popup element can be modifed.
|
||||
POPUP_REQUEST,
|
||||
|
||||
/// popup element has been measured and ready to be shown on screen,
|
||||
/// here you can use functions like `ScrollToView`.
|
||||
POPUP_READY,
|
||||
|
||||
/// popup element is closed,
|
||||
/// here DOM of popup element can be modifed again - e.g. some items can be removed to free memory.
|
||||
POPUP_DISMISSED,
|
||||
|
||||
/// menu item activated by mouse hover or by keyboard,
|
||||
MENU_ITEM_ACTIVE,
|
||||
|
||||
/// menu item click,
|
||||
/// BEHAVIOR_EVENT_PARAMS structure layout
|
||||
/// BEHAVIOR_EVENT_PARAMS.cmd - MENU_ITEM_CLICK/MENU_ITEM_ACTIVE
|
||||
/// BEHAVIOR_EVENT_PARAMS.heTarget - owner(anchor) of the menu
|
||||
/// BEHAVIOR_EVENT_PARAMS.he - the menu item, presumably `<li>` element
|
||||
/// BEHAVIOR_EVENT_PARAMS.reason - BY_MOUSE_CLICK | BY_KEY_CLICK
|
||||
MENU_ITEM_CLICK,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// "right-click", BEHAVIOR_EVENT_PARAMS::he is current popup menu `HELEMENT` being processed or `NULL`.
|
||||
/// application can provide its own `HELEMENT` here (if it is `NULL`) or modify current menu element.
|
||||
CONTEXT_MENU_REQUEST = 0x10,
|
||||
|
||||
|
||||
/// broadcast notification, sent to all elements of some container being shown or hidden
|
||||
VISIUAL_STATUS_CHANGED,
|
||||
/// broadcast notification, sent to all elements of some container that got new value of `:disabled` state
|
||||
DISABLED_STATUS_CHANGED,
|
||||
|
||||
/// popup is about to be closed
|
||||
POPUP_DISMISSING,
|
||||
|
||||
/// content has been changed, is posted to the element that gets content changed, reason is combination of `CONTENT_CHANGE_BITS`.
|
||||
/// `target == NULL` means the window got new document and this event is dispatched only to the window.
|
||||
CONTENT_CHANGED = 0x15,
|
||||
|
||||
|
||||
/// generic click
|
||||
CLICK = 0x16,
|
||||
/// generic change
|
||||
CHANGE = 0x17,
|
||||
|
||||
/// media changed (screen resolution, number of displays, etc.)
|
||||
MEDIA_CHANGED = 0x18,
|
||||
/// input language has changed, data is iso lang-country string
|
||||
INPUT_LANGUAGE_CHANGED = 0x19,
|
||||
/// editable content has changed
|
||||
CONTENT_MODIFIED = 0x1A,
|
||||
/// a broadcast notification being posted to all elements of some container
|
||||
/// that changes its `:read-only` state.
|
||||
READONLY_STATUS_CHANGED = 0x1B,
|
||||
/// change in `aria-live="polite|assertive"`
|
||||
ARIA_LIVE_AREA_CHANGED = 0x1C,
|
||||
|
||||
// "grey" event codes - notfications from behaviors from this SDK
|
||||
/// hyperlink click
|
||||
HYPERLINK_CLICK = 0x80,
|
||||
|
||||
PASTE_TEXT = 0x8E,
|
||||
PASTE_HTML = 0x8F,
|
||||
|
||||
/// element was collapsed, so far only `behavior:tabs` is sending these two to the panels
|
||||
ELEMENT_COLLAPSED = 0x90,
|
||||
/// element was expanded,
|
||||
ELEMENT_EXPANDED,
|
||||
|
||||
/// activate (select) child,
|
||||
/// used, for example, by `accesskeys` behaviors to send activation request, e.g. tab on `behavior:tabs`.
|
||||
ACTIVATE_CHILD,
|
||||
|
||||
/// ui state changed, observers shall update their visual states.
|
||||
/// is sent, for example, by `behavior:richtext` when caret position/selection has changed.
|
||||
UI_STATE_CHANGED = 0x95,
|
||||
|
||||
|
||||
/// `behavior:form` detected submission event. `BEHAVIOR_EVENT_PARAMS::data` field contains data to be posted.
|
||||
/// `BEHAVIOR_EVENT_PARAMS::data` is of type `T_MAP` in this case key/value pairs of data that is about
|
||||
/// to be submitted. You can modify the data or discard submission by returning true from the handler.
|
||||
FORM_SUBMIT,
|
||||
|
||||
|
||||
/// `behavior:form` detected reset event (from `button type=reset`). `BEHAVIOR_EVENT_PARAMS::data` field contains data to be reset.
|
||||
/// `BEHAVIOR_EVENT_PARAMS::data` is of type `T_MAP` in this case key/value pairs of data that is about
|
||||
/// to be rest. You can modify the data or discard reset by returning true from the handler.
|
||||
FORM_RESET,
|
||||
|
||||
|
||||
|
||||
/// document in `behavior:frame` or root document is complete.
|
||||
DOCUMENT_COMPLETE,
|
||||
|
||||
/// requests to `behavior:history` (commands)
|
||||
HISTORY_PUSH,
|
||||
HISTORY_DROP,
|
||||
HISTORY_PRIOR,
|
||||
HISTORY_NEXT,
|
||||
/// `behavior:history` notification - history stack has changed
|
||||
HISTORY_STATE_CHANGED,
|
||||
|
||||
/// close popup request,
|
||||
CLOSE_POPUP,
|
||||
/// request tooltip, `evt.source` <- is the tooltip element.
|
||||
TOOLTIP_REQUEST,
|
||||
|
||||
/// animation started (`reason=1`) or ended(`reason=0`) on the element.
|
||||
ANIMATION = 0xA0,
|
||||
|
||||
/// document created, script namespace initialized. `target` -> the document
|
||||
DOCUMENT_CREATED = 0xC0,
|
||||
/// document is about to be closed, to cancel closing do: `evt.data = sciter::Value("cancel")`;
|
||||
DOCUMENT_CLOSE_REQUEST,
|
||||
/// last notification before document removal from the DOM
|
||||
DOCUMENT_CLOSE,
|
||||
/// document has got DOM structure, styles and behaviors of DOM elements. Script loading run is complete at this moment.
|
||||
DOCUMENT_READY,
|
||||
/// document just finished parsing - has got DOM structure. This event is generated before the `DOCUMENT_READY`.
|
||||
/// Since 4.0.3.
|
||||
DOCUMENT_PARSED = 0xC4,
|
||||
|
||||
/// `<video>` "ready" notification
|
||||
VIDEO_INITIALIZED = 0xD1,
|
||||
/// `<video>` playback started notification
|
||||
VIDEO_STARTED,
|
||||
/// `<video>` playback stoped/paused notification
|
||||
VIDEO_STOPPED,
|
||||
/// `<video>` request for frame source binding,
|
||||
/// If you want to provide your own video frames source for the given target `<video>` element do the following:
|
||||
///
|
||||
/// 1. Handle and consume this `VIDEO_BIND_RQ` request
|
||||
/// 2. You will receive second `VIDEO_BIND_RQ` request/event for the same `<video>` element
|
||||
/// but this time with the `reason` field set to an instance of `sciter::video_destination` interface.
|
||||
/// 3. `add_ref()` it and store it, for example, in a worker thread producing video frames.
|
||||
/// 4. call `sciter::video_destination::start_streaming(...)` providing needed parameters
|
||||
/// call `sciter::video_destination::render_frame(...)` as soon as they are available
|
||||
/// call `sciter::video_destination::stop_streaming()` to stop the rendering (a.k.a. end of movie reached)
|
||||
VIDEO_BIND_RQ,
|
||||
|
||||
|
||||
/// `behavior:pager` starts pagination
|
||||
PAGINATION_STARTS = 0xE0,
|
||||
/// `behavior:pager` paginated page no, reason -> page no
|
||||
PAGINATION_PAGE,
|
||||
/// `behavior:pager` end pagination, reason -> total pages
|
||||
PAGINATION_ENDS,
|
||||
|
||||
/// event with custom name.
|
||||
/// Since 4.2.8.
|
||||
CUSTOM = 0xF0,
|
||||
|
||||
/// SSX, delayed mount_component
|
||||
MOUNT_COMPONENT = 0xF1,
|
||||
|
||||
/// all custom event codes shall be greater than this number. All codes below this will be used
|
||||
/// solely by application - Sciter will not intrepret it and will do just dispatching.
|
||||
/// To send event notifications with these codes use `SciterSend`/`PostEvent` API.
|
||||
FIRST_APPLICATION_EVENT_CODE = 0x100,
|
||||
|
||||
}
|
||||
|
||||
|
||||
impl ::std::ops::BitOr for EVENT_GROUPS {
|
||||
type Output = EVENT_GROUPS;
|
||||
fn bitor(self, rhs: Self::Output) -> Self::Output {
|
||||
let rn = (self as UINT) | (rhs as UINT);
|
||||
unsafe { ::std::mem::transmute(rn) }
|
||||
}
|
||||
}
|
388
libs/rust-sciter/src/capi/scdef.rs
Normal file
388
libs/rust-sciter/src/capi/scdef.rs
Normal file
@ -0,0 +1,388 @@
|
||||
//! Common Sciter declarations.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scvalue::{VALUE};
|
||||
use capi::screquest::{HREQUEST};
|
||||
use capi::scdom::{HELEMENT};
|
||||
use capi::scapi::ISciterAPI;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
pub enum ID2D1RenderTarget {}
|
||||
pub enum ID2D1Factory {}
|
||||
pub enum IDWriteFactory {}
|
||||
pub enum IDXGISwapChain {}
|
||||
pub enum IDXGISurface {}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// `HostHandler::on_data_load()` result code.
|
||||
///
|
||||
/// This notification gives application a chance to override built-in loader and
|
||||
/// implement loading of resources in its own way (for example, images can be loaded from
|
||||
/// a database or other resource).
|
||||
pub enum LOAD_RESULT {
|
||||
/// Do the default loading if data is not set.
|
||||
LOAD_DEFAULT,
|
||||
/// Discard the request completely (data will not be loaded at the document).
|
||||
LOAD_DISCARD,
|
||||
/// Data will be delivered later by the host application.
|
||||
LOAD_DELAYED,
|
||||
/// You return this result to indicate that your (the host) application took or
|
||||
/// will take care about `HREQUEST` in your code completely.
|
||||
LOAD_MYSELF,
|
||||
}
|
||||
|
||||
/// Script runtime options.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum SCRIPT_RUNTIME_FEATURES
|
||||
{
|
||||
ALLOW_FILE_IO = 0x1,
|
||||
ALLOW_SOCKET_IO = 0x2,
|
||||
ALLOW_EVAL = 0x4,
|
||||
ALLOW_SYSINFO = 0x8,
|
||||
}
|
||||
|
||||
/// Sciter graphics rendering backend.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum GFX_LAYER
|
||||
{
|
||||
/// An auto-selected backend.
|
||||
AUTO = 0xFFFF,
|
||||
|
||||
/// Depends on OS: GDI, Cairo or CoreGraphics.
|
||||
CPU = 1,
|
||||
|
||||
/// A software rasterizer for Direct2D (Windows only).
|
||||
#[cfg(windows)]
|
||||
WARP = 2,
|
||||
|
||||
/// A hardware Direct2D mode (Windows only).
|
||||
#[cfg(windows)]
|
||||
D2D = 3,
|
||||
|
||||
/// Skia backend with CPU rasterization mode.
|
||||
SKIA_CPU = 4,
|
||||
|
||||
/// Skia backend with OpenGL rendering.
|
||||
SKIA_OPENGL = 5,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Various Sciter engine options (global or per-window).
|
||||
pub enum SCITER_RT_OPTIONS
|
||||
{
|
||||
/// value:TRUE - enable, value:FALSE - disable, enabled by default.
|
||||
SCITER_SMOOTH_SCROLL = 1,
|
||||
/// global; value: milliseconds, connection timeout of http client.
|
||||
SCITER_CONNECTION_TIMEOUT = 2,
|
||||
/// global; value: 0 - drop connection, 1 - use builtin dialog, 2 - accept connection silently.
|
||||
SCITER_HTTPS_ERROR = 3,
|
||||
/// value: 0 - system default, 1 - no smoothing, 2 - std smoothing, 3 - clear type.
|
||||
SCITER_FONT_SMOOTHING = 4,
|
||||
/// Windows Aero support, value:
|
||||
/// 0 - normal drawing,
|
||||
/// 1 - window has transparent background after calls `DwmExtendFrameIntoClientArea()` or `DwmEnableBlurBehindWindow()`.
|
||||
SCITER_TRANSPARENT_WINDOW = 6,
|
||||
/// global; value = LPCBYTE, json - GPU black list, see: gpu-blacklist.json resource.
|
||||
/// Note: is not used since Sciter 4.
|
||||
#[deprecated(since="4.0.1", note="This option isn't working since Sciter 4.0.1.1.")]
|
||||
SCITER_SET_GPU_BLACKLIST = 7,
|
||||
/// global or per-window; value - combination of [SCRIPT_RUNTIME_FEATURES](enum.SCRIPT_RUNTIME_FEATURES.html) flags.
|
||||
SCITER_SET_SCRIPT_RUNTIME_FEATURES = 8,
|
||||
/// global (must be called before any window creation); value - [GFX_LAYER](enum.GFX_LAYER.html).
|
||||
SCITER_SET_GFX_LAYER = 9,
|
||||
/// global or per-window; value - TRUE/FALSE
|
||||
SCITER_SET_DEBUG_MODE = 10,
|
||||
/// global; value - BOOL, TRUE - the engine will use "unisex" theme that is common for all platforms.
|
||||
/// That UX theme is not using OS primitives for rendering input elements.
|
||||
/// Use it if you want exactly the same (modulo fonts) look-n-feel on all platforms.
|
||||
SCITER_SET_UX_THEMING = 11,
|
||||
/// value - TRUE/FALSE - window uses per pixel alpha (e.g. `WS_EX_LAYERED`/`UpdateLayeredWindow()` window).
|
||||
SCITER_ALPHA_WINDOW = 12,
|
||||
/// global; value: UTF-8 encoded script source to be loaded into each view before any other script execution.
|
||||
SCITER_SET_INIT_SCRIPT = 13,
|
||||
/// per-window; value - TRUE/FALSE - window is main, will destroy all other dependent windows on close.
|
||||
SCITER_SET_MAIN_WINDOW = 14,
|
||||
/// global; value - max request length in megabytes (1024*1024 bytes).
|
||||
SCITER_SET_MAX_HTTP_DATA_LENGTH = 15,
|
||||
}
|
||||
|
||||
/// Window flags
|
||||
#[repr(C)]
|
||||
pub enum SCITER_CREATE_WINDOW_FLAGS {
|
||||
/// child window only, if this flag is set all other flags ignored.
|
||||
SW_CHILD = 1,
|
||||
/// toplevel window, has titlebar.
|
||||
SW_TITLEBAR = 1 << 1,
|
||||
/// has resizeable frame.
|
||||
SW_RESIZEABLE = 1 << 2,
|
||||
/// is tool window.
|
||||
SW_TOOL = 1 << 3,
|
||||
/// has minimize / maximize buttons.
|
||||
SW_CONTROLS = 1 << 4,
|
||||
/// glassy window - "Acrylic" on Windows and "Vibrant" on macOS.
|
||||
SW_GLASSY = 1 << 5,
|
||||
/// transparent window (e.g. `WS_EX_LAYERED` on Windows, macOS is supported too).
|
||||
SW_ALPHA = 1 << 6,
|
||||
/// main window of the app, will terminate the app on close.
|
||||
SW_MAIN = 1 << 7,
|
||||
/// the window is created as topmost window.
|
||||
SW_POPUP = 1 << 8,
|
||||
/// make this window inspector ready.
|
||||
SW_ENABLE_DEBUG = 1 << 9,
|
||||
/// it has its own script VM.
|
||||
SW_OWNS_VM = 1 << 10,
|
||||
}
|
||||
|
||||
impl Default for SCITER_CREATE_WINDOW_FLAGS {
|
||||
fn default() -> Self {
|
||||
SCITER_CREATE_WINDOW_FLAGS::SW_CHILD
|
||||
}
|
||||
}
|
||||
|
||||
/// Flags can be OR'ed as `SW_MAIN|SW_ALPHA`.
|
||||
impl ::std::ops::BitOr for SCITER_CREATE_WINDOW_FLAGS {
|
||||
type Output = SCITER_CREATE_WINDOW_FLAGS;
|
||||
fn bitor(self, rhs: Self::Output) -> Self::Output {
|
||||
let rn = (self as UINT) | (rhs as UINT);
|
||||
unsafe { ::std::mem::transmute(rn) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum SCITER_NOTIFICATION {
|
||||
SC_LOAD_DATA = 1,
|
||||
SC_DATA_LOADED = 2,
|
||||
SC_ATTACH_BEHAVIOR = 4,
|
||||
SC_ENGINE_DESTROYED = 5,
|
||||
SC_POSTED_NOTIFICATION = 6,
|
||||
SC_GRAPHICS_CRITICAL_FAILURE = 7,
|
||||
SC_KEYBOARD_REQUEST = 8,
|
||||
SC_INVALIDATE_RECT = 9,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// The type of a loaded resource.
|
||||
pub enum RESOURCE_TYPE {
|
||||
/// HTML document.
|
||||
HTML = 0,
|
||||
/// Image.
|
||||
IMAGE = 1,
|
||||
/// CSS.
|
||||
STYLE = 2,
|
||||
/// Mouse cursor image.
|
||||
CURSOR = 3,
|
||||
/// TIScript document.
|
||||
SCRIPT = 4,
|
||||
/// Any data.
|
||||
RAW = 5,
|
||||
/// Font.
|
||||
FONT,
|
||||
/// Sound (wav bytes).
|
||||
SOUND,
|
||||
}
|
||||
|
||||
/// The type of a loaded resource.
|
||||
pub type SCITER_RESOURCE_TYPE = RESOURCE_TYPE;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Notifies that Sciter is about to download a referred resource.
|
||||
pub struct SCN_LOAD_DATA
|
||||
{
|
||||
/// `SC_LOAD_DATA` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
|
||||
/// [in] Zero terminated string, fully qualified uri, for example, "http://server/folder/file.ext".
|
||||
pub uri: LPCWSTR,
|
||||
|
||||
/// [in,out] pointer to loaded data to return. If data exists in the cache then this field contain pointer to it.
|
||||
pub outData: LPCBYTE,
|
||||
/// [in,out] loaded data size to return.
|
||||
pub outDataSize: UINT,
|
||||
|
||||
/// [in] resource type category
|
||||
pub dataType: RESOURCE_TYPE,
|
||||
|
||||
/// [in] request handle that can be used with Sciter request API.
|
||||
pub request_id: HREQUEST,
|
||||
|
||||
/// [in] destination element for request.
|
||||
pub principal: HELEMENT,
|
||||
/// [in] source element for request.
|
||||
pub initiator: HELEMENT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// This notification indicates that external data (for example, image) download process has been completed.
|
||||
pub struct SCN_DATA_LOADED
|
||||
{
|
||||
/// `SC_DATA_LOADED` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
/// [in] zero terminated string, fully qualified uri, for example, "http://server/folder/file.ext".
|
||||
pub uri: LPCWSTR,
|
||||
/// [in] pointer to loaded data.
|
||||
pub data: LPCBYTE,
|
||||
/// [in] loaded data size (in bytes).
|
||||
pub dataSize: UINT,
|
||||
/// [in] resource type category
|
||||
pub dataType: RESOURCE_TYPE,
|
||||
/// Download status code:
|
||||
///
|
||||
/// * status = 0 and `dataSize == 0` - unknown error.
|
||||
/// * status = 100..505 - http response status, note: 200 - OK!
|
||||
/// * status > 12000 - wininet error code, see `ERROR_INTERNET_***` in wininet.h
|
||||
pub status: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// This notification is sent on parsing the document and while processing elements
|
||||
/// having non empty `behavior: ` style attribute value.
|
||||
pub struct SCN_ATTACH_BEHAVIOR
|
||||
{
|
||||
/// `SC_ATTACH_BEHAVIOR` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
|
||||
/// [in] target DOM element handle
|
||||
pub element: HELEMENT,
|
||||
/// [in] zero terminated string, string appears as value of CSS `behavior: ` attribute.
|
||||
pub name: LPCSTR,
|
||||
/// [out] pointer to ElementEventProc function.
|
||||
pub elementProc: ElementEventProc,
|
||||
/// [out] tag value, passed as is into pointer ElementEventProc function.
|
||||
pub elementTag: LPVOID,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// This notification is issued when keyboard needs to be shown –
|
||||
/// mobiles can show soft keyboard by handling it.
|
||||
pub struct SCN_KEYBOARD_REQUEST
|
||||
{
|
||||
/// `SC_KEYBOARD_REQUEST` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
|
||||
pub keyboard_mode: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// This notification is sent when a specific window area
|
||||
/// needs to be redrawn.
|
||||
pub struct SCN_INVALIDATE_RECT
|
||||
{
|
||||
/// `SC_INVALIDATE_RECT` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
|
||||
/// Coordinates of the invalidated area.
|
||||
pub invalid_rect: RECT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SCITER_CALLBACK_NOTIFICATION
|
||||
{
|
||||
pub code: UINT,
|
||||
pub hwnd: HWINDOW,
|
||||
}
|
||||
pub type LPSCITER_CALLBACK_NOTIFICATION = *mut SCITER_CALLBACK_NOTIFICATION;
|
||||
|
||||
pub type SciterHostCallback = extern "system" fn (pns: LPSCITER_CALLBACK_NOTIFICATION, callbackParam: LPVOID) -> UINT;
|
||||
|
||||
pub type SciterWindowDelegate = extern "system" fn (hwnd: HWINDOW, msg: UINT, wParam: WPARAM, lParam: LPARAM, pParam: LPVOID, handled: * mut BOOL) -> LRESULT;
|
||||
|
||||
pub type ElementEventProc = extern "system" fn (tag: LPVOID, he: HELEMENT, evtg: UINT, prms: LPVOID) -> BOOL;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Debug output categories.
|
||||
pub enum OUTPUT_SUBSYTEMS
|
||||
{
|
||||
/// html parser & runtime
|
||||
DOM = 0,
|
||||
/// csss! parser & runtime
|
||||
CSSS,
|
||||
/// css parser
|
||||
CSS,
|
||||
/// TIS parser & runtime
|
||||
TIS,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
#[allow(missing_docs)]
|
||||
/// Debug output severity.
|
||||
pub enum OUTPUT_SEVERITY
|
||||
{
|
||||
INFO,
|
||||
WARNING,
|
||||
ERROR,
|
||||
}
|
||||
|
||||
pub type DEBUG_OUTPUT_PROC = extern "system" fn (param: LPVOID, subsystem: OUTPUT_SUBSYTEMS, severity: OUTPUT_SEVERITY, text: LPCWSTR, text_length: UINT);
|
||||
|
||||
pub type LPCWSTR_RECEIVER = extern "system" fn (szstr: LPCWSTR, str_length: UINT, param: LPVOID);
|
||||
pub type LPCSTR_RECEIVER = extern "system" fn (szstr: LPCSTR, str_length: UINT, param: LPVOID);
|
||||
pub type LPCBYTE_RECEIVER = extern "system" fn (szstr: LPCBYTE, str_length: UINT, param: LPVOID);
|
||||
|
||||
pub type ELEMENT_BITMAP_RECEIVER = extern "system" fn (rgba: LPCBYTE, x: INT, y: INT, width: UINT, height: UINT, param: LPVOID);
|
||||
|
||||
pub type KeyValueCallback = extern "system" fn (param: LPVOID, pkey: *const VALUE, pval: *const VALUE) -> BOOL;
|
||||
|
||||
/// Signature of Sciter extension library.
|
||||
///
|
||||
/// * `api` - Sciter API to be used inside the extension.
|
||||
/// * `exported` - extension object, it can be [asset](https://sciter.com/developers/for-native-gui-programmers/sciter-object-model/),
|
||||
/// function, or other `sciter::Value` supported type.
|
||||
///
|
||||
/// Return `true` if the `exported` object was initialized.
|
||||
///
|
||||
/// The extension should be placed in the same folder as "sciter.dll"
|
||||
/// and export a `SciterLibraryInit` function:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use sciter::types::{BOOL, VALUE};
|
||||
/// use sciter::Value;
|
||||
///
|
||||
/// #[no_mangle]
|
||||
/// pub extern "system"
|
||||
/// fn SciterLibraryInit(api: &'static sciter::ISciterAPI, exported: &mut VALUE) -> BOOL
|
||||
/// {
|
||||
/// sciter::set_host_api(api);
|
||||
///
|
||||
/// unimplemented!("export some extension functions");
|
||||
///
|
||||
/// true as BOOL
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// In script such extension library can be imported as:
|
||||
///
|
||||
/// ```javascript
|
||||
/// const exported = include library "library-name";
|
||||
/// ```
|
||||
///
|
||||
/// See the [blog post](https://sciter.com/include-library-name-native-extensions/) for more details.
|
||||
///
|
||||
pub type SciterLibraryInit = extern "system" fn (api: &'static ISciterAPI, exported: &mut VALUE) -> BOOL;
|
233
libs/rust-sciter/src/capi/scdom.rs
Normal file
233
libs/rust-sciter/src/capi/scdom.rs
Normal file
@ -0,0 +1,233 @@
|
||||
//! DOM access methods, C interface.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
|
||||
MAKE_HANDLE!(#[doc = "Element native handle."] HELEMENT, _HELEMENT);
|
||||
MAKE_HANDLE!(#[doc = "Node native handle."] HNODE, _HNODE);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Type of the result value for Sciter DOM functions.
|
||||
pub enum SCDOM_RESULT {
|
||||
/// Function completed successfully.
|
||||
OK = 0,
|
||||
/// Invalid `HWINDOW`.
|
||||
INVALID_HWND = 1,
|
||||
/// Invalid `HELEMENT`.
|
||||
INVALID_HANDLE = 2,
|
||||
/// Attempt to use `HELEMENT` which is not attached to document.
|
||||
PASSIVE_HANDLE = 3,
|
||||
/// Parameter is invalid, e.g. pointer is null.
|
||||
INVALID_PARAMETER = 4,
|
||||
/// Operation failed, e.g. invalid html passed.
|
||||
OPERATION_FAILED = 5,
|
||||
/// Function completed successfully, but no result (e.g. no such attribute at element).
|
||||
OK_NOT_HANDLED = -1,
|
||||
}
|
||||
|
||||
impl std::error::Error for SCDOM_RESULT {}
|
||||
|
||||
impl std::fmt::Display for SCDOM_RESULT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// `dom::Element.set_html()` options.
|
||||
pub enum SET_ELEMENT_HTML
|
||||
{
|
||||
SIH_REPLACE_CONTENT = 0,
|
||||
SIH_INSERT_AT_START = 1,
|
||||
SIH_APPEND_AFTER_LAST = 2,
|
||||
SOH_REPLACE = 3,
|
||||
SOH_INSERT_BEFORE = 4,
|
||||
SOH_INSERT_AFTER = 5,
|
||||
}
|
||||
|
||||
/// Bounding rectangle of the element.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum ELEMENT_AREAS {
|
||||
|
||||
/// `or` this flag if you want to get Sciter window relative coordinates,
|
||||
/// otherwise it will use nearest windowed container e.g. popup window.
|
||||
ROOT_RELATIVE = 0x01,
|
||||
|
||||
/// `or` this flag if you want to get coordinates relative to the origin of element iself.
|
||||
SELF_RELATIVE = 0x02,
|
||||
|
||||
/// Position inside immediate container.
|
||||
CONTAINER_RELATIVE = 0x03,
|
||||
|
||||
/// Position relative to view - Sciter window.
|
||||
VIEW_RELATIVE = 0x04,
|
||||
|
||||
/// Content (inner) box.
|
||||
CONTENT_BOX = 0x00,
|
||||
|
||||
/// Content + paddings.
|
||||
PADDING_BOX = 0x10,
|
||||
|
||||
/// Content + paddings + border.
|
||||
BORDER_BOX = 0x20,
|
||||
|
||||
/// Content + paddings + border + margins.
|
||||
MARGIN_BOX = 0x30,
|
||||
|
||||
/// Relative to content origin - location of background image (if it set `no-repeat`).
|
||||
BACK_IMAGE_AREA = 0x40,
|
||||
|
||||
/// Relative to content origin - location of foreground image (if it set `no-repeat`).
|
||||
FORE_IMAGE_AREA = 0x50,
|
||||
|
||||
/// Scroll_area - scrollable area in content box.
|
||||
SCROLLABLE_AREA = 0x60,
|
||||
}
|
||||
|
||||
impl ELEMENT_AREAS {
|
||||
/// Size of content (i.e `(0, 0, width, height)`).
|
||||
pub fn self_content() -> u32 {
|
||||
ELEMENT_AREAS::SELF_RELATIVE as u32
|
||||
}
|
||||
|
||||
/// Size of rect (i.e `(left, top, width, height)`)
|
||||
pub fn self_rect() -> u32 {
|
||||
ELEMENT_AREAS::ROOT_RELATIVE as u32
|
||||
}
|
||||
}
|
||||
|
||||
/// Collection of states (runtime flags) of a DOM element.
|
||||
///
|
||||
/// They reflect CSS pseudo-classes that are used in selectors,
|
||||
/// e.g. `STATE_HOVER` is `:hover`, `STATE_ACTIVE` is `:active`, and so on.
|
||||
///
|
||||
/// Implements `|` and `&` bitwise operators.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum ELEMENT_STATE_BITS
|
||||
{
|
||||
/// Zero state.
|
||||
STATE_NONE = 0x00000000,
|
||||
|
||||
/// Element is a link.
|
||||
///
|
||||
/// E.g. `<a href`.
|
||||
STATE_LINK = 0x00000001,
|
||||
|
||||
/// Mouse over the element at the moment.
|
||||
STATE_HOVER = 0x00000002,
|
||||
/// Element is pressed.
|
||||
///
|
||||
/// Commonly used by `<button>` or `<a>` elements.
|
||||
STATE_ACTIVE = 0x00000004,
|
||||
/// Element is focused.
|
||||
STATE_FOCUS = 0x00000008,
|
||||
|
||||
/// Element was visited.
|
||||
///
|
||||
/// For example, a link that was clicked.
|
||||
STATE_VISITED = 0x00000010,
|
||||
/// Current (hot) item.
|
||||
STATE_CURRENT = 0x00000020,
|
||||
/// Element is checked (or selected).
|
||||
STATE_CHECKED = 0x00000040,
|
||||
/// Element is disabled.
|
||||
STATE_DISABLED = 0x00000080,
|
||||
/// Readonly input element.
|
||||
STATE_READONLY = 0x00000100,
|
||||
|
||||
/// Expanded state - e.g. nodes in tree view.
|
||||
///
|
||||
/// Mutually exclusive with `STATE_COLLAPSED`.
|
||||
STATE_EXPANDED = 0x00000200,
|
||||
|
||||
/// Collapsed state - e.g. nodes in tree view.
|
||||
///
|
||||
/// Mutually exclusive with `STATE_EXPANDED`.
|
||||
STATE_COLLAPSED = 0x00000400,
|
||||
|
||||
/// One of fore/back images was requested but is not delivered.
|
||||
STATE_INCOMPLETE = 0x00000800,
|
||||
/// Is animating currently.
|
||||
STATE_ANIMATING = 0x00001000,
|
||||
/// Will accept focus.
|
||||
STATE_FOCUSABLE = 0x00002000,
|
||||
|
||||
/// Anchor in selection (used with current in selects).
|
||||
STATE_ANCHOR = 0x00004000,
|
||||
/// This is a synthetic element - i.e. don't emit it's head/tail.
|
||||
STATE_SYNTHETIC = 0x00008000,
|
||||
/// A popup element is shown for this particular element.
|
||||
STATE_OWNS_POPUP = 0x00010000,
|
||||
|
||||
/// Focus gained by tab traversal.
|
||||
STATE_TABFOCUS = 0x00020000,
|
||||
|
||||
/// Element is empty.
|
||||
///
|
||||
/// i.e. the element has no text content nor children nodes.
|
||||
///
|
||||
/// If element has a behavior attached then the behavior is responsible for the value of this flag.
|
||||
STATE_EMPTY = 0x00040000,
|
||||
|
||||
/// Busy or loading.
|
||||
STATE_BUSY = 0x00080000,
|
||||
|
||||
/// Drag over the block that can accept it (so is a current drop target).
|
||||
///
|
||||
/// Flag is set for the drop target block.
|
||||
STATE_DRAG_OVER = 0x00100000,
|
||||
/// Active drop target.
|
||||
STATE_DROP_TARGET = 0x00200000,
|
||||
/// Dragging/moving - the flag is set for the moving block.
|
||||
STATE_MOVING = 0x00400000,
|
||||
/// Dragging/copying - the flag is set for the copying block.
|
||||
STATE_COPYING = 0x00800000,
|
||||
/// Element that is a drag source.
|
||||
STATE_DRAG_SOURCE = 0x01000000,
|
||||
/// Element is drop marker.
|
||||
STATE_DROP_MARKER = 0x02000000,
|
||||
|
||||
/// Close to `STATE_ACTIVE` but has wider life span.
|
||||
///
|
||||
/// E.g. in `MOUSE_UP` it is still on;
|
||||
/// so behavior can check it in `MOUSE_UP` to discover the `CLICK` condition.
|
||||
STATE_PRESSED = 0x04000000,
|
||||
|
||||
/// This element is out of flow.
|
||||
STATE_POPUP = 0x08000000,
|
||||
|
||||
/// The element or one of its containers has `dir=ltr` declared.
|
||||
STATE_IS_LTR = 0x10000000,
|
||||
/// The element or one of its containers has `dir=rtl` declared.
|
||||
STATE_IS_RTL = 0x20000000,
|
||||
|
||||
/// Element is ready (behavior has finished initialization).
|
||||
STATE_READY = 0x40000000,
|
||||
}
|
||||
|
||||
/// Flags can be OR'ed.
|
||||
impl ::std::ops::BitOr for ELEMENT_STATE_BITS {
|
||||
type Output = ELEMENT_STATE_BITS;
|
||||
fn bitor(self, rhs: Self::Output) -> Self::Output {
|
||||
let rn = (self as UINT) | (rhs as UINT);
|
||||
unsafe { ::std::mem::transmute(rn) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Flags can be AND'ed.
|
||||
impl ::std::ops::BitAnd for ELEMENT_STATE_BITS {
|
||||
type Output = ELEMENT_STATE_BITS;
|
||||
fn bitand(self, rhs: Self::Output) -> Self::Output {
|
||||
let rn = (self as UINT) & (rhs as UINT);
|
||||
unsafe { ::std::mem::transmute(rn) }
|
||||
}
|
||||
}
|
||||
|
||||
pub type SciterElementCallback = extern "system" fn (he: HELEMENT, param: LPVOID) -> BOOL;
|
||||
|
||||
pub type ELEMENT_COMPARATOR = extern "system" fn (he1: HELEMENT, he2: HELEMENT, param: LPVOID) -> INT;
|
353
libs/rust-sciter/src/capi/scgraphics.rs
Normal file
353
libs/rust-sciter/src/capi/scgraphics.rs
Normal file
@ -0,0 +1,353 @@
|
||||
//! Sciter's platform independent graphics interface.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::scdom::HELEMENT;
|
||||
use capi::sctypes::{BOOL, LPCBYTE, LPCWSTR, LPVOID, UINT};
|
||||
use capi::scvalue::VALUE;
|
||||
|
||||
MAKE_HANDLE!(#[doc = "Graphics native handle."] HGFX, _HGFX);
|
||||
MAKE_HANDLE!(#[doc = "Image native handle."] HIMG, _HIMG);
|
||||
MAKE_HANDLE!(#[doc = "Path native handle."] HPATH, _HPATH);
|
||||
MAKE_HANDLE!(#[doc = "Text native handle."] HTEXT, _HTEXT);
|
||||
|
||||
pub type SC_REAL = f32;
|
||||
pub type SC_POS = SC_REAL;
|
||||
pub type SC_DIM = SC_REAL;
|
||||
pub type SC_ANGLE = SC_REAL;
|
||||
|
||||
pub type SC_COLOR = u32;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// Type of the result value for Sciter Graphics functions.
|
||||
pub enum GRAPHIN_RESULT {
|
||||
/// E.g. not enough memory.
|
||||
PANIC = -1,
|
||||
/// Success.
|
||||
OK = 0,
|
||||
/// Bad parameter.
|
||||
BAD_PARAM = 1,
|
||||
/// Operation failed, e.g. `restore()` without `save()`.
|
||||
FAILURE = 2,
|
||||
/// Platform does not support the requested feature.
|
||||
NOTSUPPORTED = 3,
|
||||
}
|
||||
|
||||
impl std::error::Error for GRAPHIN_RESULT {}
|
||||
|
||||
impl std::fmt::Display for GRAPHIN_RESULT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Path drawing mode.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DRAW_PATH {
|
||||
/// Draw without outline line.
|
||||
FILL_ONLY = 1,
|
||||
/// Draw outline without fill.
|
||||
STROKE_ONLY = 2,
|
||||
/// Draw outlined and filled path.
|
||||
FILL_AND_STROKE = 3,
|
||||
}
|
||||
|
||||
/// Line drawing join mode.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum LINE_JOIN {
|
||||
/// Specifies a mitered join. This produces a sharp corner or a clipped corner,
|
||||
/// depending on whether the length of the miter exceeds the miter limit (`10.0`).
|
||||
MITER = 0,
|
||||
/// Specifies a circular join. This produces a smooth, circular arc between the lines.
|
||||
ROUND = 1,
|
||||
/// Specifies a beveled join. This produces a diagonal corner.
|
||||
BEVEL = 2,
|
||||
/// Specifies a mitered join. This produces a sharp corner or a beveled corner,
|
||||
/// depending on whether the length of the miter exceeds the miter limit (`10.0`).
|
||||
MITER_OR_BEVEL = 3,
|
||||
}
|
||||
|
||||
/// Line drawing cap mode.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum LINE_CAP {
|
||||
/// The ends of lines are squared off at the endpoints.
|
||||
BUTT = 0,
|
||||
/// The ends of lines are squared off by adding a box with an equal width
|
||||
/// and half the height of the line's thickness.
|
||||
SQUARE = 1,
|
||||
/// The ends of lines are rounded.
|
||||
ROUND = 2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum IMAGE_ENCODING {
|
||||
RAW, // [a,b,g,r,a,b,g,r,...] vector
|
||||
PNG,
|
||||
JPG,
|
||||
WEBP,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct SC_COLOR_STOP {
|
||||
pub color: SC_COLOR,
|
||||
pub offset: f32,
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct SciterGraphicsAPI {
|
||||
// image primitives
|
||||
pub imageCreate: extern "system" fn(poutImg: &mut HIMG, width: UINT, height: UINT, withAlpha: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
// construct image from B[n+0],G[n+1],R[n+2],A[n+3] data.
|
||||
// Size of pixmap data is pixmapWidth*pixmapHeight*4
|
||||
pub imageCreateFromPixmap:
|
||||
extern "system" fn(poutImg: &mut HIMG, pixmapWidth: UINT, pixmapHeight: UINT, withAlpha: BOOL, pixmap: LPCBYTE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageAddRef: extern "system" fn(himg: HIMG) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageRelease: extern "system" fn(himg: HIMG) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageGetInfo: extern "system" fn(himg: HIMG, width: &mut UINT, height: &mut UINT, usesAlpha: &mut BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageClear: extern "system" fn(himg: HIMG, byColor: SC_COLOR) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageLoad: extern "system" fn(bytes: LPCBYTE, num_bytes: UINT, pout_img: &mut HIMG) -> GRAPHIN_RESULT, // load png/jpeg/etc. image from stream of bytes
|
||||
|
||||
pub imageSave: extern "system" fn(himg: HIMG, pfn: ImageWriteFunction, prm: LPVOID, encoding: IMAGE_ENCODING, quality: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: graphics primitives and drawing operations
|
||||
|
||||
// create SC_COLOR value
|
||||
pub RGBA: extern "system" fn(red: UINT, green: UINT, blue: UINT, alpha: UINT) -> SC_COLOR,
|
||||
|
||||
pub gCreate: extern "system" fn(img: HIMG, pout_gfx: &mut HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gAddRef: extern "system" fn(gfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gRelease: extern "system" fn(gfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws line from x1,y1 to x2,y2 using current lineColor and lineGradient.
|
||||
pub gLine: extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws rectangle using current lineColor/lineGradient and fillColor/fillGradient with (optional) rounded corners.
|
||||
pub gRectangle: extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws rounded rectangle using current lineColor/lineGradient and fillColor/fillGradient with (optional) rounded corners.
|
||||
pub gRoundedRectangle: extern "system" fn(
|
||||
hgfx: HGFX,
|
||||
x1: SC_POS,
|
||||
y1: SC_POS,
|
||||
x2: SC_POS,
|
||||
y2: SC_POS,
|
||||
radii8: *const SC_DIM,
|
||||
) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws circle or ellipse using current lineColor/lineGradient and fillColor/fillGradient.
|
||||
pub gEllipse: extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, rx: SC_DIM, ry: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws closed arc using current lineColor/lineGradient and fillColor/fillGradient.
|
||||
pub gArc:
|
||||
extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, rx: SC_POS, ry: SC_POS, start: SC_ANGLE, sweep: SC_ANGLE) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws star.
|
||||
pub gStar: extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, r1: SC_DIM, r2: SC_DIM, start: SC_ANGLE, rays: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// Closed polygon.
|
||||
pub gPolygon: extern "system" fn(hgfx: HGFX, xy: *const SC_POS, num_points: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// Polyline.
|
||||
pub gPolyline: extern "system" fn(hgfx: HGFX, xy: *const SC_POS, num_points: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: Path operations
|
||||
pub pathCreate: extern "system" fn(path: &mut HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathAddRef: extern "system" fn(path: HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathRelease: extern "system" fn(path: HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathMoveTo: extern "system" fn(path: HPATH, x: SC_POS, y: SC_POS, relative: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathLineTo: extern "system" fn(path: HPATH, x: SC_POS, y: SC_POS, relative: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathArcTo: extern "system" fn(
|
||||
path: HPATH,
|
||||
x: SC_POS,
|
||||
y: SC_POS,
|
||||
angle: SC_ANGLE,
|
||||
rx: SC_DIM,
|
||||
ry: SC_DIM,
|
||||
is_large_arc: BOOL,
|
||||
clockwise: BOOL,
|
||||
relative: BOOL,
|
||||
) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathQuadraticCurveTo: extern "system" fn(path: HPATH, xc: SC_POS, yc: SC_POS, x: SC_POS, y: SC_POS, relative: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathBezierCurveTo:
|
||||
extern "system" fn(path: HPATH, xc1: SC_POS, yc1: SC_POS, xc2: SC_POS, yc2: SC_POS, x: SC_POS, y: SC_POS, relative: BOOL)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
pub pathClosePath: extern "system" fn(path: HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gDrawPath: extern "system" fn(hgfx: HGFX, path: HPATH, dpm: DRAW_PATH) -> GRAPHIN_RESULT,
|
||||
|
||||
// end of path opearations
|
||||
|
||||
// SECTION: affine tranformations:
|
||||
pub gRotate: extern "system" fn(hgfx: HGFX, radians: SC_ANGLE, cx: Option<&SC_POS>, cy: Option<&SC_POS>) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gTranslate: extern "system" fn(hgfx: HGFX, cx: SC_POS, cy: SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gScale: extern "system" fn(hgfx: HGFX, x: SC_DIM, y: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gSkew: extern "system" fn(hgfx: HGFX, dx: SC_DIM, dy: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
// all above in one shot
|
||||
pub gTransform:
|
||||
extern "system" fn(hgfx: HGFX, m11: SC_POS, m12: SC_POS, m21: SC_POS, m22: SC_POS, dx: SC_POS, dy: SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
// end of affine tranformations.
|
||||
|
||||
// SECTION: state save/restore
|
||||
pub gStateSave: extern "system" fn(hgfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gStateRestore: extern "system" fn(hgfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
// end of state save/restore
|
||||
|
||||
// SECTION: drawing attributes
|
||||
|
||||
// set line width for subsequent drawings.
|
||||
pub gLineWidth: extern "system" fn(hgfx: HGFX, width: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gLineJoin: extern "system" fn(hgfx: HGFX, join_type: LINE_JOIN) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gLineCap: extern "system" fn(hgfx: HGFX, cap_type: LINE_CAP) -> GRAPHIN_RESULT,
|
||||
|
||||
// SC_COLOR for solid lines/strokes
|
||||
pub gLineColor: extern "system" fn(hgfx: HGFX, color: SC_COLOR) -> GRAPHIN_RESULT,
|
||||
|
||||
// SC_COLOR for solid fills
|
||||
pub gFillColor: extern "system" fn(hgfx: HGFX, color: SC_COLOR) -> GRAPHIN_RESULT,
|
||||
|
||||
// setup parameters of linear gradient of lines.
|
||||
pub gLineGradientLinear:
|
||||
extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS, stops: *const SC_COLOR_STOP, nstops: UINT)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
// setup parameters of linear gradient of fills.
|
||||
pub gFillGradientLinear:
|
||||
extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS, stops: *const SC_COLOR_STOP, nstops: UINT)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
// setup parameters of line gradient radial fills.
|
||||
pub gLineGradientRadial:
|
||||
extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, rx: SC_DIM, ry: SC_DIM, stops: *const SC_COLOR_STOP, nstops: UINT)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
// setup parameters of gradient radial fills.
|
||||
pub gFillGradientRadial:
|
||||
extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, rx: SC_DIM, ry: SC_DIM, stops: *const SC_COLOR_STOP, nstops: UINT)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
pub gFillMode: extern "system" fn(hgfx: HGFX, even_odd: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: text
|
||||
|
||||
// create text layout for host element
|
||||
pub textCreateForElement: extern "system" fn(ptext: &mut HTEXT, text: LPCWSTR, textLength: UINT, he: HELEMENT, classNameOrNull: LPCWSTR) -> GRAPHIN_RESULT,
|
||||
|
||||
// create text layout using explicit style declaration
|
||||
pub textCreateForElementAndStyle:
|
||||
extern "system" fn(ptext: &mut HTEXT, text: LPCWSTR, textLength: UINT, he: HELEMENT, style: LPCWSTR, styleLength: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// since 4.1.10
|
||||
pub textAddRef: extern "system" fn(text: HTEXT) -> GRAPHIN_RESULT,
|
||||
|
||||
// since 4.1.10
|
||||
pub textRelease: extern "system" fn(text: HTEXT) -> GRAPHIN_RESULT,
|
||||
|
||||
pub textGetMetrics: extern "system" fn(
|
||||
text: HTEXT,
|
||||
minWidth: &mut SC_DIM,
|
||||
maxWidth: &mut SC_DIM,
|
||||
height: &mut SC_DIM,
|
||||
ascent: &mut SC_DIM,
|
||||
descent: &mut SC_DIM,
|
||||
nLines: &mut UINT,
|
||||
) -> GRAPHIN_RESULT,
|
||||
|
||||
pub textSetBox: extern "system" fn(text: HTEXT, width: SC_DIM, height: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
// draw text with position (1..9 on MUMPAD) at px,py
|
||||
// Ex: gDrawText(100,100,5) will draw text box with its center at 100,100 px
|
||||
pub gDrawText: extern "system" fn(hgfx: HGFX, text: HTEXT, px: SC_POS, py: SC_POS, position: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: image rendering
|
||||
|
||||
// draws img onto the graphics surface with current transformation applied (scale, rotation).
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub gDrawImage: extern "system" fn(
|
||||
hgfx: HGFX,
|
||||
himg: HIMG,
|
||||
x: SC_POS,
|
||||
y: SC_POS,
|
||||
w: Option<&SC_DIM>,
|
||||
h: Option<&SC_DIM>,
|
||||
ix: Option<&UINT>,
|
||||
iy: Option<&UINT>,
|
||||
iw: Option<&UINT>,
|
||||
ih: Option<&UINT>,
|
||||
opacity: Option<&f32>,
|
||||
) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: coordinate space
|
||||
pub gWorldToScreen: extern "system" fn(hgfx: HGFX, inout_x: &mut SC_POS, inout_y: &mut SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gScreenToWorld: extern "system" fn(hgfx: HGFX, inout_x: &mut SC_POS, inout_y: &mut SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: clipping
|
||||
pub gPushClipBox: extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS, opacity: f32) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gPushClipPath: extern "system" fn(hgfx: HGFX, hpath: HPATH, opacity: f32) -> GRAPHIN_RESULT,
|
||||
|
||||
// pop clip layer previously set by gPushClipBox or gPushClipPath
|
||||
pub gPopClip: extern "system" fn(hgfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
// image painter
|
||||
pub imagePaint: extern "system" fn(himg: HIMG, pPainter: ImagePaintFunction, prm: LPVOID) -> GRAPHIN_RESULT, // paint on image using graphics
|
||||
|
||||
// VALUE interface
|
||||
pub vWrapGfx: extern "system" fn(hgfx: HGFX, toValue: *mut VALUE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vWrapImage: extern "system" fn(himg: HIMG, toValue: *mut VALUE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vWrapPath: extern "system" fn(hpath: HPATH, toValue: *mut VALUE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vWrapText: extern "system" fn(htext: HTEXT, toValue: *mut VALUE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vUnWrapGfx: extern "system" fn(fromValue: *const VALUE, phgfx: &mut HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vUnWrapImage: extern "system" fn(fromValue: *const VALUE, phimg: &mut HIMG) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vUnWrapPath: extern "system" fn(fromValue: *const VALUE, phpath: &mut HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vUnWrapText: extern "system" fn(fromValue: *const VALUE, phtext: &mut HTEXT) -> GRAPHIN_RESULT,
|
||||
|
||||
// since 4.4.3.20
|
||||
pub gFlush: extern "system" fn(hgfx: HGFX) -> GRAPHIN_RESULT,
|
||||
}
|
||||
|
||||
pub type ImageWriteFunction = extern "system" fn(prm: LPVOID, data: LPCBYTE, data_length: UINT);
|
||||
pub type ImagePaintFunction = extern "system" fn(prm: LPVOID, hgfx: HGFX, width: UINT, height: UINT);
|
118
libs/rust-sciter/src/capi/schandler.rs
Normal file
118
libs/rust-sciter/src/capi/schandler.rs
Normal file
@ -0,0 +1,118 @@
|
||||
//! Native handler wrappers.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::{LPCVOID, LPVOID};
|
||||
|
||||
type Opaque = LPCVOID;
|
||||
|
||||
|
||||
/// Native wrapper for handlers which can be passed to foreign functions.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct NativeHandler {
|
||||
// pointer to handler
|
||||
handler: Opaque,
|
||||
|
||||
// pointer to handler destructor
|
||||
dtor: fn(param: Opaque),
|
||||
}
|
||||
|
||||
impl Drop for NativeHandler {
|
||||
fn drop(&mut self) {
|
||||
if !self.handler.is_null() {
|
||||
(self.dtor)(self.handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for NativeHandler {
|
||||
fn default() -> Self {
|
||||
NativeHandler { handler: ::std::ptr::null(), dtor: NativeHandler::drop_it::<i32> }
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeHandler {
|
||||
|
||||
/// Construct boxed wrapper from handler object.
|
||||
pub fn from<T>(handler: T) -> NativeHandler {
|
||||
let boxed = Box::new(handler);
|
||||
let ptr = Box::into_raw(boxed);
|
||||
let dtor = NativeHandler::drop_it::<T>;
|
||||
return NativeHandler { handler: ptr as Opaque, dtor: dtor };
|
||||
}
|
||||
|
||||
/// Return a native pointer to handler wrapper.
|
||||
pub fn as_ptr(&self) -> LPCVOID {
|
||||
self.handler as LPCVOID
|
||||
}
|
||||
|
||||
/// Return a native pointer to handler wrapper.
|
||||
pub fn as_mut_ptr(&self) -> LPVOID {
|
||||
self.handler as LPVOID
|
||||
}
|
||||
|
||||
/// Access handler by reference.
|
||||
pub fn as_ref<T>(&self) -> &T {
|
||||
let pobj = self.handler as *const T;
|
||||
let boxed = unsafe { &*pobj };
|
||||
return boxed;
|
||||
}
|
||||
|
||||
/// Access handler by mutable reference.
|
||||
pub fn as_mut<T>(&mut self) -> &mut T {
|
||||
let pobj = self.handler as *mut T;
|
||||
let boxed = unsafe { &mut *pobj };
|
||||
return boxed;
|
||||
}
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
pub fn get_data<T>(ptr: &LPVOID) -> &mut T {
|
||||
assert!(!ptr.is_null());
|
||||
let obj = *ptr as *mut T;
|
||||
unsafe { &mut *obj}
|
||||
}
|
||||
|
||||
// Call destructor of handler.
|
||||
fn drop_it<T>(param: Opaque) {
|
||||
// reconstruct pointer to Box
|
||||
let pobj = param as *mut T;
|
||||
if !pobj.is_null() {
|
||||
// and drop it
|
||||
unsafe { Box::from_raw(pobj) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::NativeHandler;
|
||||
|
||||
struct Handler {
|
||||
pub i: i32,
|
||||
}
|
||||
|
||||
impl Drop for Handler {
|
||||
fn drop(&mut self) {
|
||||
println!("Handler::drop");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[test]
|
||||
fn test1() {
|
||||
{
|
||||
println!("\ncreate");
|
||||
let h = Handler { i: 7 };
|
||||
let p = NativeHandler::from(h);
|
||||
|
||||
println!("handler i {:?}", p.as_ref::<Handler>().i);
|
||||
println!("quit");
|
||||
}
|
||||
println!("done.");
|
||||
|
||||
// assert!(false);
|
||||
}
|
||||
|
||||
}
|
462
libs/rust-sciter/src/capi/scmsg.rs
Normal file
462
libs/rust-sciter/src/capi/scmsg.rs
Normal file
@ -0,0 +1,462 @@
|
||||
//! Sciter.Lite interface.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::{GFX_LAYER, ELEMENT_BITMAP_RECEIVER};
|
||||
use capi::scdom::HELEMENT;
|
||||
use capi::scbehavior::{MOUSE_BUTTONS, MOUSE_EVENTS, KEY_EVENTS};
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum SCITER_X_MSG_CODE
|
||||
{
|
||||
SXM_CREATE = 0,
|
||||
SXM_DESTROY = 1,
|
||||
SXM_SIZE = 2,
|
||||
SXM_PAINT = 3,
|
||||
SXM_RESOLUTION = 4,
|
||||
SXM_HEARTBIT = 5,
|
||||
SXM_MOUSE = 6,
|
||||
SXM_KEY = 7,
|
||||
SXM_FOCUS = 8,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Common header of message structures passed to `SciterProcX`.
|
||||
pub struct SCITER_X_MSG
|
||||
{
|
||||
pub msg: SCITER_X_MSG_CODE,
|
||||
}
|
||||
|
||||
impl From<SCITER_X_MSG_CODE> for SCITER_X_MSG {
|
||||
fn from(code: SCITER_X_MSG_CODE) -> Self {
|
||||
Self { msg: code }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to create the specific Sciter backend.
|
||||
pub struct SCITER_X_MSG_CREATE
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
pub backend: GFX_LAYER,
|
||||
pub transparent: BOOL,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to destroy the current Sciter backend.
|
||||
pub struct SCITER_X_MSG_DESTROY
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about view resize.
|
||||
pub struct SCITER_X_MSG_SIZE
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
pub width: UINT,
|
||||
pub height: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about screen resolution change.
|
||||
pub struct SCITER_X_MSG_RESOLUTION
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
/// Pixels per inch.
|
||||
pub ppi: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about mouse input.
|
||||
pub struct SCITER_X_MSG_MOUSE
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
pub event: MOUSE_EVENTS,
|
||||
pub button: MOUSE_BUTTONS,
|
||||
pub modifiers: UINT,
|
||||
pub pos: POINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about keyboard input.
|
||||
pub struct SCITER_X_MSG_KEY
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
pub event: KEY_EVENTS,
|
||||
pub code: UINT,
|
||||
pub modifiers: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about window focus change.
|
||||
pub struct SCITER_X_MSG_FOCUS
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
pub enter: BOOL,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Give Sciter a chance to process animations, timers and other timed things.
|
||||
pub struct SCITER_X_MSG_HEARTBIT
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
/// Absolute time in milliseconds.
|
||||
pub time: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// `SCITER_X_MSG_PAINT` rendering targets.
|
||||
pub enum SCITER_PAINT_TARGET_TYPE
|
||||
{
|
||||
/// Default target - OpenGL window surface.
|
||||
SPT_DEFAULT = 0,
|
||||
|
||||
/// Bitmap target.
|
||||
SPT_RECEIVER = 1,
|
||||
|
||||
/// `IDXGISurface` target (since 4.4.3.27).
|
||||
SPT_SURFACE = 2,
|
||||
}
|
||||
|
||||
/// Message to paint view to the provided target (HDC or callback).
|
||||
#[repr(C)]
|
||||
pub struct SCITER_X_MSG_PAINT
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
pub element: HELEMENT,
|
||||
pub isFore: BOOL,
|
||||
pub targetType: SCITER_PAINT_TARGET_TYPE,
|
||||
|
||||
// union {
|
||||
// HDC or LPVOID
|
||||
pub context: LPVOID,
|
||||
pub callback: Option<ELEMENT_BITMAP_RECEIVER>,
|
||||
// }
|
||||
}
|
||||
|
||||
/// Sciter.Lite key codes.
|
||||
///
|
||||
/// The table matches the [GLFW keyboard keys](https://www.glfw.org/docs/3.3/group__keys.html).
|
||||
pub mod key_codes
|
||||
{
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// The same keys, but wrapped as a enum.
|
||||
pub enum KEYBOARD_CODES {
|
||||
KB_SPACE = 32,
|
||||
KB_APOSTROPHE = 39, /* ' */
|
||||
KB_COMMA = 44, /* , */
|
||||
// KB_QUOTE = KB_COMMA,
|
||||
KB_MINUS = 45, /* - */
|
||||
KB_PERIOD = 46, /* . */
|
||||
KB_SLASH = 47, /* / */
|
||||
KB_0 = 48,
|
||||
KB_1 = 49,
|
||||
KB_2 = 50,
|
||||
KB_3 = 51,
|
||||
KB_4 = 52,
|
||||
KB_5 = 53,
|
||||
KB_6 = 54,
|
||||
KB_7 = 55,
|
||||
KB_8 = 56,
|
||||
KB_9 = 57,
|
||||
KB_SEMICOLON = 59, /* ; */
|
||||
KB_EQUAL = 61, /* = */
|
||||
KB_A = 65,
|
||||
KB_B = 66,
|
||||
KB_C = 67,
|
||||
KB_D = 68,
|
||||
KB_E = 69,
|
||||
KB_F = 70,
|
||||
KB_G = 71,
|
||||
KB_H = 72,
|
||||
KB_I = 73,
|
||||
KB_J = 74,
|
||||
KB_K = 75,
|
||||
KB_L = 76,
|
||||
KB_M = 77,
|
||||
KB_N = 78,
|
||||
KB_O = 79,
|
||||
KB_P = 80,
|
||||
KB_Q = 81,
|
||||
KB_R = 82,
|
||||
KB_S = 83,
|
||||
KB_T = 84,
|
||||
KB_U = 85,
|
||||
KB_V = 86,
|
||||
KB_W = 87,
|
||||
KB_X = 88,
|
||||
KB_Y = 89,
|
||||
KB_Z = 90,
|
||||
KB_LEFT_BRACKET = 91, /* [ */
|
||||
// KB_LEFTBRACKET = KB_LEFT_BRACKET,
|
||||
KB_BACKSLASH = 92, /* \ */
|
||||
KB_RIGHT_BRACKET = 93, /* ] */
|
||||
// KB_RIGHTBRACKET = KB_RIGHT_BRACKET,
|
||||
KB_GRAVE_ACCENT = 96, /* ` */
|
||||
KB_WORLD_1 = 161, /* non-US #1 */
|
||||
// KB_DOT = KB_WORLD_1,
|
||||
KB_WORLD_2 = 162, /* non-US #2 */
|
||||
|
||||
/* Function keys */
|
||||
KB_ESCAPE = 256,
|
||||
KB_ENTER = 257,
|
||||
// KB_RETURN = KB_ENTER,
|
||||
KB_TAB = 258,
|
||||
KB_BACKSPACE = 259,
|
||||
// KB_BACK = KB_BACKSPACE,
|
||||
KB_INSERT = 260,
|
||||
KB_DELETE = 261,
|
||||
KB_RIGHT = 262,
|
||||
KB_LEFT = 263,
|
||||
KB_DOWN = 264,
|
||||
KB_UP = 265,
|
||||
KB_PAGE_UP = 266,
|
||||
// KB_PRIOR = KB_PAGE_UP,
|
||||
KB_PAGE_DOWN = 267,
|
||||
// KB_NEXT = KB_PAGE_DOWN,
|
||||
KB_HOME = 268,
|
||||
KB_END = 269,
|
||||
KB_CAPS_LOCK = 280,
|
||||
// KB_CAPITAL = KB_CAPS_LOCK,
|
||||
KB_SCROLL_LOCK = 281,
|
||||
// KB_SCROLL = KB_SCROLL_LOCK,
|
||||
KB_NUM_LOCK = 282,
|
||||
// KB_NUMLOCK = KB_NUM_LOCK,
|
||||
KB_PRINT_SCREEN = 283,
|
||||
KB_PAUSE = 284,
|
||||
KB_F1 = 290,
|
||||
KB_F2 = 291,
|
||||
KB_F3 = 292,
|
||||
KB_F4 = 293,
|
||||
KB_F5 = 294,
|
||||
KB_F6 = 295,
|
||||
KB_F7 = 296,
|
||||
KB_F8 = 297,
|
||||
KB_F9 = 298,
|
||||
KB_F10 = 299,
|
||||
KB_F11 = 300,
|
||||
KB_F12 = 301,
|
||||
KB_F13 = 302,
|
||||
KB_F14 = 303,
|
||||
KB_F15 = 304,
|
||||
KB_F16 = 305,
|
||||
KB_F17 = 306,
|
||||
KB_F18 = 307,
|
||||
KB_F19 = 308,
|
||||
KB_F20 = 309,
|
||||
KB_F21 = 310,
|
||||
KB_F22 = 311,
|
||||
KB_F23 = 312,
|
||||
KB_F24 = 313,
|
||||
KB_F25 = 314,
|
||||
KB_NUMPAD0 = 320,
|
||||
KB_NUMPAD1 = 321,
|
||||
KB_NUMPAD2 = 322,
|
||||
KB_NUMPAD3 = 323,
|
||||
KB_NUMPAD4 = 324,
|
||||
KB_NUMPAD5 = 325,
|
||||
KB_NUMPAD6 = 326,
|
||||
KB_NUMPAD7 = 327,
|
||||
KB_NUMPAD8 = 328,
|
||||
KB_NUMPAD9 = 329,
|
||||
KB_NUMPAD_DECIMAL = 330,
|
||||
// KB_DECIMAL = KB_NUMPAD_DECIMAL, KB_SEPARATOR = KB_DECIMAL,
|
||||
KB_NUMPAD_DIVIDE = 331,
|
||||
// KB_DIVIDE = KB_NUMPAD_DIVIDE,
|
||||
KB_NUMPAD_MULTIPLY = 332,
|
||||
// KB_MULTIPLY = KB_NUMPAD_MULTIPLY,
|
||||
KB_NUMPAD_SUBTRACT = 333,
|
||||
// KB_SUBTRACT = KB_NUMPAD_SUBTRACT,
|
||||
KB_NUMPAD_ADD = 334,
|
||||
// KB_ADD = KB_NUMPAD_ADD, KB_PLUS = KB_ADD,
|
||||
KB_NUMPAD_ENTER = 335,
|
||||
KB_NUMPAD_EQUAL = 336,
|
||||
KB_LEFT_SHIFT = 340,
|
||||
// KB_SHIFT = KB_LEFT_SHIFT,
|
||||
KB_LEFT_CONTROL = 341,
|
||||
// KB_CONTROL = KB_LEFT_CONTROL, KB_SHORTCUT = KB_CONTROL,
|
||||
KB_LEFT_ALT = 342,
|
||||
KB_LEFT_SUPER = 343,
|
||||
KB_RIGHT_SHIFT = 344,
|
||||
KB_RIGHT_CONTROL = 345,
|
||||
KB_RIGHT_ALT = 346,
|
||||
KB_RIGHT_SUPER = 347,
|
||||
KB_MENU = 348,
|
||||
}
|
||||
|
||||
pub const KB_SPACE : u32 = 32;
|
||||
pub const KB_APOSTROPHE : u32 = 39; /* ' */
|
||||
pub const KB_COMMA : u32 = 44; /* , */
|
||||
pub const KB_QUOTE : u32 = KB_COMMA;
|
||||
pub const KB_MINUS : u32 = 45; /* - */
|
||||
pub const KB_PERIOD : u32 = 46; /* . */
|
||||
pub const KB_SLASH : u32 = 47; /* / */
|
||||
|
||||
pub const KB_0 : u32 = 48;
|
||||
pub const KB_1 : u32 = 49;
|
||||
pub const KB_2 : u32 = 50;
|
||||
pub const KB_3 : u32 = 51;
|
||||
pub const KB_4 : u32 = 52;
|
||||
pub const KB_5 : u32 = 53;
|
||||
pub const KB_6 : u32 = 54;
|
||||
pub const KB_7 : u32 = 55;
|
||||
pub const KB_8 : u32 = 56;
|
||||
pub const KB_9 : u32 = 57;
|
||||
|
||||
pub const KB_SEMICOLON : u32 = 59; /* ; */
|
||||
pub const KB_EQUAL : u32 = 61; /* = */
|
||||
|
||||
pub const KB_A : u32 = 65;
|
||||
pub const KB_B : u32 = 66;
|
||||
pub const KB_C : u32 = 67;
|
||||
pub const KB_D : u32 = 68;
|
||||
pub const KB_E : u32 = 69;
|
||||
pub const KB_F : u32 = 70;
|
||||
pub const KB_G : u32 = 71;
|
||||
pub const KB_H : u32 = 72;
|
||||
pub const KB_I : u32 = 73;
|
||||
pub const KB_J : u32 = 74;
|
||||
pub const KB_K : u32 = 75;
|
||||
pub const KB_L : u32 = 76;
|
||||
pub const KB_M : u32 = 77;
|
||||
pub const KB_N : u32 = 78;
|
||||
pub const KB_O : u32 = 79;
|
||||
pub const KB_P : u32 = 80;
|
||||
pub const KB_Q : u32 = 81;
|
||||
pub const KB_R : u32 = 82;
|
||||
pub const KB_S : u32 = 83;
|
||||
pub const KB_T : u32 = 84;
|
||||
pub const KB_U : u32 = 85;
|
||||
pub const KB_V : u32 = 86;
|
||||
pub const KB_W : u32 = 87;
|
||||
pub const KB_X : u32 = 88;
|
||||
pub const KB_Y : u32 = 89;
|
||||
pub const KB_Z : u32 = 90;
|
||||
|
||||
pub const KB_LEFT_BRACKET : u32 = 91; /* [ */
|
||||
pub const KB_LEFTBRACKET : u32 = KB_LEFT_BRACKET;
|
||||
pub const KB_BACKSLASH : u32 = 92; /* \ */
|
||||
pub const KB_RIGHT_BRACKET : u32 = 93; /* ] */
|
||||
pub const KB_RIGHTBRACKET : u32 = KB_RIGHT_BRACKET;
|
||||
pub const KB_GRAVE_ACCENT : u32 = 96; /* ` */
|
||||
pub const KB_WORLD_1 : u32 = 161; /* non-US #1 */
|
||||
pub const KB_DOT : u32 = KB_WORLD_1;
|
||||
pub const KB_WORLD_2 : u32 = 162; /* non-US #2 */
|
||||
|
||||
/* Function keys */
|
||||
pub const KB_ESCAPE : u32 = 256;
|
||||
pub const KB_ENTER : u32 = 257;
|
||||
pub const KB_RETURN : u32 = KB_ENTER;
|
||||
pub const KB_TAB : u32 = 258;
|
||||
pub const KB_BACKSPACE : u32 = 259;
|
||||
pub const KB_BACK : u32 = KB_BACKSPACE;
|
||||
pub const KB_INSERT : u32 = 260;
|
||||
pub const KB_DELETE : u32 = 261;
|
||||
pub const KB_RIGHT : u32 = 262;
|
||||
pub const KB_LEFT : u32 = 263;
|
||||
pub const KB_DOWN : u32 = 264;
|
||||
pub const KB_UP : u32 = 265;
|
||||
pub const KB_PAGE_UP : u32 = 266;
|
||||
pub const KB_PRIOR : u32 = KB_PAGE_UP;
|
||||
pub const KB_PAGE_DOWN : u32 = 267;
|
||||
pub const KB_NEXT : u32 = KB_PAGE_DOWN;
|
||||
pub const KB_HOME : u32 = 268;
|
||||
pub const KB_END : u32 = 269;
|
||||
pub const KB_CAPS_LOCK : u32 = 280;
|
||||
pub const KB_CAPITAL : u32 = KB_CAPS_LOCK;
|
||||
pub const KB_SCROLL_LOCK : u32 = 281;
|
||||
pub const KB_SCROLL : u32 = KB_SCROLL_LOCK;
|
||||
pub const KB_NUM_LOCK : u32 = 282;
|
||||
pub const KB_NUMLOCK : u32 = KB_NUM_LOCK;
|
||||
pub const KB_PRINT_SCREEN : u32 = 283;
|
||||
pub const KB_PAUSE : u32 = 284;
|
||||
|
||||
pub const KB_F1 : u32 = 290;
|
||||
pub const KB_F2 : u32 = 291;
|
||||
pub const KB_F3 : u32 = 292;
|
||||
pub const KB_F4 : u32 = 293;
|
||||
pub const KB_F5 : u32 = 294;
|
||||
pub const KB_F6 : u32 = 295;
|
||||
pub const KB_F7 : u32 = 296;
|
||||
pub const KB_F8 : u32 = 297;
|
||||
pub const KB_F9 : u32 = 298;
|
||||
pub const KB_F10 : u32 = 299;
|
||||
pub const KB_F11 : u32 = 300;
|
||||
pub const KB_F12 : u32 = 301;
|
||||
pub const KB_F13 : u32 = 302;
|
||||
pub const KB_F14 : u32 = 303;
|
||||
pub const KB_F15 : u32 = 304;
|
||||
pub const KB_F16 : u32 = 305;
|
||||
pub const KB_F17 : u32 = 306;
|
||||
pub const KB_F18 : u32 = 307;
|
||||
pub const KB_F19 : u32 = 308;
|
||||
pub const KB_F20 : u32 = 309;
|
||||
pub const KB_F21 : u32 = 310;
|
||||
pub const KB_F22 : u32 = 311;
|
||||
pub const KB_F23 : u32 = 312;
|
||||
pub const KB_F24 : u32 = 313;
|
||||
pub const KB_F25 : u32 = 314;
|
||||
|
||||
pub const KB_NUMPAD0 : u32 = 320;
|
||||
pub const KB_NUMPAD1 : u32 = 321;
|
||||
pub const KB_NUMPAD2 : u32 = 322;
|
||||
pub const KB_NUMPAD3 : u32 = 323;
|
||||
pub const KB_NUMPAD4 : u32 = 324;
|
||||
pub const KB_NUMPAD5 : u32 = 325;
|
||||
pub const KB_NUMPAD6 : u32 = 326;
|
||||
pub const KB_NUMPAD7 : u32 = 327;
|
||||
pub const KB_NUMPAD8 : u32 = 328;
|
||||
pub const KB_NUMPAD9 : u32 = 329;
|
||||
|
||||
pub const KB_NUMPAD_DECIMAL : u32 = 330;
|
||||
pub const KB_DECIMAL : u32 = KB_NUMPAD_DECIMAL;
|
||||
pub const KB_SEPARATOR : u32 = KB_DECIMAL;
|
||||
pub const KB_NUMPAD_DIVIDE : u32 = 331;
|
||||
pub const KB_DIVIDE : u32 = KB_NUMPAD_DIVIDE;
|
||||
pub const KB_NUMPAD_MULTIPLY : u32 = 332;
|
||||
pub const KB_MULTIPLY : u32 = KB_NUMPAD_MULTIPLY;
|
||||
pub const KB_NUMPAD_SUBTRACT : u32 = 333;
|
||||
pub const KB_SUBTRACT : u32 = KB_NUMPAD_SUBTRACT;
|
||||
pub const KB_NUMPAD_ADD : u32 = 334;
|
||||
pub const KB_ADD : u32 = KB_NUMPAD_ADD;
|
||||
pub const KB_PLUS : u32 = KB_ADD;
|
||||
pub const KB_NUMPAD_ENTER : u32 = 335;
|
||||
pub const KB_NUMPAD_EQUAL : u32 = 336;
|
||||
|
||||
pub const KB_LEFT_SHIFT : u32 = 340;
|
||||
pub const KB_SHIFT : u32 = KB_LEFT_SHIFT;
|
||||
pub const KB_LEFT_CONTROL : u32 = 341;
|
||||
pub const KB_CONTROL : u32 = KB_LEFT_CONTROL;
|
||||
pub const KB_SHORTCUT : u32 = KB_CONTROL;
|
||||
pub const KB_LEFT_ALT : u32 = 342;
|
||||
pub const KB_LEFT_SUPER : u32 = 343;
|
||||
pub const KB_RIGHT_SHIFT : u32 = 344;
|
||||
pub const KB_RIGHT_CONTROL : u32 = 345;
|
||||
pub const KB_RIGHT_ALT : u32 = 346;
|
||||
pub const KB_RIGHT_SUPER : u32 = 347;
|
||||
pub const KB_MENU : u32 = 348;
|
||||
}
|
223
libs/rust-sciter/src/capi/scom.rs
Normal file
223
libs/rust-sciter/src/capi/scom.rs
Normal file
@ -0,0 +1,223 @@
|
||||
/*! Sciter Object Model (SOM passport), native C interface.
|
||||
|
||||
See https://sciter.com/native-code-exposure-to-script/
|
||||
and https://sciter.com/developers/for-native-gui-programmers/sciter-object-model/.
|
||||
|
||||
*/
|
||||
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scvalue::VALUE;
|
||||
|
||||
/// An atom value that uniquely identifies the name being registered.
|
||||
pub type som_atom_t = u64;
|
||||
|
||||
|
||||
/// `som_asset_t` is a structure that a custom native object must be derived from.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct som_asset_t {
|
||||
pub(crate) isa: &'static som_asset_class_t,
|
||||
}
|
||||
|
||||
impl som_asset_t {
|
||||
pub(crate) fn get_passport(&self) -> *const som_passport_t {
|
||||
(self.isa.get_passport)(self as *const _ as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Is a pack of 4 pointers to functions that define the life time of an asset.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct som_asset_class_t {
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(thing: *mut som_asset_t) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(thing: *mut som_asset_t) -> i32,
|
||||
|
||||
/// Retrieves a pointer to a supported interface of an object.
|
||||
pub get_interface: extern "C" fn(thing: *mut som_asset_t, name: LPCSTR, out: *mut *mut som_asset_t) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut som_asset_t) -> *const som_passport_t,
|
||||
}
|
||||
|
||||
|
||||
/// Defines properties and methods of an asset.
|
||||
#[repr(C)]
|
||||
pub struct som_passport_t {
|
||||
/// Flags of an asset, see [`som_passport_flags`](enum.som_passport_flags.html).
|
||||
pub flags: u64,
|
||||
|
||||
/// The name of the class (asset type).
|
||||
pub name: som_atom_t,
|
||||
|
||||
/// Properties: `asset.prop`.
|
||||
///
|
||||
/// Must be a pointer to an array of structures:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use sciter::om::*;
|
||||
/// let mut pst = Box::new(som_passport_t::default());
|
||||
///
|
||||
/// type ObjectProps = [som_property_def_t; 2];
|
||||
/// let mut props = Box::new(ObjectProps::default());
|
||||
///
|
||||
/// let mut prop1 = &mut props[0];
|
||||
/// prop1.name = atom("age");
|
||||
///
|
||||
/// let mut prop2 = &mut props[1];
|
||||
/// prop2.name = atom("name");
|
||||
///
|
||||
/// pst.n_properties = 2;
|
||||
/// pst.properties = Box::into_raw(props) as *const _;
|
||||
/// ```
|
||||
|
||||
pub properties: *const som_property_def_t,
|
||||
|
||||
/// Properties count.
|
||||
pub n_properties: usize,
|
||||
|
||||
/// Methods: `asset.func()`
|
||||
///
|
||||
/// Must be a pointer to an array of structures,
|
||||
/// see [`properties`](struct.som_passport_t.html#structfield.properties) for an example.
|
||||
pub methods: *const som_method_def_t,
|
||||
|
||||
/// Methods count.
|
||||
pub n_methods: usize,
|
||||
|
||||
/// Index access: `var item = asset[key]`.
|
||||
pub item_getter: Option<som_item_getter_t>,
|
||||
|
||||
/// Index access: `asset[key] = item`.
|
||||
pub item_setter: Option<som_item_setter_t>,
|
||||
|
||||
/// Enumeration: `for(var item in asset)`.
|
||||
pub item_next: Option<som_item_next_t>,
|
||||
|
||||
/// Property access interceptor: `var val = asset.prop`.
|
||||
pub prop_getter: Option<som_any_prop_getter_t>,
|
||||
|
||||
/// Property set interceptor: `asset.prop = val`.
|
||||
pub prop_setter: Option<som_any_prop_setter_t>,
|
||||
}
|
||||
|
||||
/// Empty passport.
|
||||
impl Default for som_passport_t {
|
||||
fn default() -> Self {
|
||||
use std::ptr;
|
||||
Self {
|
||||
flags: 0,
|
||||
name: 0,
|
||||
|
||||
prop_getter: None,
|
||||
prop_setter: None,
|
||||
|
||||
item_getter: None,
|
||||
item_setter: None,
|
||||
item_next: None,
|
||||
|
||||
properties: ptr::null(),
|
||||
n_properties: 0,
|
||||
|
||||
methods: ptr::null(),
|
||||
n_methods: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// [`som_passport_t`](struct.som_passport_t.html#structfield.flags) flags.
|
||||
#[repr(u64)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum som_passport_flags {
|
||||
/// Not extendable.
|
||||
SEALED = 0,
|
||||
|
||||
/// Extendable.
|
||||
///
|
||||
/// An asset may have new properties added by script.
|
||||
EXTENDABLE = 1,
|
||||
}
|
||||
|
||||
|
||||
/// Property of an asset.
|
||||
#[repr(C)]
|
||||
pub struct som_property_def_t {
|
||||
pub reserved: LPVOID,
|
||||
|
||||
/// Property name.
|
||||
pub name: som_atom_t,
|
||||
|
||||
/// Property getter: `var val = asset.prop`.
|
||||
pub getter: Option<som_prop_getter_t>,
|
||||
|
||||
/// Property setter: `asset.prop = val`.
|
||||
pub setter: Option<som_prop_setter_t>,
|
||||
}
|
||||
|
||||
/// Empty property.
|
||||
impl Default for som_property_def_t {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
reserved: std::ptr::null_mut(),
|
||||
name: 0,
|
||||
getter: None,
|
||||
setter: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Method of an asset.
|
||||
#[repr(C)]
|
||||
pub struct som_method_def_t {
|
||||
pub reserved: LPVOID,
|
||||
|
||||
/// Method name.
|
||||
pub name: som_atom_t,
|
||||
|
||||
/// Parameters count.
|
||||
///
|
||||
/// The actual arguments count can be lesser then specified here:
|
||||
///
|
||||
/// ```tiscript,ignore
|
||||
/// function asset.func(a,b,c); // native asset method accepts 3 parameters
|
||||
///
|
||||
/// asset.func("one"); // call with only one parameter.
|
||||
/// ```
|
||||
pub params: usize,
|
||||
|
||||
/// Method body.
|
||||
pub func: Option<som_method_t>,
|
||||
}
|
||||
|
||||
/// Empty method.
|
||||
impl Default for som_method_def_t {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
reserved: std::ptr::null_mut(),
|
||||
name: 0,
|
||||
params: 0,
|
||||
func: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type som_dispose_t = extern "C" fn(thing: *mut som_asset_t);
|
||||
|
||||
type som_prop_getter_t = extern "C" fn(thing: *mut som_asset_t, p_value: &mut VALUE) -> BOOL;
|
||||
type som_prop_setter_t = extern "C" fn(thing: *mut som_asset_t, p_value: &VALUE) -> BOOL;
|
||||
|
||||
type som_any_prop_getter_t = extern "C" fn(thing: *mut som_asset_t, propSymbol: som_atom_t, p_value: &mut VALUE) -> BOOL;
|
||||
type som_any_prop_setter_t = extern "C" fn(thing: *mut som_asset_t, propSymbol: som_atom_t, p_value: &VALUE) -> BOOL;
|
||||
|
||||
type som_item_getter_t = extern "C" fn(thing: *mut som_asset_t, p_key: &VALUE, p_value: &mut VALUE) -> BOOL;
|
||||
type som_item_setter_t = extern "C" fn(thing: *mut som_asset_t, p_key: &VALUE, p_value: &VALUE) -> BOOL;
|
||||
|
||||
type som_item_next_t = extern "C" fn(thing: *mut som_asset_t, p_idx: &mut VALUE, p_value: &mut VALUE) -> BOOL;
|
||||
|
||||
type som_method_t = extern "C" fn(thing: *mut som_asset_t, argc: u32, argv: *const VALUE, p_result: &mut VALUE) -> BOOL;
|
184
libs/rust-sciter/src/capi/screquest.rs
Normal file
184
libs/rust-sciter/src/capi/screquest.rs
Normal file
@ -0,0 +1,184 @@
|
||||
/*! Handling all attributes of requests (GET/POST/PUT/DELETE) sent by
|
||||
[`Element.request()`](https://sciter.com/docs/content/sciter/Element.htm) and
|
||||
[`View.request()`](https://sciter.com/docs/content/sciter/View.htm)
|
||||
functions and other load requests.
|
||||
|
||||
*/
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
|
||||
use capi::sctypes::{UINT, LPVOID, LPCBYTE, LPCSTR, LPCWSTR};
|
||||
use capi::scdef::{LPCSTR_RECEIVER, LPCWSTR_RECEIVER, LPCBYTE_RECEIVER};
|
||||
pub use capi::scdef::RESOURCE_TYPE;
|
||||
|
||||
MAKE_HANDLE!(#[doc = "Request native handle."] HREQUEST, _HREQUEST);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// Type of the result value for Sciter Request functions.
|
||||
pub enum REQUEST_RESULT {
|
||||
/// E.g. not enough memory.
|
||||
PANIC = -1,
|
||||
/// Success.
|
||||
OK = 0,
|
||||
/// Bad parameter.
|
||||
BAD_PARAM = 1,
|
||||
/// Operation failed, e.g. index out of bounds.
|
||||
FAILURE = 2,
|
||||
/// The platform does not support requested feature.
|
||||
NOTSUPPORTED = 3,
|
||||
}
|
||||
|
||||
impl std::error::Error for REQUEST_RESULT {}
|
||||
|
||||
impl std::fmt::Display for REQUEST_RESULT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// Request methods.
|
||||
pub enum REQUEST_METHOD {
|
||||
/// Sends a plain HTTP GET request.
|
||||
///
|
||||
/// Url-encoded params (if any) are appended to the url in order to form the request.
|
||||
GET = 1,
|
||||
/// Sends an HTTP POST request.
|
||||
///
|
||||
/// The params are serialized as `Content-Type: application/x-www-form-urlencoded;charset=utf-8`.
|
||||
POST = 2,
|
||||
/// Sends an HTTP PUT request.
|
||||
///
|
||||
/// The params are serialized as `Content-Type: multipart/form-data; boundary= ...`.
|
||||
PUT = 3,
|
||||
/// Sends an HTTP DELETE request.
|
||||
DELETE = 4,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// HTTP methods for the [`Element::send_request`](../dom/struct.Element.html#method.send_request).
|
||||
pub enum REQUEST_TYPE {
|
||||
/// Asynchronous GET.
|
||||
AsyncGet,
|
||||
/// Asynchronous POST.
|
||||
AsyncPost,
|
||||
/// Synchronous GET.
|
||||
Get,
|
||||
/// Synchronous POST.
|
||||
Post,
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// Completion state of a request.
|
||||
pub enum REQUEST_STATE {
|
||||
/// The request is pending.
|
||||
PENDING = 0,
|
||||
/// Completed successfully.
|
||||
SUCCESS = 1,
|
||||
/// Completed with failure.
|
||||
FAILURE = 2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct REQUEST_PARAM {
|
||||
pub name: LPCWSTR,
|
||||
pub value: LPCWSTR,
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct SciterRequestAPI
|
||||
{
|
||||
/// a.k.a AddRef()
|
||||
pub RequestUse: extern "system" fn (rq: HREQUEST) -> REQUEST_RESULT,
|
||||
|
||||
/// a.k.a Release()
|
||||
pub RequestUnUse: extern "system" fn (rq: HREQUEST) -> REQUEST_RESULT,
|
||||
|
||||
/// get requested URL
|
||||
pub RequestUrl: extern "system" fn (rq: HREQUEST, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get real, content URL (after possible redirection)
|
||||
pub RequestContentUrl: extern "system" fn (rq: HREQUEST, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get requested data type
|
||||
pub RequestGetRequestType: extern "system" fn (rq: HREQUEST, pType: &mut REQUEST_METHOD) -> REQUEST_RESULT,
|
||||
|
||||
/// get requested data type
|
||||
pub RequestGetRequestedDataType: extern "system" fn (rq: HREQUEST, pData: &mut RESOURCE_TYPE) -> REQUEST_RESULT,
|
||||
|
||||
/// get received data type, string, mime type
|
||||
pub RequestGetReceivedDataType: extern "system" fn (rq: HREQUEST, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
|
||||
/// get number of request parameters passed
|
||||
pub RequestGetNumberOfParameters: extern "system" fn (rq: HREQUEST, pNumber: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth request parameter name
|
||||
pub RequestGetNthParameterName: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth request parameter value
|
||||
pub RequestGetNthParameterValue: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get request times , ended - started = milliseconds to get the requst
|
||||
pub RequestGetTimes: extern "system" fn (rq: HREQUEST, pStarted: &mut UINT, pEnded: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get number of request headers
|
||||
pub RequestGetNumberOfRqHeaders: extern "system" fn (rq: HREQUEST, pNumber: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth request header name
|
||||
pub RequestGetNthRqHeaderName: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth request header value
|
||||
pub RequestGetNthRqHeaderValue: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get number of response headers
|
||||
pub RequestGetNumberOfRspHeaders: extern "system" fn (rq: HREQUEST, pNumber: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth response header name
|
||||
pub RequestGetNthRspHeaderName: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth response header value
|
||||
pub RequestGetNthRspHeaderValue: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get completion status (CompletionStatus - http response code : 200, 404, etc.)
|
||||
pub RequestGetCompletionStatus: extern "system" fn (rq: HREQUEST, pState: &mut REQUEST_STATE, pCompletionStatus: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get proxy host
|
||||
pub RequestGetProxyHost: extern "system" fn (rq: HREQUEST, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get proxy port
|
||||
pub RequestGetProxyPort: extern "system" fn (rq: HREQUEST, pPort: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// mark reequest as complete with status and data
|
||||
pub RequestSetSucceeded: extern "system" fn (rq: HREQUEST, status: UINT, dataOrNull: LPCBYTE, dataLength: UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// mark reequest as complete with failure and optional data
|
||||
pub RequestSetFailed: extern "system" fn (rq: HREQUEST, status: UINT, dataOrNull: LPCBYTE, dataLength: UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// append received data chunk
|
||||
pub RequestAppendDataChunk: extern "system" fn (rq: HREQUEST, data: LPCBYTE, dataLength: UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// set request header (single item)
|
||||
pub RequestSetRqHeader: extern "system" fn (rq: HREQUEST, name: LPCWSTR, value: LPCWSTR) -> REQUEST_RESULT,
|
||||
|
||||
/// set respone header (single item)
|
||||
pub RequestSetRspHeader: extern "system" fn (rq: HREQUEST, name: LPCWSTR, value: LPCWSTR) -> REQUEST_RESULT,
|
||||
|
||||
/// set received data type, string, mime type
|
||||
pub RequestSetReceivedDataType: extern "system" fn (rq: HREQUEST, _type: LPCSTR) -> REQUEST_RESULT,
|
||||
|
||||
/// set received data encoding, string
|
||||
pub RequestSetReceivedDataEncoding: extern "system" fn (rq: HREQUEST, encoding: LPCSTR) -> REQUEST_RESULT,
|
||||
|
||||
/// get received (so far) data
|
||||
pub RequestGetData: extern "system" fn (rq: HREQUEST, rcv: LPCBYTE_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
}
|
15
libs/rust-sciter/src/capi/sctiscript.rs
Normal file
15
libs/rust-sciter/src/capi/sctiscript.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//! TIScript Virtual Machine Runtime.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
|
||||
use capi::sctypes::{LPVOID, UINT64};
|
||||
|
||||
MAKE_HANDLE!(#[doc = "TIScript VM native handle."] HVM, _HVM);
|
||||
|
||||
pub type tiscript_value = UINT64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct tiscript_native_interface
|
||||
{
|
||||
create_vm: LPVOID,
|
||||
}
|
127
libs/rust-sciter/src/capi/sctypes.rs
Normal file
127
libs/rust-sciter/src/capi/sctypes.rs
Normal file
@ -0,0 +1,127 @@
|
||||
//! Sciter platform-dependent types.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use self::libc::*;
|
||||
|
||||
|
||||
// common
|
||||
MAKE_HANDLE!(#[doc = "Window native handle."] HWINDOW, _HWINDOW); // HWND or NSView* or GtkWidget*
|
||||
MAKE_HANDLE!(#[doc = "Archive native handle."] HSARCHIVE, _HSARCHIVE);
|
||||
|
||||
pub type BYTE = u8;
|
||||
pub type INT = i32;
|
||||
pub type LONG = i32;
|
||||
pub type UINT = u32;
|
||||
pub type INT64 = i64;
|
||||
pub type UINT64 = u64;
|
||||
|
||||
pub type FLOAT_VALUE = f64;
|
||||
|
||||
pub type WPARAM = size_t;
|
||||
pub type LPARAM = ssize_t;
|
||||
|
||||
pub type UINT_PTR = uintptr_t;
|
||||
pub type LRESULT = ssize_t;
|
||||
|
||||
pub type CHAR = c_char;
|
||||
pub type LPSTR = *mut CHAR;
|
||||
pub type LPCSTR = *const CHAR;
|
||||
|
||||
pub type WCHAR = u16;
|
||||
pub type LPWSTR = *mut WCHAR;
|
||||
pub type LPCWSTR = *const WCHAR;
|
||||
|
||||
pub type LPCBYTE = *const BYTE;
|
||||
pub type LPUINT = *mut UINT;
|
||||
|
||||
pub type VOID = c_void;
|
||||
pub type LPVOID = *mut VOID;
|
||||
pub type LPCVOID = *const VOID;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub type BOOL = i32;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub type BOOL = i8;
|
||||
|
||||
pub type PBOOL = *mut BOOL;
|
||||
|
||||
/// Defines the coordinates of the upper-left and lower-right corners of a rectangle.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct RECT {
|
||||
pub left: LONG,
|
||||
pub top: LONG,
|
||||
pub right: LONG,
|
||||
pub bottom: LONG,
|
||||
}
|
||||
pub type LPRECT = *mut RECT;
|
||||
pub type LPCRECT = *const RECT;
|
||||
|
||||
impl RECT {
|
||||
/// Calculate the height of the rect.
|
||||
pub fn height(&self) -> LONG {
|
||||
self.bottom - self.top
|
||||
}
|
||||
|
||||
/// Calculate the width of the rect.
|
||||
pub fn width(&self) -> LONG {
|
||||
self.right - self.left
|
||||
}
|
||||
|
||||
/// Return the size of the rect in width and height form.
|
||||
pub fn size(&self) -> SIZE {
|
||||
SIZE {
|
||||
cx: self.width(),
|
||||
cy: self.height(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the top-left point of the rect.
|
||||
pub fn topleft(&self) -> POINT {
|
||||
POINT {
|
||||
x: self.left,
|
||||
y: self.top,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines the `x` and `y` coordinates of a point.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct POINT {
|
||||
pub x: LONG,
|
||||
pub y: LONG,
|
||||
}
|
||||
pub type LPPOINT = *mut POINT;
|
||||
|
||||
/// Specifies the width and height of a rectangle.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct SIZE {
|
||||
pub cx: LONG,
|
||||
pub cy: LONG,
|
||||
}
|
||||
pub type LPSIZE = *mut SIZE;
|
||||
|
||||
|
||||
#[cfg(windows)]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct MSG {
|
||||
pub hwnd: HWINDOW,
|
||||
pub message: UINT,
|
||||
pub wParam: WPARAM,
|
||||
pub lParam: LPARAM,
|
||||
pub time: UINT,
|
||||
pub pt: POINT,
|
||||
}
|
||||
#[cfg(windows)]
|
||||
pub type LPMSG = *mut MSG;
|
||||
|
124
libs/rust-sciter/src/capi/scvalue.rs
Normal file
124
libs/rust-sciter/src/capi/scvalue.rs
Normal file
@ -0,0 +1,124 @@
|
||||
//! Sciter value, native C interface.
|
||||
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
|
||||
/// A JSON value.
|
||||
///
|
||||
/// An opaque union that can hold different types of values: numbers, strings, arrays, objects, etc.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VALUE
|
||||
{
|
||||
/// Value type.
|
||||
pub t: VALUE_TYPE,
|
||||
|
||||
/// Value unit type.
|
||||
pub u: UINT,
|
||||
|
||||
/// Value data.
|
||||
pub d: UINT64,
|
||||
}
|
||||
|
||||
impl Default for VALUE {
|
||||
fn default() -> Self {
|
||||
VALUE { t: VALUE_TYPE::T_UNDEFINED, u: 0, d: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_RESULT
|
||||
{
|
||||
OK_TRUE = -1,
|
||||
OK = 0,
|
||||
BAD_PARAMETER = 1,
|
||||
INCOMPATIBLE_TYPE = 2,
|
||||
}
|
||||
|
||||
impl std::error::Error for VALUE_RESULT {}
|
||||
|
||||
impl std::fmt::Display for VALUE_RESULT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_STRING_CVT_TYPE {
|
||||
SIMPLE = 0,
|
||||
JSON_LITERAL = 1,
|
||||
JSON_MAP = 2,
|
||||
XJSON_LITERAL = 3,
|
||||
}
|
||||
|
||||
|
||||
/// Type identifier of the value.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_TYPE {
|
||||
T_UNDEFINED = 0,
|
||||
T_NULL = 1,
|
||||
T_BOOL,
|
||||
T_INT,
|
||||
T_FLOAT,
|
||||
T_STRING,
|
||||
T_DATE,
|
||||
T_CURRENCY,
|
||||
T_LENGTH,
|
||||
T_ARRAY,
|
||||
T_MAP,
|
||||
T_FUNCTION,
|
||||
T_BYTES,
|
||||
T_OBJECT,
|
||||
T_DOM_OBJECT,
|
||||
T_RESOURCE,
|
||||
T_RANGE,
|
||||
T_DURATION,
|
||||
T_ANGLE,
|
||||
T_COLOR,
|
||||
T_ENUM,
|
||||
T_ASSET,
|
||||
|
||||
T_UNKNOWN,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_UNIT_UNDEFINED
|
||||
{
|
||||
UT_NOTHING = 1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_UNIT_TYPE_STRING
|
||||
{
|
||||
STRING = 0, // string
|
||||
ERROR = 1, // is an error string
|
||||
SECURE = 2, // secure string ("wiped" on destroy)
|
||||
URL = 3, // url(...)
|
||||
SELECTOR = 4, // selector(...)
|
||||
FILE = 0xfffe, // file name
|
||||
SYMBOL = 0xffff, // symbol in tiscript sense
|
||||
}
|
||||
|
||||
// Sciter or TIScript specific
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_UNIT_TYPE_OBJECT
|
||||
{
|
||||
ARRAY = 0, // type T_OBJECT of type Array
|
||||
OBJECT = 1, // type T_OBJECT of type Object
|
||||
CLASS = 2, // type T_OBJECT of type Class (class or namespace)
|
||||
NATIVE = 3, // type T_OBJECT of native Type with data slot (LPVOID)
|
||||
FUNCTION = 4, // type T_OBJECT of type Function
|
||||
ERROR = 5, // type T_OBJECT of type Error
|
||||
}
|
||||
|
||||
pub type NATIVE_FUNCTOR_INVOKE = extern "C" fn (tag: LPVOID, argc: UINT, argv: *const VALUE, retval: * mut VALUE);
|
||||
pub type NATIVE_FUNCTOR_RELEASE = extern "C" fn (tag: LPVOID);
|
1570
libs/rust-sciter/src/dom.rs
Normal file
1570
libs/rust-sciter/src/dom.rs
Normal file
File diff suppressed because it is too large
Load Diff
306
libs/rust-sciter/src/eventhandler.rs
Normal file
306
libs/rust-sciter/src/eventhandler.rs
Normal file
@ -0,0 +1,306 @@
|
||||
use capi::sctypes::*;
|
||||
use capi::scbehavior::*;
|
||||
use capi::scdom::{HELEMENT};
|
||||
use value::Value;
|
||||
use dom::event::EventHandler;
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct WindowHandler<T>
|
||||
{
|
||||
pub hwnd: HWINDOW,
|
||||
pub handler: T,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct BoxedHandler {
|
||||
pub handler: Box<dyn EventHandler>,
|
||||
}
|
||||
|
||||
fn is_detach_event(evtg: UINT, params: LPVOID) -> bool {
|
||||
let evtg : EVENT_GROUPS = unsafe { ::std::mem::transmute(evtg) };
|
||||
if evtg == EVENT_GROUPS::HANDLE_INITIALIZATION {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const INITIALIZATION_EVENTS;
|
||||
let cmd = unsafe { *scnm };
|
||||
if cmd == INITIALIZATION_EVENTS::BEHAVIOR_DETACH {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub(crate) extern "system" fn _event_handler_window_proc<T: EventHandler>(tag: LPVOID, _he: ::capi::scdom::HELEMENT, evtg: UINT, params: LPVOID) -> BOOL
|
||||
{
|
||||
let boxed = tag as *mut WindowHandler<T>;
|
||||
let tuple: &mut WindowHandler<T> = unsafe { &mut *boxed };
|
||||
|
||||
let hroot: HELEMENT = if let Ok(root) = ::dom::Element::from_window(tuple.hwnd) {
|
||||
root.as_ptr()
|
||||
} else {
|
||||
::std::ptr::null_mut()
|
||||
};
|
||||
|
||||
// custom initialization (because there is no DOM in plain window)
|
||||
if is_detach_event(evtg, params) {
|
||||
tuple.handler.detached(hroot);
|
||||
|
||||
// here we drop our tuple
|
||||
let ptr = unsafe { Box::from_raw(boxed) };
|
||||
drop(ptr);
|
||||
|
||||
return true as BOOL;
|
||||
}
|
||||
|
||||
process_events(&mut tuple.handler, hroot, evtg, params)
|
||||
}
|
||||
|
||||
pub(crate) extern "system" fn _event_handler_behavior_proc(tag: LPVOID, he: HELEMENT, evtg: UINT, params: LPVOID) -> BOOL {
|
||||
// reconstruct pointer to Handler
|
||||
let boxed = tag as *mut BoxedHandler;
|
||||
let me = unsafe { &mut *boxed };
|
||||
let me = &mut *me.handler;
|
||||
|
||||
if is_detach_event(evtg, params) {
|
||||
me.detached(he);
|
||||
|
||||
// here we drop our handler
|
||||
let ptr = unsafe { Box::from_raw(boxed) };
|
||||
drop(ptr);
|
||||
|
||||
return true as BOOL;
|
||||
}
|
||||
|
||||
process_events(me, he, evtg, params)
|
||||
}
|
||||
|
||||
pub(crate) extern "system" fn _event_handler_proc<T: EventHandler>(tag: LPVOID, he: HELEMENT, evtg: UINT, params: LPVOID) -> BOOL
|
||||
{
|
||||
// reconstruct pointer to Handler
|
||||
let boxed = tag as *mut T;
|
||||
let me = unsafe { &mut *boxed };
|
||||
|
||||
if is_detach_event(evtg, params) {
|
||||
me.detached(he);
|
||||
|
||||
// here we drop our handler
|
||||
let ptr = unsafe { Box::from_raw(boxed) };
|
||||
drop(ptr);
|
||||
|
||||
return true as BOOL;
|
||||
}
|
||||
|
||||
process_events(me, he, evtg, params)
|
||||
}
|
||||
|
||||
fn process_events(me: &mut dyn EventHandler, he: HELEMENT, evtg: UINT, params: LPVOID) -> BOOL
|
||||
{
|
||||
let evtg : EVENT_GROUPS = unsafe { ::std::mem::transmute(evtg) };
|
||||
if he.is_null()
|
||||
&& evtg != EVENT_GROUPS::SUBSCRIPTIONS_REQUEST
|
||||
&& evtg != EVENT_GROUPS::HANDLE_BEHAVIOR_EVENT
|
||||
&& evtg != EVENT_GROUPS::HANDLE_INITIALIZATION
|
||||
&& evtg != EVENT_GROUPS::HANDLE_SOM
|
||||
{
|
||||
eprintln!("[sciter] warning! null element for {:04X}", evtg as u32);
|
||||
}
|
||||
|
||||
let result = match evtg {
|
||||
|
||||
EVENT_GROUPS::SUBSCRIPTIONS_REQUEST => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *mut EVENT_GROUPS;
|
||||
let nm = unsafe {&mut *scnm};
|
||||
let handled = me.get_subscription();
|
||||
if let Some(needed) = handled {
|
||||
*nm = needed;
|
||||
}
|
||||
handled.is_some()
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_INITIALIZATION => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *mut INITIALIZATION_PARAMS;
|
||||
let nm = unsafe { &mut *scnm };
|
||||
match nm.cmd {
|
||||
INITIALIZATION_EVENTS::BEHAVIOR_DETACH => {
|
||||
me.detached(he);
|
||||
},
|
||||
|
||||
INITIALIZATION_EVENTS::BEHAVIOR_ATTACH => {
|
||||
me.attached(he);
|
||||
},
|
||||
};
|
||||
true
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_SOM => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *mut SOM_PARAMS;
|
||||
let nm = unsafe { &mut *scnm };
|
||||
match nm.cmd {
|
||||
SOM_EVENTS::SOM_GET_PASSPORT => {
|
||||
if let Some(asset) = me.get_asset() {
|
||||
nm.result.passport = asset.get_passport();
|
||||
return true as BOOL;
|
||||
}
|
||||
},
|
||||
|
||||
SOM_EVENTS::SOM_GET_ASSET => {
|
||||
if let Some(asset) = me.get_asset() {
|
||||
nm.result.asset = asset;
|
||||
return true as BOOL;
|
||||
}
|
||||
},
|
||||
};
|
||||
false
|
||||
},
|
||||
|
||||
|
||||
EVENT_GROUPS::HANDLE_BEHAVIOR_EVENT => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const BEHAVIOR_EVENT_PARAMS;
|
||||
let nm = unsafe { &*scnm };
|
||||
|
||||
use dom::event::EventReason;
|
||||
let code :BEHAVIOR_EVENTS = unsafe{ ::std::mem::transmute(nm.cmd & 0x0_0FFF) };
|
||||
let phase: PHASE_MASK = unsafe { ::std::mem::transmute(nm.cmd & 0xFFFF_F000) };
|
||||
let reason = match code {
|
||||
BEHAVIOR_EVENTS::EDIT_VALUE_CHANGED | BEHAVIOR_EVENTS::EDIT_VALUE_CHANGING => {
|
||||
let reason: EDIT_CHANGED_REASON = unsafe{ ::std::mem::transmute(nm.reason as UINT) };
|
||||
EventReason::EditChanged(reason)
|
||||
},
|
||||
|
||||
BEHAVIOR_EVENTS::VIDEO_BIND_RQ => {
|
||||
EventReason::VideoBind(nm.reason as LPVOID)
|
||||
}
|
||||
|
||||
_ => {
|
||||
let reason: CLICK_REASON = unsafe{ ::std::mem::transmute(nm.reason as UINT) };
|
||||
EventReason::General(reason)
|
||||
}
|
||||
};
|
||||
|
||||
if he.is_null() && code != BEHAVIOR_EVENTS::MEDIA_CHANGED {
|
||||
eprintln!("[sciter] warning! null element for {:?}:{:?}", evtg, code);
|
||||
}
|
||||
|
||||
if phase == PHASE_MASK::SINKING { // catch this only once
|
||||
match code {
|
||||
BEHAVIOR_EVENTS::DOCUMENT_COMPLETE => {
|
||||
me.document_complete(he, nm.heTarget);
|
||||
},
|
||||
BEHAVIOR_EVENTS::DOCUMENT_CLOSE => {
|
||||
me.document_close(he, nm.heTarget);
|
||||
},
|
||||
_ => ()
|
||||
};
|
||||
}
|
||||
|
||||
let handled = me.on_event(he, nm.he, nm.heTarget, code, phase, reason);
|
||||
handled
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_SCRIPTING_METHOD_CALL => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *mut SCRIPTING_METHOD_PARAMS;
|
||||
let nm = unsafe { &mut *scnm };
|
||||
let name = u2s!(nm.name);
|
||||
let argv = unsafe { Value::unpack_from(nm.argv, nm.argc) };
|
||||
let rv = me.on_script_call(he, &name, &argv);
|
||||
let handled = if let Some(v) = rv {
|
||||
v.pack_to(&mut nm.result);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
handled
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_METHOD_CALL => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const METHOD_PARAMS;
|
||||
let nm = unsafe { & *scnm };
|
||||
let code: BEHAVIOR_METHOD_IDENTIFIERS = unsafe { ::std::mem::transmute((*nm).method) };
|
||||
use capi::scbehavior::BEHAVIOR_METHOD_IDENTIFIERS::*;
|
||||
|
||||
// output values
|
||||
let mut method_value = Value::new();
|
||||
let mut is_empty = false;
|
||||
|
||||
let handled = {
|
||||
|
||||
// unpack method parameters
|
||||
use dom::event::MethodParams;
|
||||
let reason = match code {
|
||||
DO_CLICK => {
|
||||
MethodParams::Click
|
||||
},
|
||||
IS_EMPTY => {
|
||||
MethodParams::IsEmpty(&mut is_empty)
|
||||
},
|
||||
GET_VALUE => {
|
||||
MethodParams::GetValue(&mut method_value)
|
||||
},
|
||||
SET_VALUE => {
|
||||
// Value from Sciter.
|
||||
let payload = params as *const VALUE_PARAMS;
|
||||
let pm = unsafe { & *payload };
|
||||
MethodParams::SetValue(Value::from(&pm.value))
|
||||
},
|
||||
|
||||
_ => {
|
||||
MethodParams::Custom((*nm).method, params)
|
||||
},
|
||||
};
|
||||
|
||||
// call event handler
|
||||
let handled = me.on_method_call(he, reason);
|
||||
handled
|
||||
};
|
||||
|
||||
if handled {
|
||||
// Pack values back to Sciter.
|
||||
match code {
|
||||
GET_VALUE => {
|
||||
let payload = params as *mut VALUE_PARAMS;
|
||||
let pm = unsafe { &mut *payload };
|
||||
method_value.pack_to(&mut pm.value);
|
||||
},
|
||||
|
||||
IS_EMPTY => {
|
||||
let payload = params as *mut IS_EMPTY_PARAMS;
|
||||
let pm = unsafe { &mut *payload };
|
||||
pm.is_empty = is_empty as UINT;
|
||||
},
|
||||
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
// we've done here
|
||||
handled
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_TIMER => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const TIMER_PARAMS;
|
||||
let nm = unsafe { & *scnm };
|
||||
let handled = me.on_timer(he, nm.timerId as u64);
|
||||
handled
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_DRAW => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const DRAW_PARAMS;
|
||||
let nm = unsafe { & *scnm };
|
||||
let handled = me.on_draw(he, nm.gfx, &nm.area, nm.layer);
|
||||
handled
|
||||
},
|
||||
|
||||
// unknown `EVENT_GROUPS` notification
|
||||
_ => {
|
||||
eprintln!("[sciter] warning! unknown event group {:04X}", evtg as u32);
|
||||
false
|
||||
},
|
||||
};
|
||||
return result as BOOL;
|
||||
}
|
1101
libs/rust-sciter/src/graphics.rs
Normal file
1101
libs/rust-sciter/src/graphics.rs
Normal file
File diff suppressed because it is too large
Load Diff
585
libs/rust-sciter/src/host.rs
Normal file
585
libs/rust-sciter/src/host.rs
Normal file
@ -0,0 +1,585 @@
|
||||
//! Sciter host application helpers.
|
||||
|
||||
use ::{_API};
|
||||
use capi::scdef::SCITER_RT_OPTIONS;
|
||||
use capi::sctypes::*;
|
||||
use capi::screquest::HREQUEST;
|
||||
use capi::schandler::NativeHandler;
|
||||
use dom::event::EventHandler;
|
||||
use eventhandler::*;
|
||||
use value::{Value};
|
||||
|
||||
pub use capi::scdef::{LOAD_RESULT, OUTPUT_SUBSYTEMS, OUTPUT_SEVERITY};
|
||||
pub use capi::scdef::{SCN_LOAD_DATA, SCN_DATA_LOADED, SCN_ATTACH_BEHAVIOR, SCN_INVALIDATE_RECT};
|
||||
|
||||
|
||||
/// A specialized `Result` type for Sciter host operations.
|
||||
pub type Result<T> = ::std::result::Result<T, ()>;
|
||||
|
||||
macro_rules! ok_or {
|
||||
($ok:ident) => {
|
||||
if $ok != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
};
|
||||
|
||||
($ok:ident, $rv:expr) => {
|
||||
if $ok != 0 {
|
||||
Ok($rv)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
};
|
||||
|
||||
($ok:ident, $rv:expr, $err:expr) => {
|
||||
if $ok != 0 {
|
||||
Ok($rv)
|
||||
} else {
|
||||
Err($err)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/** Sciter notification handler for [`Window.sciter_handler()`](../window/struct.Window.html#method.sciter_handler).
|
||||
|
||||
## Resource handling and custom resource loader
|
||||
|
||||
HTML loaded into Sciter may contain external resources: CSS (Cascading Style Sheets),
|
||||
images, fonts, cursors and scripts.
|
||||
To get any of such resources Sciter will first send a `on_data_load(SCN_LOAD_DATA)` notification
|
||||
to your application using the callback handler registered with `sciter::Window.sciter_handler()` function.
|
||||
|
||||
Your application can provide your own data for such resources
|
||||
(for example, from the resource section, database or other storage of your choice)
|
||||
or delegate the resource loading to the built-in HTTP client or file loader, or discard the loading at all.
|
||||
|
||||
Note: This handler should be registered before any
|
||||
[`load_html()`](struct.Host.html#method.load_html) or
|
||||
[`load_file()`](struct.Host.html#method.load_file) calls
|
||||
in order to send notifications while loading.
|
||||
|
||||
*/
|
||||
#[allow(unused_variables)]
|
||||
pub trait HostHandler {
|
||||
|
||||
/// Notifies that Sciter is about to download the referred resource.
|
||||
///
|
||||
/// You can load or overload data immediately by calling `self.data_ready()` with parameters provided by `SCN_LOAD_DATA`,
|
||||
/// or save them (including `request_id`) for later usage and answer here with `LOAD_RESULT::LOAD_DELAYED` code.
|
||||
///
|
||||
/// Also you can discard the request (data will not be loaded at the document)
|
||||
/// or take care about this request completely by yourself (via the [request API](../request/index.html)).
|
||||
fn on_data_load(&mut self, pnm: &mut SCN_LOAD_DATA) -> Option<LOAD_RESULT> { return None; }
|
||||
|
||||
/// This notification indicates that external data (for example, image) download process completed.
|
||||
fn on_data_loaded(&mut self, pnm: &SCN_DATA_LOADED) { }
|
||||
|
||||
/// This notification is sent on parsing the document and while processing elements
|
||||
/// having non empty `behavior: ` style attribute value.
|
||||
fn on_attach_behavior(&mut self, pnm: &mut SCN_ATTACH_BEHAVIOR) -> bool { return false; }
|
||||
|
||||
/// This notification is sent when instance of the engine is destroyed.
|
||||
fn on_engine_destroyed(&mut self) { }
|
||||
|
||||
/// This notification is sent when the engine encounters critical rendering error: e.g. DirectX gfx driver error.
|
||||
/// Most probably bad gfx drivers.
|
||||
fn on_graphics_critical_failure(&mut self) { }
|
||||
|
||||
/// This notification is sent when the engine needs some area to be redrawn.
|
||||
fn on_invalidate(&mut self, pnm: &SCN_INVALIDATE_RECT) {}
|
||||
|
||||
/// This output function will be used for reporting problems found while loading html and css documents.
|
||||
fn on_debug_output(&mut self, subsystem: OUTPUT_SUBSYTEMS, severity: OUTPUT_SEVERITY, message: &str) {
|
||||
if !message.is_empty() {
|
||||
if severity == OUTPUT_SEVERITY::INFO {
|
||||
// e.g. `stdout.println` in TIScript
|
||||
println!("{:?}:{:?}: {}", severity, subsystem, message);
|
||||
} else {
|
||||
// e.g. `stderr.println` or CSS/script errors and warnings.
|
||||
eprintln!("{:?}:{:?}: {}", severity, subsystem, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This function is used as response to [`on_data_load`](#method.on_data_load) request.
|
||||
///
|
||||
/// Parameters here must be taken from [`SCN_LOAD_DATA`](struct.SCN_LOAD_DATA.html) structure. You can store them for later usage,
|
||||
/// but you must answer as [`LOAD_DELAYED`](enum.LOAD_RESULT.html#variant.LOAD_DELAYED) code and provide an `request_id` here.
|
||||
fn data_ready(&self, hwnd: HWINDOW, uri: &str, data: &[u8], request_id: Option<HREQUEST>) {
|
||||
let s = s2w!(uri);
|
||||
match request_id {
|
||||
Some(req) => {
|
||||
(_API.SciterDataReadyAsync)(hwnd, s.as_ptr(), data.as_ptr(), data.len() as UINT, req)
|
||||
},
|
||||
None => {
|
||||
(_API.SciterDataReady)(hwnd, s.as_ptr(), data.as_ptr(), data.len() as UINT)
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// This function is used as a response to the [`on_attach_behavior`](#method.on_attach_behavior) request
|
||||
/// to attach a newly created behavior `handler` to the requested element.
|
||||
fn attach_behavior<Handler: EventHandler>(&self, pnm: &mut SCN_ATTACH_BEHAVIOR, handler: Handler) {
|
||||
// make native handler
|
||||
let boxed = Box::new(handler);
|
||||
let ptr = Box::into_raw(boxed); // dropped in `_event_handler_proc`
|
||||
pnm.elementProc = ::eventhandler::_event_handler_proc::<Handler>;
|
||||
pnm.elementTag = ptr as LPVOID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Default `HostHandler` implementation
|
||||
#[derive(Default)]
|
||||
struct DefaultHandler;
|
||||
|
||||
/// Default `HostHandler` implementation
|
||||
impl HostHandler for DefaultHandler {
|
||||
|
||||
}
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
type BehaviorList = Vec<(String, Box<dyn Fn() -> Box<dyn EventHandler>>)>;
|
||||
type SharedBehaviorList = Rc<RefCell<BehaviorList>>;
|
||||
type SharedArchive = Rc<RefCell<Option<Archive>>>;
|
||||
|
||||
#[repr(C)]
|
||||
struct HostCallback<Callback> {
|
||||
sig: u32,
|
||||
behaviors: SharedBehaviorList,
|
||||
handler: Callback,
|
||||
archive: SharedArchive,
|
||||
}
|
||||
|
||||
/// Sciter host runtime support.
|
||||
pub struct Host {
|
||||
hwnd: HWINDOW,
|
||||
behaviors: SharedBehaviorList,
|
||||
handler: RefCell<NativeHandler>,
|
||||
archive: SharedArchive,
|
||||
}
|
||||
|
||||
impl Host {
|
||||
|
||||
/// Attach Sciter host to existing window.
|
||||
///
|
||||
/// Usually Sciter window created by a [`sciter::Window::create()`](../window/struct.Window.html#method.create),
|
||||
/// but you can attach Sciter to an existing native window.
|
||||
/// In this case you need to mix-in window events processing with `SciterProcND` (Windows only).
|
||||
/// Sciter engine will be initialized either on `WM_CREATE` or `WM_INITDIALOG` response
|
||||
/// or by calling `SciterCreateOnDirectXWindow` (again, Windows only).
|
||||
pub fn attach(hwnd: HWINDOW) -> Host {
|
||||
// Host with default debug handler installed
|
||||
let host = Host {
|
||||
hwnd,
|
||||
behaviors: Default::default(),
|
||||
handler: Default::default(),
|
||||
archive: Default::default(),
|
||||
};
|
||||
host.setup_callback(DefaultHandler::default());
|
||||
return host;
|
||||
}
|
||||
|
||||
/// Attach Sciter host to an existing window with the given Host handler.
|
||||
pub fn attach_with<Handler: HostHandler>(hwnd: HWINDOW, handler: Handler) -> Host {
|
||||
let host = Host {
|
||||
hwnd,
|
||||
behaviors: Default::default(),
|
||||
handler: Default::default(),
|
||||
archive: Default::default(),
|
||||
};
|
||||
host.setup_callback(handler);
|
||||
return host;
|
||||
}
|
||||
|
||||
/// Attach [`dom::EventHandler`](../dom/event/trait.EventHandler.html) to the Sciter window.
|
||||
pub fn event_handler<Handler: EventHandler>(&self, handler: Handler) {
|
||||
self.attach_handler(handler)
|
||||
}
|
||||
|
||||
/// Attach [`dom::EventHandler`](../dom/event/trait.EventHandler.html) to the Sciter window.
|
||||
#[doc(hidden)]
|
||||
pub fn attach_handler<Handler: EventHandler>(&self, handler: Handler) {
|
||||
let hwnd = self.get_hwnd();
|
||||
let boxed = Box::new( WindowHandler { hwnd, handler } );
|
||||
let ptr = Box::into_raw(boxed); // dropped in `_event_handler_window_proc`
|
||||
// eprintln!("{}: {:?}", std::any::type_name::<Handler>(), ptr);
|
||||
|
||||
let func = _event_handler_window_proc::<Handler>;
|
||||
let flags = ::dom::event::default_events();
|
||||
(_API.SciterWindowAttachEventHandler)(hwnd, func, ptr as LPVOID, flags as UINT);
|
||||
}
|
||||
|
||||
/// Set callback for Sciter engine events.
|
||||
pub(crate) fn setup_callback<Callback: HostHandler>(&self, handler: Callback) {
|
||||
|
||||
let payload: HostCallback<Callback> = HostCallback {
|
||||
sig: 17,
|
||||
behaviors: Rc::clone(&self.behaviors),
|
||||
archive: Rc::clone(&self.archive),
|
||||
handler: handler,
|
||||
};
|
||||
|
||||
*self.handler.borrow_mut() = NativeHandler::from(payload);
|
||||
let ptr = self.handler.borrow().as_mut_ptr();
|
||||
|
||||
(_API.SciterSetCallback)(self.get_hwnd(), _on_handle_notification::<Callback>, ptr);
|
||||
(_API.SciterSetupDebugOutput)(0 as HWINDOW, ptr, _on_debug_notification::<Callback>);
|
||||
}
|
||||
|
||||
/// Register a native event handler for the specified behavior name.
|
||||
///
|
||||
/// See the [`Window::register_behavior`](../window/struct.Window.html#method.register_behavior) for an example.
|
||||
pub fn register_behavior<Factory>(&self, name: &str, factory: Factory)
|
||||
where
|
||||
Factory: Fn() -> Box<dyn EventHandler> + 'static
|
||||
{
|
||||
let make: Box<dyn Fn() -> Box<dyn EventHandler>> = Box::new(factory);
|
||||
let pair = (name.to_owned(), make);
|
||||
self.behaviors.borrow_mut().push(pair);
|
||||
}
|
||||
|
||||
/// Register an archive produced by `packfolder`.
|
||||
///
|
||||
/// See documentation of the [`Archive`](struct.Archive.html).
|
||||
pub fn register_archive(&self, resource: &[u8]) -> Result<()> {
|
||||
*self.archive.borrow_mut() = Some(Archive::open(resource)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set debug mode for this window.
|
||||
pub fn enable_debug(&self, enable: bool) {
|
||||
(_API.SciterSetOption)(self.hwnd, SCITER_RT_OPTIONS::SCITER_SET_DEBUG_MODE, enable as UINT_PTR);
|
||||
}
|
||||
|
||||
/// Get native window handle.
|
||||
pub fn get_hwnd(&self) -> HWINDOW {
|
||||
self.hwnd
|
||||
}
|
||||
|
||||
/// Get window root DOM element.
|
||||
pub fn get_root(&self) -> Option<::dom::Element> {
|
||||
::dom::Element::from_window(self.hwnd).ok()
|
||||
}
|
||||
|
||||
/// Load an HTML document from file.
|
||||
pub fn load_file(&self, uri: &str) -> bool {
|
||||
// TODO: it should be `Result<()>` instead `bool`
|
||||
let s = s2w!(uri);
|
||||
(_API.SciterLoadFile)(self.hwnd, s.as_ptr()) != 0
|
||||
}
|
||||
|
||||
/// Load an HTML document from memory.
|
||||
pub fn load_html(&self, html: &[u8], uri: Option<&str>) -> bool {
|
||||
match uri {
|
||||
Some(uri) => {
|
||||
let s = s2w!(uri);
|
||||
(_API.SciterLoadHtml)(self.hwnd, html.as_ptr(), html.len() as UINT, s.as_ptr()) != 0
|
||||
},
|
||||
None => {
|
||||
(_API.SciterLoadHtml)(self.hwnd, html.as_ptr(), html.len() as UINT, 0 as LPCWSTR) != 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This function is used as response to [`HostHandler::on_data_load`](trait.HostHandler.html#method.on_data_load) request.
|
||||
pub fn data_ready(&self, uri: &str, data: &[u8]) {
|
||||
let s = s2w!(uri);
|
||||
(_API.SciterDataReady)(self.hwnd, s.as_ptr(), data.as_ptr(), data.len() as UINT);
|
||||
}
|
||||
|
||||
/// Use this function outside of [`HostHandler::on_data_load`](trait.HostHandler.html#method.on_data_load) request.
|
||||
///
|
||||
/// It can be used for two purposes:
|
||||
///
|
||||
/// 1. Asynchronious resource loading in respect of [`on_data_load`](trait.HostHandler.html#method.on_data_load)
|
||||
/// requests (you must use `request_id` in this case).
|
||||
/// 2. Refresh of an already loaded resource (for example, dynamic image updates).
|
||||
pub fn data_ready_async(&self, uri: &str, data: &[u8], request_id: Option<HREQUEST>) {
|
||||
let s = s2w!(uri);
|
||||
let req = request_id.unwrap_or(::std::ptr::null_mut());
|
||||
(_API.SciterDataReadyAsync)(self.hwnd, s.as_ptr(), data.as_ptr(), data.len() as UINT, req);
|
||||
}
|
||||
|
||||
/// Evaluate the given script in context of the current document.
|
||||
///
|
||||
/// This function returns `Result<Value,Value>` with script function result value or with Sciter script error.
|
||||
pub fn eval_script(&self, script: &str) -> ::std::result::Result<Value, Value> {
|
||||
let (s,n) = s2wn!(script);
|
||||
let mut rv = Value::new();
|
||||
let ok = (_API.SciterEval)(self.hwnd, s.as_ptr(), n, rv.as_ptr());
|
||||
ok_or!(ok, rv, rv)
|
||||
}
|
||||
|
||||
/// Call a script function defined in the global namespace.
|
||||
///
|
||||
/// This function returns `Result<Value,Value>` with script function result value or with Sciter script error.
|
||||
///
|
||||
/// You can use the [`&make_args!(args...)`](../macro.make_args.html) macro which helps you
|
||||
/// to construct script arguments from Rust types.
|
||||
pub fn call_function(&self, name: &str, args: &[Value]) -> ::std::result::Result<Value, Value> {
|
||||
let mut rv = Value::new();
|
||||
let s = s2u!(name);
|
||||
let argv = Value::pack_args(args);
|
||||
let ok = (_API.SciterCall)(self.hwnd, s.as_ptr(), argv.len() as UINT, argv.as_ptr(), rv.as_ptr());
|
||||
ok_or!(ok, rv, rv)
|
||||
}
|
||||
|
||||
/// Set home url for Sciter resources.
|
||||
///
|
||||
/// If you set it like `set_home_url("https://sciter.com/modules/")` then
|
||||
///
|
||||
/// `<script src="sciter:lib/root-extender.tis">` will load
|
||||
/// root-extender.tis from
|
||||
///
|
||||
/// `https://sciter.com/modules/lib/root-extender.tis`.
|
||||
pub fn set_home_url(&self, url: &str) -> Result<()> {
|
||||
let s = s2w!(url);
|
||||
let ok = (_API.SciterSetHomeURL)(self.hwnd, s.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set media type of this Sciter instance.
|
||||
///
|
||||
/// For example, media type can be "handheld", "projection", "screen", "screen-hires", etc.
|
||||
/// By default, Sciter window has the `"screen"` media type.
|
||||
///
|
||||
/// Media type name is used while loading and parsing style sheets in the engine,
|
||||
/// so you should call this function **before** loading document in it.
|
||||
///
|
||||
pub fn set_media_type(&self, media_type: &str) -> Result<()> {
|
||||
let s = s2w!(media_type);
|
||||
let ok = (_API.SciterSetMediaType)(self.hwnd, s.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set media variables (dictionary) for this Sciter instance.
|
||||
///
|
||||
/// By default Sciter window has `"screen:true"` and `"desktop:true"/"handheld:true"` media variables.
|
||||
///
|
||||
/// Media variables can be changed in runtime. This will cause styles of the document to be reset.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use sciter::vmap;
|
||||
/// # let mut host = sciter::Host::attach(0 as sciter::types::HWINDOW);
|
||||
/// host.set_media_vars( &vmap! {
|
||||
/// "screen" => true,
|
||||
/// "handheld" => true,
|
||||
/// }).unwrap();
|
||||
/// ```
|
||||
pub fn set_media_vars(&self, media: &Value) -> Result<()> {
|
||||
let ok = (_API.SciterSetMediaVars)(self.hwnd, media.as_cptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set or append the [master](https://sciter.com/css-extensions-in-h-smile-engine-part-i-style-sets/)
|
||||
/// style sheet styles (**globally**, for all windows).
|
||||
pub fn set_master_css(&self, css: &str, append: bool) -> Result<()> {
|
||||
let s = s2u!(css);
|
||||
let b = s.as_bytes();
|
||||
let n = b.len() as UINT;
|
||||
let ok = if append {
|
||||
(_API.SciterAppendMasterCSS)(b.as_ptr(), n)
|
||||
} else {
|
||||
(_API.SciterSetMasterCSS)(b.as_ptr(), n)
|
||||
};
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set (reset) style sheet of the **current** document.
|
||||
///
|
||||
/// Will reset styles for all elements according to given CSS.
|
||||
pub fn set_window_css(&self, css: &str, base_url: &str, media_type: &str) -> Result<()> {
|
||||
let s = s2u!(css);
|
||||
let url = s2w!(base_url);
|
||||
let media = s2w!(media_type);
|
||||
let b = s.as_bytes();
|
||||
let n = b.len() as UINT;
|
||||
let ok = (_API.SciterSetCSS)(self.hwnd, b.as_ptr(), n, url.as_ptr(), media.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Sciter notification handler.
|
||||
// This comes as free function due to https://github.com/rust-lang/rust/issues/32364
|
||||
extern "system" fn _on_handle_notification<T: HostHandler>(pnm: *mut ::capi::scdef::SCITER_CALLBACK_NOTIFICATION, param: LPVOID) -> UINT
|
||||
{
|
||||
use capi::scdef::{SCITER_NOTIFICATION, SCITER_CALLBACK_NOTIFICATION};
|
||||
|
||||
// reconstruct pointer to Handler
|
||||
let callback = NativeHandler::get_data::<HostCallback<T>>(¶m);
|
||||
let me: &mut T = &mut callback.handler;
|
||||
|
||||
// process notification
|
||||
let nm: &mut SCITER_CALLBACK_NOTIFICATION = unsafe { &mut *pnm };
|
||||
let code: SCITER_NOTIFICATION = unsafe { ::std::mem::transmute(nm.code) };
|
||||
|
||||
|
||||
let result: UINT = match code {
|
||||
SCITER_NOTIFICATION::SC_LOAD_DATA => {
|
||||
let scnm = pnm as *mut SCN_LOAD_DATA;
|
||||
let scnm = unsafe { &mut *scnm };
|
||||
let mut re = me.on_data_load(scnm);
|
||||
if re.is_none() {
|
||||
if let Some(archive) = callback.archive.borrow().as_ref() {
|
||||
let uri = w2s!(scnm.uri);
|
||||
if uri.starts_with("this://app/") {
|
||||
if let Some(data) = archive.get(&uri) {
|
||||
me.data_ready(scnm.hwnd, &uri, data, None);
|
||||
} else {
|
||||
eprintln!("[sciter] error: can't load {:?}", uri);
|
||||
}
|
||||
}
|
||||
re = Some(LOAD_RESULT::LOAD_DEFAULT);
|
||||
}
|
||||
}
|
||||
re.unwrap_or(LOAD_RESULT::LOAD_DEFAULT) as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_DATA_LOADED => {
|
||||
let scnm = pnm as *mut SCN_DATA_LOADED;
|
||||
me.on_data_loaded(unsafe { &mut *scnm } );
|
||||
0 as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_ATTACH_BEHAVIOR => {
|
||||
let scnm = pnm as *mut SCN_ATTACH_BEHAVIOR;
|
||||
let scnm = unsafe { &mut *scnm };
|
||||
let mut re = me.on_attach_behavior(scnm);
|
||||
if !re {
|
||||
let name = u2s!(scnm.name);
|
||||
let behavior = callback.behaviors
|
||||
.borrow()
|
||||
.iter()
|
||||
.find(|x| x.0 == name)
|
||||
.map(|x| x.1());
|
||||
|
||||
if let Some(behavior) = behavior {
|
||||
let boxed = Box::new( BoxedHandler { handler: behavior } );
|
||||
let ptr = Box::into_raw(boxed); // dropped in `_event_handler_behavior_proc`
|
||||
|
||||
scnm.elementProc = ::eventhandler::_event_handler_behavior_proc;
|
||||
scnm.elementTag = ptr as LPVOID;
|
||||
re = true;
|
||||
}
|
||||
}
|
||||
re as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_ENGINE_DESTROYED => {
|
||||
me.on_engine_destroyed();
|
||||
0 as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_GRAPHICS_CRITICAL_FAILURE => {
|
||||
me.on_graphics_critical_failure();
|
||||
0 as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_INVALIDATE_RECT => {
|
||||
let scnm = pnm as *const SCN_INVALIDATE_RECT;
|
||||
me.on_invalidate(unsafe { &*scnm });
|
||||
0 as UINT
|
||||
}
|
||||
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Sciter debug output handler.
|
||||
extern "system" fn _on_debug_notification<T: HostHandler>(param: LPVOID, subsystem: OUTPUT_SUBSYTEMS, severity: OUTPUT_SEVERITY,
|
||||
text: LPCWSTR, _text_length: UINT)
|
||||
{
|
||||
// reconstruct pointer to Handler
|
||||
// let me = unsafe { &mut *(param as *mut HostCallback<T>) };
|
||||
let me = NativeHandler::get_data::<HostCallback<T>>(¶m);
|
||||
let message = ::utf::w2s(text).replace("\r", "\n");
|
||||
me.handler.on_debug_output(subsystem, severity, message.trim_end());
|
||||
}
|
||||
|
||||
|
||||
/// Sciter compressed archive.
|
||||
///
|
||||
/// An archive is produced by `packfolder` tool (from SDK) that creates a single blob with compressed resources.
|
||||
/// It allows to use the same resource pack uniformly across different platforms.
|
||||
///
|
||||
/// For example, app resource files (HTML/CSS/scripts) can be stored in an `assets` folder
|
||||
/// that can be packed into a single archive by calling `packfolder.exe assets target/assets.rc -binary`.
|
||||
/// And later it can be accessed via the Archive API explicitly:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let archived = include_bytes!("target/assets.rc");
|
||||
/// let assets = sciter::host::Archive::open(archived).expect("Unable to load archive.");
|
||||
///
|
||||
/// // access `assets/index.htm`
|
||||
/// let html_data = assets.get("index.htm").unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// or implicitly via the `this://app/` URL after registering the archive via
|
||||
/// [`Window::archive_handler`](../window/struct.Window.html#method.archive_handler):
|
||||
///
|
||||
/// ```rust,ignore
|
||||
///
|
||||
/// let archived = include_bytes!("target/assets.rc");
|
||||
/// let mut frame = sciter::Window::new();
|
||||
/// frame.archive_handler(archived).expect("Unable to load archive");
|
||||
/// frame.load("this://app/index.htm");
|
||||
/// ```
|
||||
pub struct Archive(HSARCHIVE);
|
||||
|
||||
/// Close the archive.
|
||||
impl Drop for Archive {
|
||||
fn drop(&mut self) {
|
||||
(_API.SciterCloseArchive)(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl Archive {
|
||||
/// Open an archive blob.
|
||||
pub fn open(archived: &[u8]) -> Result<Self> {
|
||||
let p = (_API.SciterOpenArchive)(archived.as_ptr(), archived.len() as u32);
|
||||
if !p.is_null() {
|
||||
Ok(Archive(p))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an archive item.
|
||||
///
|
||||
/// Given a path, returns a reference to the contents of an archived item.
|
||||
pub fn get(&self, path: &str) -> Option<&[u8]> {
|
||||
// skip initial part of the path
|
||||
let skip = if path.starts_with("this://app/") {
|
||||
"this://app/".len()
|
||||
} else if path.starts_with("//") {
|
||||
"//".len()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let wname = s2w!(path);
|
||||
let name = &wname[skip..];
|
||||
|
||||
let mut pb = ::std::ptr::null();
|
||||
let mut cb = 0;
|
||||
let ok = (_API.SciterGetArchiveItem)(self.0, name.as_ptr(), &mut pb, &mut cb);
|
||||
if ok != 0 && !pb.is_null() {
|
||||
let data = unsafe { ::std::slice::from_raw_parts(pb, cb as usize) };
|
||||
Some(data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
590
libs/rust-sciter/src/lib.rs
Normal file
590
libs/rust-sciter/src/lib.rs
Normal file
@ -0,0 +1,590 @@
|
||||
// This component uses Sciter Engine,
|
||||
// copyright Terra Informatica Software, Inc.
|
||||
// (http://terrainformatica.com/).
|
||||
|
||||
/*!
|
||||
# Rust bindings library for Sciter engine.
|
||||
|
||||
[Sciter](http://sciter.com) is an embeddable [multiplatform](https://sciter.com/sciter/crossplatform/) HTML/CSS/script engine
|
||||
with GPU accelerated rendering designed to render modern desktop application UI.
|
||||
It's a compact, single dll/dylib/so file (4-8 mb) engine without any additional dependencies.
|
||||
|
||||
Check the [screenshot gallery](https://github.com/oskca/sciter#sciter-desktop-ui-examples)
|
||||
of the desktop UI examples.
|
||||
|
||||
Sciter supports all standard elements defined in HTML5 specification
|
||||
[with some additions](https://sciter.com/developers/for-web-programmers/).
|
||||
CSS is extended to better support the Desktop UI development,
|
||||
e.g. flow and flex units, vertical and horizontal alignment, OS theming.
|
||||
|
||||
[Sciter SDK](https://sciter.com/download/) comes with a demo "browser" with builtin DOM inspector,
|
||||
script debugger and documentation viewer:
|
||||
|
||||
![Sciter tools](https://sciter.com/images/sciter-tools.png)
|
||||
|
||||
Check <https://sciter.com> website and its [documentation resources](https://sciter.com/developers/)
|
||||
for engine principles, architecture and more.
|
||||
|
||||
|
||||
## Brief look:
|
||||
|
||||
Here is a minimal sciter app:
|
||||
|
||||
```no_run
|
||||
extern crate sciter;
|
||||
|
||||
fn main() {
|
||||
let mut frame = sciter::Window::new();
|
||||
frame.load_file("minimal.htm");
|
||||
frame.run_app();
|
||||
}
|
||||
```
|
||||
|
||||
It looks similar like this:
|
||||
|
||||
![Minimal sciter sample](https://i.imgur.com/ojcM5JJ.png)
|
||||
|
||||
Check [rust-sciter/examples](https://github.com/sciter-sdk/rust-sciter/tree/master/examples)
|
||||
folder for more complex usage and module-level sections for the guides about:
|
||||
|
||||
* [Window](window/index.html) creation.
|
||||
* [Behaviors](dom/event/index.html) and event handling.
|
||||
* [DOM](dom/index.html) access methods.
|
||||
* Sciter [Value](value/index.html) interface.
|
||||
|
||||
*/
|
||||
|
||||
#![doc(html_logo_url = "https://sciter.com/screenshots/slide-sciter-osx.png",
|
||||
html_favicon_url = "https://sciter.com/wp-content/themes/sciter/!images/favicon.ico")]
|
||||
|
||||
// documentation test:
|
||||
// #![warn(missing_docs)]
|
||||
|
||||
|
||||
/* Clippy lints */
|
||||
|
||||
#![allow(clippy::needless_return, clippy::let_and_return)] // past habits
|
||||
#![allow(clippy::redundant_field_names)] // since Rust 1.17 and less readable
|
||||
#![allow(clippy::unreadable_literal)] // C++ SDK constants
|
||||
// #![allow(clippy::cast_ptr_alignment)] // 0.0.195 only
|
||||
|
||||
|
||||
/* Macros */
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[macro_use] extern crate objc;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
|
||||
|
||||
#[macro_use] pub mod macros;
|
||||
|
||||
mod capi;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use capi::scdom::{HELEMENT};
|
||||
pub use capi::scdef::{GFX_LAYER, SCRIPT_RUNTIME_FEATURES};
|
||||
|
||||
/* Rust interface */
|
||||
mod platform;
|
||||
mod eventhandler;
|
||||
|
||||
pub mod dom;
|
||||
pub mod graphics;
|
||||
pub mod host;
|
||||
pub mod om;
|
||||
pub mod request;
|
||||
pub mod types;
|
||||
pub mod utf;
|
||||
pub mod value;
|
||||
pub mod video;
|
||||
pub mod window;
|
||||
pub mod windowless;
|
||||
|
||||
pub use dom::Element;
|
||||
pub use dom::event::EventHandler;
|
||||
pub use host::{Archive, Host, HostHandler};
|
||||
pub use value::{Value, FromValue};
|
||||
pub use window::Window;
|
||||
|
||||
|
||||
/// Builder pattern for window creation. See [`window::Builder`](window/struct.Builder.html) documentation.
|
||||
///
|
||||
/// For example,
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// let mut frame = sciter::WindowBuilder::main_window()
|
||||
/// .with_size((800,600))
|
||||
/// .glassy()
|
||||
/// .fixed()
|
||||
/// .create();
|
||||
/// ```
|
||||
pub type WindowBuilder = window::Builder;
|
||||
|
||||
|
||||
/* Loader */
|
||||
pub use capi::scapi::{ISciterAPI};
|
||||
use capi::scgraphics::SciterGraphicsAPI;
|
||||
use capi::screquest::SciterRequestAPI;
|
||||
|
||||
#[cfg(all(windows, not(feature = "dynamic")))]
|
||||
mod ext {
|
||||
#[link(name = "sciter.static")]
|
||||
extern "system" { pub fn SciterAPI() -> *const ::capi::scapi::ISciterAPI; }
|
||||
}
|
||||
|
||||
#[cfg(all(windows, feature = "dynamic"))]
|
||||
mod ext {
|
||||
// Note:
|
||||
// Sciter 4.x shipped with universal "sciter.dll" library for different builds:
|
||||
// bin/32, bin/64, bin/skia32, bin/skia64
|
||||
// However it is quite inconvenient now (e.g. we can not put x64 and x86 builds in %PATH%)
|
||||
//
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
use capi::scapi::{ISciterAPI};
|
||||
use capi::sctypes::{LPCSTR, LPCVOID, BOOL};
|
||||
|
||||
type ApiType = *const ISciterAPI;
|
||||
type FuncType = extern "system" fn () -> *const ISciterAPI;
|
||||
|
||||
pub static mut CUSTOM_DLL_PATH: Option<String> = None;
|
||||
|
||||
extern "system"
|
||||
{
|
||||
fn LoadLibraryA(lpFileName: LPCSTR) -> LPCVOID;
|
||||
fn FreeLibrary(dll: LPCVOID) -> BOOL;
|
||||
fn GetProcAddress(hModule: LPCVOID, lpProcName: LPCSTR) -> LPCVOID;
|
||||
}
|
||||
|
||||
pub fn try_load_library(permanent: bool) -> ::std::result::Result<ApiType, String> {
|
||||
use std::ffi::CString;
|
||||
use std::path::Path;
|
||||
|
||||
fn try_load(path: &Path) -> Option<LPCVOID> {
|
||||
let path = CString::new(format!("{}", path.display())).expect("invalid library path");
|
||||
let dll = unsafe { LoadLibraryA(path.as_ptr()) };
|
||||
if !dll.is_null() {
|
||||
Some(dll)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn in_global() -> Option<LPCVOID> {
|
||||
// modern dll name
|
||||
let mut dll = unsafe { LoadLibraryA(b"sciter.dll\0".as_ptr() as LPCSTR) };
|
||||
if dll.is_null() {
|
||||
// try to load with old names
|
||||
let alternate = if cfg!(target_arch = "x86_64") { b"sciter64.dll\0" } else { b"sciter32.dll\0" };
|
||||
dll = unsafe { LoadLibraryA(alternate.as_ptr() as LPCSTR) };
|
||||
}
|
||||
if !dll.is_null() {
|
||||
Some(dll)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// try specified path first (and only if present)
|
||||
// and several paths to lookup then
|
||||
let dll = if let Some(path) = unsafe { CUSTOM_DLL_PATH.as_ref() } {
|
||||
try_load(Path::new(path))
|
||||
} else {
|
||||
in_global()
|
||||
};
|
||||
|
||||
if let Some(dll) = dll {
|
||||
// get the "SciterAPI" exported symbol
|
||||
let sym = unsafe { GetProcAddress(dll, b"SciterAPI\0".as_ptr() as LPCSTR) };
|
||||
if sym.is_null() {
|
||||
return Err("\"SciterAPI\" function was expected in the loaded library.".to_owned());
|
||||
}
|
||||
|
||||
if !permanent {
|
||||
unsafe { FreeLibrary(dll) };
|
||||
return Ok(0 as ApiType);
|
||||
}
|
||||
|
||||
let get_api: FuncType = unsafe { std::mem::transmute(sym) };
|
||||
return Ok(get_api());
|
||||
}
|
||||
let sdkbin = if cfg!(target_arch = "x86_64") { "bin/64" } else { "bin/32" };
|
||||
let msg = format!("Please verify that Sciter SDK is installed and its binaries (from SDK/{}) are available in PATH.", sdkbin);
|
||||
Err(format!("error: '{}' was not found neither in PATH nor near the current executable.\n {}", "sciter.dll", msg))
|
||||
}
|
||||
|
||||
pub unsafe fn SciterAPI() -> *const ISciterAPI {
|
||||
match try_load_library(true) {
|
||||
Ok(api) => api,
|
||||
Err(error) => panic!(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "dynamic", unix))]
|
||||
mod ext {
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
extern crate libc;
|
||||
|
||||
pub static mut CUSTOM_DLL_PATH: Option<String> = None;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
const DLL_NAMES: &'static [&'static str] = &[ "libsciter-gtk.so" ];
|
||||
|
||||
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
||||
const DLL_NAMES: &'static [&'static str] = &[ "sciter-osx-64.dylib" ];
|
||||
|
||||
use capi::scapi::ISciterAPI;
|
||||
use capi::sctypes::{LPVOID, LPCSTR};
|
||||
|
||||
type FuncType = extern "system" fn () -> *const ISciterAPI;
|
||||
type ApiType = *const ISciterAPI;
|
||||
|
||||
|
||||
pub fn try_load_library(permanent: bool) -> ::std::result::Result<ApiType, String> {
|
||||
use std::ffi::CString;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
|
||||
// Try to load the library from a specified absolute path.
|
||||
fn try_load(path: &Path) -> Option<LPVOID> {
|
||||
let bytes = path.as_os_str().as_bytes();
|
||||
if let Ok(cstr) = CString::new(bytes) {
|
||||
let dll = unsafe { libc::dlopen(cstr.as_ptr(), libc::RTLD_LOCAL | libc::RTLD_LAZY) };
|
||||
if !dll.is_null() {
|
||||
return Some(dll)
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// Try to find a library (by one of its names) in a specified path.
|
||||
fn try_load_from(dir: Option<&Path>) -> Option<LPVOID> {
|
||||
|
||||
let dll = DLL_NAMES.iter()
|
||||
.map(|name| {
|
||||
let mut path = dir.map(Path::to_owned).unwrap_or(PathBuf::new());
|
||||
path.push(name);
|
||||
path
|
||||
})
|
||||
.map(|path| try_load(&path))
|
||||
.filter(|dll| dll.is_some())
|
||||
.nth(0)
|
||||
.map(|o| o.unwrap());
|
||||
|
||||
if dll.is_some() {
|
||||
return dll;
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// Try to load from the current directory.
|
||||
fn in_current_dir() -> Option<LPVOID> {
|
||||
if let Ok(dir) = ::std::env::current_exe() {
|
||||
if let Some(dir) = dir.parent() {
|
||||
let dll = try_load_from(Some(dir));
|
||||
if dll.is_some() {
|
||||
return dll;
|
||||
}
|
||||
|
||||
if cfg!(target_os = "macos") {
|
||||
// "(bundle folder)/Contents/Frameworks/"
|
||||
let mut path = dir.to_owned();
|
||||
path.push("../Frameworks/sciter-osx-64.dylib");
|
||||
return try_load(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// Try to load indirectly via `dlopen("dll.so")`.
|
||||
fn in_global() -> Option<LPVOID> {
|
||||
try_load_from(None)
|
||||
}
|
||||
|
||||
// Try to find in $PATH.
|
||||
fn in_paths() -> Option<LPVOID> {
|
||||
use std::env;
|
||||
if let Some(paths) = env::var_os("PATH") {
|
||||
for path in env::split_paths(&paths) {
|
||||
if let Some(dll) = try_load_from(Some(&path)) {
|
||||
return Some(dll);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// try specified path first (and only if present)
|
||||
// and several paths to lookup then
|
||||
let dll = if let Some(path) = unsafe { CUSTOM_DLL_PATH.as_ref() } {
|
||||
try_load(Path::new(path))
|
||||
} else {
|
||||
in_current_dir().or_else(in_paths).or_else(in_global)
|
||||
};
|
||||
|
||||
if let Some(dll) = dll {
|
||||
// get the "SciterAPI" exported symbol
|
||||
let sym = unsafe { libc::dlsym(dll, b"SciterAPI\0".as_ptr() as LPCSTR) };
|
||||
if sym.is_null() {
|
||||
return Err("\"SciterAPI\" function was expected in the loaded library.".to_owned());
|
||||
}
|
||||
|
||||
if !permanent {
|
||||
unsafe { libc::dlclose(dll) };
|
||||
return Ok(0 as ApiType);
|
||||
}
|
||||
|
||||
let get_api: FuncType = unsafe { std::mem::transmute(sym) };
|
||||
return Ok(get_api());
|
||||
}
|
||||
|
||||
let sdkbin = if cfg!(target_os = "macos") { "bin.osx" } else { "bin.lnx" };
|
||||
let msg = format!("Please verify that Sciter SDK is installed and its binaries (from {}) are available in PATH.", sdkbin);
|
||||
Err(format!("error: '{}' was not found neither in PATH nor near the current executable.\n {}", DLL_NAMES[0], msg))
|
||||
}
|
||||
|
||||
pub fn SciterAPI() -> *const ISciterAPI {
|
||||
match try_load_library(true) {
|
||||
Ok(api) => api,
|
||||
Err(error) => panic!(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(all(target_os = "linux", not(feature = "dynamic")))]
|
||||
mod ext {
|
||||
// Note:
|
||||
// Since 4.1.4 library name has been changed to "libsciter-gtk" (without 32/64 suffix).
|
||||
// Since 3.3.1.6 library name was changed to "libsciter".
|
||||
// However CC requires `-l sciter` form.
|
||||
#[link(name = "sciter-gtk")]
|
||||
extern "system" { pub fn SciterAPI() -> *const ::capi::scapi::ISciterAPI; }
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "macos", target_arch = "x86_64", not(feature = "dynamic")))]
|
||||
mod ext {
|
||||
#[link(name = "sciter-osx-64", kind = "dylib")]
|
||||
extern "system" { pub fn SciterAPI() -> *const ::capi::scapi::ISciterAPI; }
|
||||
}
|
||||
|
||||
/// Getting ISciterAPI reference, can be used for manual API calling.
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn SciterAPI<'a>() -> &'a ISciterAPI {
|
||||
let ap = unsafe {
|
||||
if cfg!(feature="extension") {
|
||||
// TODO: it's not good to raise a panic inside `lazy_static!`,
|
||||
// because it wents into recursive panicing.
|
||||
//
|
||||
// Somehow, `cargo test --all` tests all the features,
|
||||
// also sometimes it comes even without `cfg!(test)`.
|
||||
// Well, the culprit is "examples/extensions" which uses the "extension" feature,
|
||||
// but how on earth it builds without `cfg(test)`?
|
||||
//
|
||||
if cfg!(test) {
|
||||
&*ext::SciterAPI()
|
||||
} else {
|
||||
EXT_API
|
||||
//.or_else(|| Some(&*ext::SciterAPI()))
|
||||
.expect("Sciter API is not available yet, call `sciter::set_api()` first.")
|
||||
}
|
||||
} else {
|
||||
&*ext::SciterAPI()
|
||||
}
|
||||
};
|
||||
|
||||
let abi_version = ap.version;
|
||||
|
||||
if cfg!(feature = "windowless") {
|
||||
assert!(abi_version >= 0x0001_0001, "Incompatible Sciter build and \"windowless\" feature");
|
||||
}
|
||||
if cfg!(not(feature = "windowless")) {
|
||||
assert!(abi_version < 0x0001_0000, "Incompatible Sciter build and \"windowless\" feature");
|
||||
}
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
||||
/// Getting ISciterAPI reference, can be used for manual API calling.
|
||||
///
|
||||
/// Bypasses ABI compatability checks.
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn SciterAPI_unchecked<'a>() -> &'a ISciterAPI {
|
||||
let ap = unsafe {
|
||||
if cfg!(feature="extension") {
|
||||
EXT_API.expect("Sciter API is not available yet, call `sciter::set_api()` first.")
|
||||
} else {
|
||||
&*ext::SciterAPI()
|
||||
}
|
||||
};
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref _API: &'static ISciterAPI = SciterAPI();
|
||||
static ref _GAPI: &'static SciterGraphicsAPI = {
|
||||
if version_num() < 0x0401_0A00 {
|
||||
panic!("Graphics API is incompatible since 4.1.10 (your version is {})", version());
|
||||
}
|
||||
unsafe { &*(SciterAPI().GetSciterGraphicsAPI)() }
|
||||
};
|
||||
static ref _RAPI: &'static SciterRequestAPI = unsafe { &*(SciterAPI().GetSciterRequestAPI)() };
|
||||
}
|
||||
|
||||
/// Set a custom path to the Sciter dynamic library.
|
||||
///
|
||||
/// Note: Must be called first before any other function.
|
||||
///
|
||||
/// Returns error if the specified library can not be loaded.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// if sciter::set_library("~/lib/sciter/bin.gtk/x64/libsciter-gtk.so").is_ok() {
|
||||
/// println!("loaded Sciter version {}", sciter::version());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn set_library(custom_path: &str) -> ::std::result::Result<(), String> {
|
||||
#[cfg(not(feature = "dynamic"))]
|
||||
fn set_impl(_: &str) -> ::std::result::Result<(), String> {
|
||||
Err("Don't use `sciter::set_library()` in static builds.\n Build with the feature \"dynamic\" instead.".to_owned())
|
||||
}
|
||||
|
||||
#[cfg(feature = "dynamic")]
|
||||
fn set_impl(path: &str) -> ::std::result::Result<(), String> {
|
||||
unsafe {
|
||||
ext::CUSTOM_DLL_PATH = Some(path.to_owned());
|
||||
}
|
||||
ext::try_load_library(false).map(|_| ())
|
||||
}
|
||||
|
||||
set_impl(custom_path)
|
||||
}
|
||||
|
||||
static mut EXT_API: Option<&'static ISciterAPI> = None;
|
||||
|
||||
/// Set the Sciter API coming from `SciterLibraryInit`.
|
||||
///
|
||||
/// Note: Must be called first before any other function.
|
||||
pub fn set_host_api(api: &'static ISciterAPI) {
|
||||
if cfg!(feature="extension") {
|
||||
unsafe {
|
||||
EXT_API.replace(api);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sciter engine version number (e.g. `0x03030200`).
|
||||
///
|
||||
/// Note: does not return the `build` part because it doesn't fit in `0..255` byte range.
|
||||
/// Use [`sciter::version()`](fn.version.html) instead which returns the complete version string.
|
||||
pub fn version_num() -> u32 {
|
||||
use types::BOOL;
|
||||
let v1 = (_API.SciterVersion)(true as BOOL);
|
||||
let v2 = (_API.SciterVersion)(false as BOOL);
|
||||
let (major, minor, revision, _build) = (v1 >> 16 & 0xFF, v1 & 0xFF, v2 >> 16 & 0xFF, v2 & 0xFF);
|
||||
let num = (major << 24) | (minor << 16) | (revision << 8);
|
||||
// let num = ((v1 >> 16) << 24) | ((v1 & 0xFFFF) << 16) | ((v2 >> 16) << 8) | (v2 & 0xFFFF);
|
||||
return num;
|
||||
}
|
||||
|
||||
/// Sciter engine version string (e.g. "`3.3.2.0`").
|
||||
pub fn version() -> String {
|
||||
use types::BOOL;
|
||||
let v1 = (_API.SciterVersion)(true as BOOL);
|
||||
let v2 = (_API.SciterVersion)(false as BOOL);
|
||||
let num = [v1 >> 16, v1 & 0xFFFF, v2 >> 16, v2 & 0xFFFF];
|
||||
let version = format!("{}.{}.{}.{}", num[0], num[1], num[2], num[3]);
|
||||
return version;
|
||||
}
|
||||
|
||||
/// Sciter API version.
|
||||
///
|
||||
/// Returns:
|
||||
///
|
||||
/// * `0x0000_0001` for regular builds, `0x0001_0001` for windowless builds.
|
||||
/// * `0x0000_0002` since 4.4.2.14 (a breaking change in assets with [SOM builds](https://sciter.com/native-code-exposure-to-script/))
|
||||
/// * `0x0000_0003` since 4.4.2.16
|
||||
/// * `0x0000_0004` since 4.4.2.17 (a breaking change in SOM passport)
|
||||
/// * `0x0000_0005` since 4.4.3.20 (a breaking change in `INITIALIZATION_PARAMS`, SOM in event handlers fix)
|
||||
/// * `0x0000_0006` since 4.4.3.24 (TIScript native API is gone, use SOM instead)
|
||||
///
|
||||
/// Since 4.4.0.3.
|
||||
pub fn api_version() -> u32 {
|
||||
_API.version
|
||||
}
|
||||
|
||||
/// Returns true for windowless builds.
|
||||
pub fn is_windowless() -> bool {
|
||||
api_version() >= 0x0001_0001
|
||||
}
|
||||
|
||||
/// Various global Sciter engine options.
|
||||
///
|
||||
/// Used by [`sciter::set_options()`](fn.set_options.html).
|
||||
///
|
||||
/// See also [per-window options](window/enum.Options.html).
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum RuntimeOptions<'a> {
|
||||
|
||||
/// global; value: the full path to the Sciter dynamic library (dll/dylib/so),
|
||||
/// must be called before any other Sciter function.
|
||||
LibraryPath(&'a str),
|
||||
/// global; value: [`GFX_LAYER`](enum.GFX_LAYER.html), must be called before any window creation.
|
||||
GfxLayer(GFX_LAYER),
|
||||
/// global; value: `true` - the engine will use a "unisex" theme that is common for all platforms.
|
||||
/// That UX theme is not using OS primitives for rendering input elements.
|
||||
/// Use it if you want exactly the same (modulo fonts) look-n-feel on all platforms.
|
||||
UxTheming(bool),
|
||||
/// global or per-window; enables Sciter Inspector for all windows, must be called before any window creation.
|
||||
DebugMode(bool),
|
||||
/// global or per-window; value: combination of [`SCRIPT_RUNTIME_FEATURES`](enum.SCRIPT_RUNTIME_FEATURES.html) flags.
|
||||
///
|
||||
/// Note that these features have been disabled by default
|
||||
/// since [4.2.5.0](https://rawgit.com/c-smile/sciter-sdk/7036a9c7912ac30d9f369d9abb87b278d2d54c6d/logfile.htm).
|
||||
ScriptFeatures(u8),
|
||||
/// global; value: milliseconds, connection timeout of http client.
|
||||
ConnectionTimeout(u32),
|
||||
/// global; value: `0` - drop connection, `1` - use builtin dialog, `2` - accept connection silently.
|
||||
OnHttpsError(u8),
|
||||
// global; value: json with GPU black list, see the `gpu-blacklist.json` resource.
|
||||
// Not used in Sciter 4, in fact: https://sciter.com/forums/topic/how-to-use-the-gpu-blacklist/#post-59338
|
||||
// GpuBlacklist(&'a str),
|
||||
/// global; value: script source to be loaded into each view before any other script execution.
|
||||
InitScript(&'a str),
|
||||
/// global; value - max request length in megabytes (1024*1024 bytes), since 4.3.0.15.
|
||||
MaxHttpDataLength(usize),
|
||||
}
|
||||
|
||||
/// Set various global Sciter engine options, see the [`RuntimeOptions`](enum.RuntimeOptions.html).
|
||||
pub fn set_options(options: RuntimeOptions) -> std::result::Result<(), ()> {
|
||||
use RuntimeOptions::*;
|
||||
use capi::scdef::SCITER_RT_OPTIONS::*;
|
||||
let (option, value) = match options {
|
||||
ConnectionTimeout(ms) => (SCITER_CONNECTION_TIMEOUT, ms as usize),
|
||||
OnHttpsError(behavior) => (SCITER_HTTPS_ERROR, behavior as usize),
|
||||
// GpuBlacklist(json) => (SCITER_SET_GPU_BLACKLIST, json.as_bytes().as_ptr() as usize),
|
||||
InitScript(script) => (SCITER_SET_INIT_SCRIPT, script.as_bytes().as_ptr() as usize),
|
||||
ScriptFeatures(mask) => (SCITER_SET_SCRIPT_RUNTIME_FEATURES, mask as usize),
|
||||
GfxLayer(backend) => (SCITER_SET_GFX_LAYER, backend as usize),
|
||||
DebugMode(enable) => (SCITER_SET_DEBUG_MODE, enable as usize),
|
||||
UxTheming(enable) => (SCITER_SET_UX_THEMING, enable as usize),
|
||||
MaxHttpDataLength(value) => (SCITER_SET_MAX_HTTP_DATA_LENGTH, value),
|
||||
LibraryPath(path) => {
|
||||
return set_library(path).map_err(|_|());
|
||||
}
|
||||
};
|
||||
let ok = (_API.SciterSetOption)(std::ptr::null_mut(), option, value);
|
||||
if ok != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
264
libs/rust-sciter/src/macros.rs
Normal file
264
libs/rust-sciter/src/macros.rs
Normal file
@ -0,0 +1,264 @@
|
||||
//! Macros
|
||||
|
||||
/// Rust string to UTF-8 conversion. See also `utf::u2s`.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let cstr = s2u!("hello"); // ffi::CString
|
||||
/// libc::printf("%hs", cstr.as_ptr());
|
||||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! s2u {
|
||||
($s:expr) => ( $crate::utf::s2un($s.as_ref()).0 )
|
||||
}
|
||||
|
||||
/// Rust string to UTF-8 conversion. See also `utf::u2s`.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let (cstr, len) = s2un!("hello"); // ffi::CString
|
||||
/// libc::printf("%.*hs", len, cstr.as_ptr());
|
||||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! s2un {
|
||||
($s:expr) => ( $crate::utf::s2un($s.as_ref()) )
|
||||
}
|
||||
|
||||
|
||||
/// Rust string to UTF-16 conversion. See also `utf::w2s`.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let cwstr = s2w!("hello"); // Vec<u16>
|
||||
/// libc::printf("%ws", cwstr.as_ptr());
|
||||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! s2w {
|
||||
($s:expr) => ( $crate::utf::s2vec($s.as_ref()) )
|
||||
}
|
||||
|
||||
/// Rust string to UTF-16 conversion. See also `utf::w2s`.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let (cwstr, len) = s2wn!("hello"); // Vec<u16>
|
||||
/// libc::printf("%.*ws", len, cwstr.as_ptr());
|
||||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! s2wn {
|
||||
($s:expr) => ( $crate::utf::s2vecn($s.as_ref()) )
|
||||
}
|
||||
|
||||
|
||||
/// UTF-16 to `String` conversion.
|
||||
#[macro_export]
|
||||
macro_rules! w2s {
|
||||
($s:expr) => ( $crate::utf::w2s($s) )
|
||||
}
|
||||
|
||||
|
||||
/// UTF-8 to `String` conversion.
|
||||
#[macro_export]
|
||||
macro_rules! u2s {
|
||||
($s:expr) => ( $crate::utf::u2s($s) )
|
||||
}
|
||||
|
||||
|
||||
/// Pack arguments to call the Sciter script function.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! pack_args {
|
||||
() => { $crate::value::Value::pack_args(&[]) };
|
||||
|
||||
( $($s:expr),* ) => {
|
||||
{
|
||||
let args = [
|
||||
$(
|
||||
$crate::value::Value::from($s)
|
||||
),*
|
||||
];
|
||||
$crate::value::Value::pack_args(&args)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Pack arguments into a `[Value]` array to call Sciter script functions.
|
||||
///
|
||||
/// Used in [`Element.call_function()`](dom/struct.Element.html#method.call_function),
|
||||
/// [`Element.call_method()`](dom/struct.Element.html#method.call_method),
|
||||
/// [`Host.call_function()`](host/struct.Host.html#method.call_function),
|
||||
/// [`Value.call()`](value/struct.Value.html#method.call).
|
||||
///
|
||||
/// ## Example:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// # #![doc(test(no_crate_inject))]
|
||||
/// # #[macro_use] extern crate sciter;
|
||||
/// let value = sciter::Value::new();
|
||||
/// let result = value.call(None, &make_args!(1, "2", 3.0), Some(file!())).unwrap();
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! make_args {
|
||||
() => { { let args : [$crate::value::Value; 0] = []; args } };
|
||||
|
||||
( $($s:expr),* ) => {
|
||||
{
|
||||
let args = [
|
||||
$(
|
||||
$crate::value::Value::from($s)
|
||||
),*
|
||||
];
|
||||
args
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
/// Declare handle type (native pointer).
|
||||
macro_rules! MAKE_HANDLE {
|
||||
($(#[$attrs:meta])* $name:ident, $inner:ident) => {
|
||||
#[repr(C)] #[doc(hidden)]
|
||||
pub struct $inner { _unused: usize }
|
||||
$(#[$attrs])*
|
||||
pub type $name = *mut $inner;
|
||||
};
|
||||
}
|
||||
|
||||
/// Dispatch script calls to native code. Used in [`dom::EventHandler`](dom/event/trait.EventHandler.html) implementations.
|
||||
///
|
||||
/// This macro generates a new function which dispatches incoming script calls to the corresponding native functions
|
||||
/// with arguments unpacking and type checking.
|
||||
///
|
||||
/// Note: unstable, will be improved.
|
||||
#[macro_export]
|
||||
macro_rules! dispatch_script_call {
|
||||
|
||||
(
|
||||
$(
|
||||
fn $name:ident ( $( $argt:ident ),* );
|
||||
)*
|
||||
) => {
|
||||
|
||||
fn dispatch_script_call(&mut self, _root: $crate::HELEMENT, name: &str, argv: &[$crate::Value]) -> Option<$crate::Value>
|
||||
{
|
||||
match name {
|
||||
$(
|
||||
stringify!($name) => {
|
||||
|
||||
// args count
|
||||
let mut _i = 0;
|
||||
$(
|
||||
let _: $argt;
|
||||
_i += 1;
|
||||
)*
|
||||
let argc = _i;
|
||||
|
||||
if argv.len() != argc {
|
||||
return Some($crate::Value::error(&format!("{} error: {} of {} arguments provided.", stringify!($name), argv.len(), argc)));
|
||||
}
|
||||
|
||||
// call function
|
||||
let mut _i = 0;
|
||||
let rv = self.$name(
|
||||
$(
|
||||
{
|
||||
match $crate::FromValue::from_value(&argv[_i]) {
|
||||
Some(arg) => { _i += 1; arg },
|
||||
None => {
|
||||
// invalid type
|
||||
return Some($crate::Value::error(&format!("{} error: invalid type of {} argument ({} expected, {:?} provided).",
|
||||
stringify!($name), _i, stringify!($argt), argv[_i])));
|
||||
},
|
||||
}
|
||||
}
|
||||
),*
|
||||
);
|
||||
|
||||
// return result value
|
||||
return Some($crate::Value::from(rv));
|
||||
},
|
||||
)*
|
||||
|
||||
_ => ()
|
||||
};
|
||||
|
||||
// script call not handled
|
||||
return None;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// Create a `sciter::Value` (of map type) from a list of key-value pairs.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate sciter;
|
||||
/// # fn main() {
|
||||
/// let v: sciter::Value = vmap! {
|
||||
/// "one" => 1,
|
||||
/// "two" => 2.0,
|
||||
/// "three" => "",
|
||||
/// };
|
||||
/// assert!(v.is_map());
|
||||
/// assert_eq!(v.len(), 3);
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! vmap {
|
||||
( $($key:expr => $value:expr,)+ ) => { vmap!($($key => $value),+) };
|
||||
( $($key:expr => $value:expr),* ) => {
|
||||
{
|
||||
let mut _v = $crate::Value::map();
|
||||
$(
|
||||
_v.set_item($key, $value);
|
||||
)*
|
||||
_v
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Creates a `sciter::Value` (of array type) containing the arguments.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate sciter;
|
||||
/// # fn main() {
|
||||
/// let v: sciter::Value = varray![1, 2.0, "three"];
|
||||
/// assert!(v.is_array());
|
||||
/// assert_eq!(v.len(), 3);
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! varray {
|
||||
( $($value:expr,)+ ) => { varray!($($value),+) };
|
||||
( $($value:expr),* ) => {
|
||||
{
|
||||
// args count
|
||||
let mut _i = 0;
|
||||
$(
|
||||
let _ = &$value;
|
||||
_i += 1;
|
||||
)*
|
||||
let argc = _i;
|
||||
let mut _v = $crate::Value::array(argc);
|
||||
let mut _i = 0;
|
||||
$(
|
||||
_v.set(_i, $value);
|
||||
_i += 1;
|
||||
)*
|
||||
_v
|
||||
}
|
||||
};
|
||||
}
|
271
libs/rust-sciter/src/om.rs
Normal file
271
libs/rust-sciter/src/om.rs
Normal file
@ -0,0 +1,271 @@
|
||||
/*! Sciter Object Model (SOM passport).
|
||||
|
||||
See [Native code exposure to script](http://sciter.com/native-code-exposure-to-script/)
|
||||
and [Sciter Object Model](http://sciter.com/developers/for-native-gui-programmers/sciter-object-model/) blog articles.
|
||||
|
||||
*/
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
use capi::sctypes::{LPVOID, LPCSTR};
|
||||
pub use capi::scom::*;
|
||||
|
||||
|
||||
/// Get the index of an interned string.
|
||||
pub fn atom(name: &str) -> som_atom_t {
|
||||
let s = s2u!(name);
|
||||
(crate::_API.SciterAtomValue)(s.as_ptr())
|
||||
}
|
||||
|
||||
/// Get the value of an interned string.
|
||||
pub fn atom_name(id: som_atom_t) -> Option<String> {
|
||||
let mut s = String::new();
|
||||
let ok = (crate::_API.SciterAtomNameCB)(id, crate::utf::store_astr, &mut s as *mut _ as LPVOID);
|
||||
if ok != 0 {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Something that has a SOM passport.
|
||||
///
|
||||
/// However, since we can't call extern functions in static object initialization,
|
||||
/// in order to use [`atom("name")`](fn.atom.html) we have to initializa the passport in run time
|
||||
/// and return a reference to it via [`Box::leak()`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.leak).
|
||||
pub trait Passport {
|
||||
/// A static reference to the passport that describes an asset.
|
||||
fn get_passport(&self) -> &'static som_passport_t;
|
||||
}
|
||||
|
||||
|
||||
/// A non-owning pointer to a native object.
|
||||
pub struct IAssetRef<T> {
|
||||
asset: *mut som_asset_t,
|
||||
ty: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Clone for IAssetRef<T> {
|
||||
fn clone(&self) -> Self {
|
||||
self.add_ref();
|
||||
Self {
|
||||
asset: self.asset,
|
||||
ty: self.ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for IAssetRef<T> {
|
||||
fn drop(&mut self) {
|
||||
self.release();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::fmt::Debug for IAssetRef<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
// the current reference count
|
||||
self.add_ref();
|
||||
let rc = self.release();
|
||||
|
||||
let name = self::atom_name(self.get_passport().name);
|
||||
write!(f, "Asset({}):{}", name.unwrap_or_default(), rc)
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a reference from a managed asset.
|
||||
impl<T> From<Box<IAsset<T>>> for IAssetRef<T> {
|
||||
fn from(asset: Box<IAsset<T>>) -> Self {
|
||||
Self::from_raw(IAsset::into_raw(asset))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IAssetRef<T> {
|
||||
/// Get the vtable of an asset.
|
||||
fn isa(&self) -> &'static som_asset_class_t {
|
||||
unsafe { (*self.asset).isa }
|
||||
}
|
||||
|
||||
/// Increment the reference count of an asset and returns the new value.
|
||||
fn add_ref(&self) -> i32 {
|
||||
(self.isa().add_ref)(self.asset)
|
||||
}
|
||||
|
||||
/// Decrement the reference count of an asset and returns the new value.
|
||||
fn release(&self) -> i32 {
|
||||
(self.isa().release)(self.asset)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IAssetRef<T> {
|
||||
/// Construct from a raw pointer, incrementing the reference count.
|
||||
pub fn from_raw(asset: *mut som_asset_t) -> Self {
|
||||
eprintln!("IAssetRef<{}>::from({:?})", std::any::type_name::<T>(), asset);
|
||||
assert!(asset.is_null() == false);
|
||||
let me = Self {
|
||||
asset,
|
||||
ty: std::marker::PhantomData,
|
||||
};
|
||||
me.add_ref();
|
||||
me
|
||||
}
|
||||
|
||||
/// Return the raw pointer, releasing the reference count.
|
||||
pub fn into_raw(asset: IAssetRef<T>) -> *mut som_asset_t {
|
||||
// decrement reference count
|
||||
asset.release();
|
||||
|
||||
// get the pointer and forget about this wrapper
|
||||
let ptr = asset.asset;
|
||||
std::mem::forget(asset);
|
||||
|
||||
ptr
|
||||
}
|
||||
|
||||
/// Get the underlaying pointer.
|
||||
pub fn as_ptr(&self) -> *mut som_asset_t {
|
||||
self.asset
|
||||
}
|
||||
|
||||
/// Get a reference to the underlaying pointer.
|
||||
#[doc(hidden)]
|
||||
pub fn as_ref(&self) -> &som_asset_t {
|
||||
// TODO: do we need this?
|
||||
unsafe { & *self.asset }
|
||||
}
|
||||
|
||||
/// Get the passport of the asset.
|
||||
pub fn get_passport(&self) -> &som_passport_t {
|
||||
// TODO: do we need this?
|
||||
let ptr = (self.isa().get_passport)(self.asset);
|
||||
unsafe { & *ptr }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// An owned pointer to a wrapped native object.
|
||||
#[repr(C)]
|
||||
pub struct IAsset<T> {
|
||||
// NB: should be the first member here
|
||||
// in order to `*mut IAsset as *mut som_asset_t` work
|
||||
asset: som_asset_t,
|
||||
refc: AtomicI32,
|
||||
passport: Option<&'static som_passport_t>,
|
||||
data: T,
|
||||
}
|
||||
|
||||
/// Make the object to be accessible as other global objects in TIScript.
|
||||
pub fn set_global<T>(asset: IAssetRef<T>) {
|
||||
let ptr = asset.as_ptr();
|
||||
// eprintln!("IAsset<{}>: {:?}", std::any::type_name::<T>(), ptr);
|
||||
(crate::_API.SciterSetGlobalAsset)(ptr);
|
||||
}
|
||||
|
||||
/// Make the object to be accessible as other global objects in TIScript.
|
||||
pub fn into_global<T>(asset: Box<IAsset<T>>) {
|
||||
let ptr = IAsset::into_raw(asset);
|
||||
// eprintln!("IAsset<{}>: {:?}", std::any::type_name::<T>(), ptr);
|
||||
(crate::_API.SciterSetGlobalAsset)(ptr);
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for IAsset<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::DerefMut for IAsset<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for IAsset<T> {
|
||||
fn drop(&mut self) {
|
||||
let rc = self.refc.load(Ordering::SeqCst);
|
||||
if rc != 0 {
|
||||
eprintln!("asset<{}>::drop with {} references alive", std::any::type_name::<T>(), rc);
|
||||
}
|
||||
assert_eq!(rc, 0);
|
||||
// allocated in `iasset::new()`
|
||||
let ptr = self.asset.isa as *const som_asset_class_t;
|
||||
let ptr = unsafe { Box::from_raw(ptr as *mut som_asset_class_t) };
|
||||
drop(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IAsset<T> {
|
||||
/// Cast the pointer to a managed asset reference.
|
||||
pub fn from_raw(thing: &*mut som_asset_t) -> &mut IAsset<T> {
|
||||
assert!(thing.is_null() == false);
|
||||
unsafe { &mut *(*thing as *mut IAsset<T>) }
|
||||
}
|
||||
|
||||
/// Release the pointer.
|
||||
fn into_raw(asset: Box<IAsset<T>>) -> *mut som_asset_t {
|
||||
let p = Box::into_raw(asset);
|
||||
p as *mut som_asset_t
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Passport> IAsset<T> {
|
||||
/// Wrap the object into a managed asset.
|
||||
pub fn new(data: T) -> Box<Self> {
|
||||
// will be freed in `iasset<T>::drop()`
|
||||
let isa = Box::new(Self::class());
|
||||
|
||||
let me = Self {
|
||||
asset: som_asset_t { isa: Box::leak(isa) },
|
||||
refc: Default::default(),
|
||||
passport: None,
|
||||
data,
|
||||
};
|
||||
Box::new(me)
|
||||
}
|
||||
|
||||
fn class() -> som_asset_class_t {
|
||||
extern "C" fn asset_add_ref<T>(thing: *mut som_asset_t) -> i32 {
|
||||
{
|
||||
let me = IAsset::<T>::from_raw(&thing);
|
||||
let t = me.refc.fetch_add(1, Ordering::SeqCst) + 1;
|
||||
// eprintln!("iasset<T>::add_ref() -> {}", t);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
extern "C" fn asset_release<T>(thing: *mut som_asset_t) -> i32 {
|
||||
let t = {
|
||||
let me = IAsset::<T>::from_raw(&thing);
|
||||
me.refc.fetch_sub(1, Ordering::SeqCst) - 1
|
||||
};
|
||||
// eprintln!("iasset<T>::release() -> {}", t);
|
||||
if t == 0 {
|
||||
// eprintln!("iasset<T>::drop()");
|
||||
let me = unsafe { Box::from_raw(thing as *mut IAsset<T>) };
|
||||
drop(me);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
extern "C" fn asset_get_interface<T>(_thing: *mut som_asset_t, name: LPCSTR, _out: *mut *mut som_asset_t) -> bool {
|
||||
let name = u2s!(name);
|
||||
eprintln!("iasset<T>::get_interface({}) is not implemented.", name);
|
||||
return false;
|
||||
}
|
||||
extern "C" fn asset_get_passport<T: Passport>(thing: *mut som_asset_t) -> *const som_passport_t
|
||||
{
|
||||
// here we cache the returned reference in order not to allocate things again
|
||||
let me = IAsset::<T>::from_raw(&thing);
|
||||
if me.passport.is_none() {
|
||||
// eprintln!("asset_get_passport<{}>: {:?}", std::any::type_name::<T>(), thing);
|
||||
me.passport = Some(me.data.get_passport());
|
||||
}
|
||||
let ps = me.passport.as_ref().unwrap();
|
||||
return *ps;
|
||||
}
|
||||
|
||||
som_asset_class_t {
|
||||
add_ref: asset_add_ref::<T>,
|
||||
release: asset_release::<T>,
|
||||
get_interface: asset_get_interface::<T>,
|
||||
get_passport: asset_get_passport::<T>,
|
||||
}
|
||||
}
|
||||
}
|
480
libs/rust-sciter/src/platform.rs
Normal file
480
libs/rust-sciter/src/platform.rs
Normal file
@ -0,0 +1,480 @@
|
||||
//! Platform-dependent windows support.
|
||||
|
||||
use capi::sctypes::*;
|
||||
|
||||
|
||||
pub trait BaseWindow {
|
||||
|
||||
fn create(&mut self, rc: RECT, flags: UINT, parent: HWINDOW) -> HWINDOW;
|
||||
|
||||
fn get_hwnd(&self) -> HWINDOW;
|
||||
|
||||
fn collapse(&self, hide: bool);
|
||||
fn expand(&self, maximize: bool);
|
||||
fn dismiss(&self);
|
||||
|
||||
fn set_title(&mut self, title: &str);
|
||||
fn get_title(&self) -> String;
|
||||
|
||||
fn run_app(&self);
|
||||
fn quit_app(&self);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
mod windows {
|
||||
|
||||
use ::{_API};
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::*;
|
||||
|
||||
|
||||
#[link(name="user32")]
|
||||
extern "system"
|
||||
{
|
||||
fn ShowWindow(hwnd: HWINDOW, show: INT) -> BOOL;
|
||||
fn PostMessageW(hwnd: HWINDOW, msg: UINT, w: WPARAM, l: LPARAM) -> BOOL;
|
||||
fn SetWindowTextW(hwnd: HWINDOW, s: LPCWSTR) -> BOOL;
|
||||
fn GetWindowTextLengthW(hwnd: HWINDOW) -> INT;
|
||||
fn GetWindowTextW(hwnd: HWINDOW, s: LPWSTR, l: INT) -> INT;
|
||||
fn GetMessageW(msg: LPMSG, hwnd: HWINDOW, min: UINT, max: UINT) -> BOOL;
|
||||
fn DispatchMessageW(msg: LPMSG) -> LRESULT;
|
||||
fn TranslateMessage(msg: LPMSG) -> BOOL;
|
||||
fn PostQuitMessage(code: INT);
|
||||
}
|
||||
|
||||
#[link(name="ole32")]
|
||||
extern "system"
|
||||
{
|
||||
fn OleInitialize(pv: LPCVOID) -> i32; // HRESULT
|
||||
}
|
||||
|
||||
pub struct OsWindow
|
||||
{
|
||||
hwnd: HWINDOW,
|
||||
flags: UINT,
|
||||
}
|
||||
|
||||
impl OsWindow {
|
||||
|
||||
pub fn new() -> OsWindow {
|
||||
OsWindow { hwnd: 0 as HWINDOW, flags: 0 }
|
||||
}
|
||||
|
||||
pub fn from(hwnd: HWINDOW) -> OsWindow {
|
||||
OsWindow { hwnd: hwnd, flags: 0 }
|
||||
}
|
||||
|
||||
fn init_app() {
|
||||
unsafe { OleInitialize(::std::ptr::null()) };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl super::BaseWindow for OsWindow {
|
||||
|
||||
/// Get native window handle.
|
||||
fn get_hwnd(&self) -> HWINDOW {
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// Create a new native window.
|
||||
fn create(&mut self, rc: RECT, flags: UINT, parent: HWINDOW) -> HWINDOW {
|
||||
|
||||
if (flags & SCITER_CREATE_WINDOW_FLAGS::SW_MAIN as u32) != 0 {
|
||||
OsWindow::init_app();
|
||||
}
|
||||
|
||||
self.flags = flags;
|
||||
|
||||
#[cfg(not(feature = "windowless"))]
|
||||
{
|
||||
let cb = ::std::ptr::null();
|
||||
self.hwnd = (_API.SciterCreateWindow)(flags, &rc, cb, 0 as LPVOID, parent);
|
||||
if self.hwnd.is_null() {
|
||||
panic!("Failed to create window!");
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "windowless")]
|
||||
{
|
||||
let _ = rc;
|
||||
let _ = parent;
|
||||
let _ = &(_API.SciterVersion);
|
||||
}
|
||||
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// Minimize or hide window.
|
||||
fn collapse(&self, hide: bool) {
|
||||
let n: INT = if hide { 0 } else { 6 };
|
||||
unsafe { ShowWindow(self.hwnd, n) };
|
||||
}
|
||||
|
||||
/// Show or maximize window.
|
||||
fn expand(&self, maximize: bool) {
|
||||
let n: INT = if maximize { 3 } else { 1 };
|
||||
unsafe { ShowWindow(self.hwnd, n) };
|
||||
}
|
||||
|
||||
/// Close window.
|
||||
fn dismiss(&self) {
|
||||
unsafe { PostMessageW(self.hwnd, 0x0010, 0, 0) };
|
||||
}
|
||||
|
||||
/// Set native window title.
|
||||
fn set_title(&mut self, title: &str) {
|
||||
let s = s2w!(title);
|
||||
unsafe { SetWindowTextW(self.hwnd, s.as_ptr()) };
|
||||
}
|
||||
|
||||
/// Get native window title.
|
||||
fn get_title(&self) -> String {
|
||||
|
||||
let n = unsafe { GetWindowTextLengthW(self.hwnd) + 1 };
|
||||
let mut title: Vec<u16> = Vec::new();
|
||||
title.resize(n as usize, 0);
|
||||
unsafe { GetWindowTextW(self.hwnd, title.as_mut_ptr(), n) };
|
||||
return ::utf::w2s(title.as_ptr());
|
||||
}
|
||||
|
||||
/// Run the main app message loop until window been closed.
|
||||
fn run_app(&self) {
|
||||
let mut msg = MSG { hwnd: 0 as HWINDOW, message: 0, wParam: 0, lParam: 0, time: 0, pt: POINT { x: 0, y: 0 } };
|
||||
let pmsg: LPMSG = &mut msg;
|
||||
let null: HWINDOW = ::std::ptr::null_mut();
|
||||
unsafe {
|
||||
while GetMessageW(pmsg, null, 0, 0) != 0 {
|
||||
TranslateMessage(pmsg);
|
||||
DispatchMessageW(pmsg);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Post app quit message.
|
||||
fn quit_app(&self) {
|
||||
unsafe { PostQuitMessage(0) };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
mod windows {
|
||||
|
||||
use ::{_API};
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::*;
|
||||
use super::BaseWindow;
|
||||
|
||||
use ::std::ptr;
|
||||
|
||||
#[link(name="gtk-3")]
|
||||
extern "C"
|
||||
{
|
||||
fn gtk_init(argc: *const i32, argv: *const *const LPCSTR);
|
||||
fn gtk_main();
|
||||
fn gtk_main_quit();
|
||||
fn gtk_widget_get_toplevel(view: HWINDOW) -> HWINDOW;
|
||||
fn gtk_window_present(hwnd: HWINDOW);
|
||||
fn gtk_widget_hide(hwnd: HWINDOW);
|
||||
fn gtk_window_maximize(hwnd: HWINDOW);
|
||||
fn gtk_window_iconify(hwnd: HWINDOW);
|
||||
fn gtk_window_close(hwnd: HWINDOW);
|
||||
fn gtk_window_set_title(hwnd: HWINDOW, title: LPCSTR);
|
||||
fn gtk_window_get_title(hwnd: HWINDOW) -> LPCSTR;
|
||||
}
|
||||
|
||||
pub struct OsWindow
|
||||
{
|
||||
hwnd: HWINDOW,
|
||||
flags: UINT,
|
||||
}
|
||||
|
||||
impl OsWindow {
|
||||
|
||||
pub fn new() -> OsWindow {
|
||||
OsWindow { hwnd: 0 as HWINDOW, flags: 0 }
|
||||
}
|
||||
|
||||
pub fn from(hwnd: HWINDOW) -> OsWindow {
|
||||
OsWindow { hwnd: hwnd, flags: 0 }
|
||||
}
|
||||
|
||||
fn init_app() {
|
||||
unsafe { gtk_init(ptr::null(), ptr::null()) };
|
||||
}
|
||||
|
||||
fn window(&self) -> HWINDOW {
|
||||
let hwnd = self.get_hwnd();
|
||||
if hwnd.is_null() {
|
||||
hwnd
|
||||
} else {
|
||||
unsafe { gtk_widget_get_toplevel(hwnd) }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl super::BaseWindow for OsWindow {
|
||||
|
||||
/// Get native window handle.
|
||||
fn get_hwnd(&self) -> HWINDOW {
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// Create a new native window.
|
||||
fn create(&mut self, rc: RECT, flags: UINT, parent: HWINDOW) -> HWINDOW {
|
||||
|
||||
if (flags & SCITER_CREATE_WINDOW_FLAGS::SW_MAIN as u32) != 0 {
|
||||
OsWindow::init_app();
|
||||
}
|
||||
|
||||
self.flags = flags;
|
||||
|
||||
#[cfg(not(feature = "windowless"))]
|
||||
{
|
||||
let cb = ptr::null();
|
||||
self.hwnd = (_API.SciterCreateWindow)(flags, &rc, cb, 0 as LPVOID, parent);
|
||||
if self.hwnd.is_null() {
|
||||
panic!("Failed to create window!");
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "windowless")]
|
||||
{
|
||||
let _ = rc;
|
||||
let _ = parent;
|
||||
let _ = &(_API.SciterVersion);
|
||||
}
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// Minimize or hide window.
|
||||
fn collapse(&self, hide: bool) {
|
||||
unsafe {
|
||||
if hide {
|
||||
gtk_widget_hide(self.get_hwnd())
|
||||
} else {
|
||||
gtk_window_iconify(self.window())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Show or maximize window.
|
||||
fn expand(&self, maximize: bool) {
|
||||
let wnd = self.window();
|
||||
unsafe {
|
||||
if maximize {
|
||||
gtk_window_maximize(wnd)
|
||||
} else {
|
||||
gtk_window_present(wnd)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Close window.
|
||||
fn dismiss(&self) {
|
||||
unsafe { gtk_window_close(self.window()) };
|
||||
}
|
||||
|
||||
/// Set native window title.
|
||||
fn set_title(&mut self, title: &str) {
|
||||
let s = s2u!(title);
|
||||
unsafe { gtk_window_set_title(self.window(), s.as_ptr()) };
|
||||
}
|
||||
|
||||
/// Get native window title.
|
||||
fn get_title(&self) -> String {
|
||||
let s = unsafe { gtk_window_get_title(self.window()) };
|
||||
return u2s!(s);
|
||||
}
|
||||
|
||||
/// Run the main app message loop until window been closed.
|
||||
fn run_app(&self) {
|
||||
unsafe { gtk_main() };
|
||||
}
|
||||
|
||||
/// Post app quit message.
|
||||
fn quit_app(&self) {
|
||||
unsafe { gtk_main_quit() };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
mod windows {
|
||||
|
||||
extern crate objc_foundation;
|
||||
|
||||
use objc::runtime::{Class, Object};
|
||||
use self::objc_foundation::{NSString, INSString};
|
||||
|
||||
|
||||
/// Activation policies that control whether and how an app may be activated.
|
||||
#[repr(C)]
|
||||
#[allow(dead_code)]
|
||||
enum NSApplicationActivationPolicy {
|
||||
Regular = 0,
|
||||
Accessory,
|
||||
Prohibited,
|
||||
}
|
||||
|
||||
|
||||
// Note: Starting some OSX version (perhaps, 10.13),
|
||||
// the AppKit framework isn't loaded implicitly.
|
||||
#[link(name="CoreFoundation", kind="framework")]
|
||||
extern {}
|
||||
|
||||
#[link(name="AppKit", kind="framework")]
|
||||
extern {}
|
||||
|
||||
use ::{_API};
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::*;
|
||||
use super::BaseWindow;
|
||||
|
||||
pub struct OsWindow
|
||||
{
|
||||
hwnd: HWINDOW,
|
||||
flags: UINT,
|
||||
}
|
||||
|
||||
impl OsWindow {
|
||||
|
||||
pub fn new() -> OsWindow {
|
||||
OsWindow { hwnd: 0 as HWINDOW, flags: 0, }
|
||||
}
|
||||
|
||||
pub fn from(hwnd: HWINDOW) -> OsWindow {
|
||||
OsWindow { hwnd: hwnd, flags: 0 }
|
||||
}
|
||||
|
||||
fn get_app() -> *mut Object {
|
||||
let cls = Class::get("NSApplication").expect("`NSApplication` is not registered.");
|
||||
let obj = unsafe { msg_send!(cls, sharedApplication) };
|
||||
return obj;
|
||||
}
|
||||
|
||||
fn init_app() {
|
||||
// By default, unbundled apps start with `NSApplicationActivationPolicyProhibited` (no dock, no menu).
|
||||
let app = OsWindow::get_app();
|
||||
let _: () = unsafe { msg_send!(app, setActivationPolicy:NSApplicationActivationPolicy::Regular) };
|
||||
}
|
||||
|
||||
fn view(&self) -> *mut Object {
|
||||
let hwnd = self.get_hwnd();
|
||||
let hwnd: *mut Object = unsafe { ::std::mem::transmute(hwnd) };
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
fn window(&self) -> *mut Object {
|
||||
let hwnd = self.view();
|
||||
let obj: *mut Object = unsafe { msg_send!(hwnd, window) };
|
||||
assert!(!obj.is_null());
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
impl super::BaseWindow for OsWindow {
|
||||
|
||||
/// Get native window handle.
|
||||
fn get_hwnd(&self) -> HWINDOW {
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// Create a new native window.
|
||||
fn create(&mut self, rc: RECT, flags: UINT, parent: HWINDOW) -> HWINDOW {
|
||||
|
||||
if (flags & SCITER_CREATE_WINDOW_FLAGS::SW_MAIN as u32) != 0 {
|
||||
OsWindow::init_app();
|
||||
}
|
||||
|
||||
self.flags = flags;
|
||||
|
||||
#[cfg(not(feature = "windowless"))]
|
||||
{
|
||||
let w = rc.right - rc.left;
|
||||
let h = rc.bottom - rc.top;
|
||||
let prc: *const RECT = if w > 0 && h > 0 {
|
||||
&rc
|
||||
} else {
|
||||
0 as *const RECT
|
||||
};
|
||||
|
||||
let cb = 0 as *const SciterWindowDelegate;
|
||||
self.hwnd = (_API.SciterCreateWindow)(flags, prc, cb, 0 as LPVOID, parent);
|
||||
if self.hwnd.is_null() {
|
||||
panic!("Failed to create window!");
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "windowless")]
|
||||
{
|
||||
let _ = rc;
|
||||
let _ = parent;
|
||||
let _ = &(_API.SciterVersion);
|
||||
}
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// Minimize or hide window.
|
||||
fn collapse(&self, hide: bool) {
|
||||
let wnd = self.window();
|
||||
if hide {
|
||||
let _: () = unsafe { msg_send!(wnd, orderOut:0) };
|
||||
} else {
|
||||
let hwnd = self.view();
|
||||
let _: () = unsafe { msg_send!(wnd, performMiniaturize:hwnd) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Show or maximize window.
|
||||
fn expand(&self, maximize: bool) {
|
||||
let wnd = self.window();
|
||||
if (self.flags & SCITER_CREATE_WINDOW_FLAGS::SW_TITLEBAR as UINT) != 0 {
|
||||
let app = OsWindow::get_app();
|
||||
let _: () = unsafe { msg_send!(app, activateIgnoringOtherApps:true) };
|
||||
}
|
||||
unsafe {
|
||||
let _: () = msg_send!(wnd, makeKeyAndOrderFront:0);
|
||||
// msg_send!(wnd, orderFrontRegardless);
|
||||
}
|
||||
if maximize {
|
||||
let _: () = unsafe { msg_send!(wnd, performZoom:0) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Close window.
|
||||
fn dismiss(&self) {
|
||||
let wnd = self.window();
|
||||
let _: () = unsafe { msg_send!(wnd, close) };
|
||||
}
|
||||
|
||||
/// Set native window title.
|
||||
fn set_title(&mut self, title: &str) {
|
||||
let s = NSString::from_str(title);
|
||||
let wnd = self.window();
|
||||
let _: () = unsafe { msg_send!(wnd, setTitle:s) };
|
||||
}
|
||||
|
||||
/// Get native window title.
|
||||
fn get_title(&self) -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
/// Run the main app message loop until window been closed.
|
||||
fn run_app(&self) {
|
||||
let app = OsWindow::get_app();
|
||||
let _: () = unsafe { msg_send!(app, finishLaunching) };
|
||||
let _: () = unsafe { msg_send!(app, run) };
|
||||
}
|
||||
|
||||
/// Post app quit message.
|
||||
fn quit_app(&self) {
|
||||
let app = OsWindow::get_app();
|
||||
let _: () = unsafe { msg_send!(app, terminate:app) };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub type OsWindow = windows::OsWindow;
|
279
libs/rust-sciter/src/request.rs
Normal file
279
libs/rust-sciter/src/request.rs
Normal file
@ -0,0 +1,279 @@
|
||||
/*! Sciter Request API.
|
||||
|
||||
Handling all attributes of requests (GET/POST/PUT/DELETE) sent by
|
||||
[`Element.request()`](https://sciter.com/docs/content/sciter/Element.htm) and
|
||||
[`View.request()`](https://sciter.com/docs/content/sciter/View.htm)
|
||||
functions and other load requests.
|
||||
|
||||
*/
|
||||
pub use capi::screquest::{HREQUEST, REQUEST_RESULT};
|
||||
pub use capi::screquest::{REQUEST_METHOD, REQUEST_STATE, REQUEST_TYPE, RESOURCE_TYPE};
|
||||
|
||||
use capi::sctypes::{LPVOID, UINT};
|
||||
use capi::scdef::{LPCWSTR_RECEIVER};
|
||||
|
||||
use utf::{store_astr, store_wstr, store_bstr};
|
||||
|
||||
use _RAPI;
|
||||
|
||||
|
||||
|
||||
macro_rules! ok_or {
|
||||
($ok:ident) => {
|
||||
ok_or!((), $ok)
|
||||
};
|
||||
|
||||
($rv:expr, $ok:ident) => {
|
||||
if $ok == REQUEST_RESULT::OK {
|
||||
Ok($rv)
|
||||
} else {
|
||||
Err($ok)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A specialized `Result` type for request operations.
|
||||
pub type Result<T> = ::std::result::Result<T, REQUEST_RESULT>;
|
||||
|
||||
type GetCountFn = extern "system" fn (rq: HREQUEST, pNumber: &mut UINT) -> REQUEST_RESULT;
|
||||
type GetNameFn = extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT;
|
||||
type GetValueFn = extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT;
|
||||
|
||||
/// Request object.
|
||||
///
|
||||
/// Can be constructed from a `HREQUEST` handle only:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use sciter::request::Request;
|
||||
/// # use sciter::host::{SCN_LOAD_DATA, LOAD_RESULT};
|
||||
/// fn on_data_load(pnm: &mut SCN_LOAD_DATA) -> Option<LOAD_RESULT> {
|
||||
/// let mut rq = Request::from(pnm.request_id);
|
||||
/// // ...
|
||||
/// # None
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Request(HREQUEST);
|
||||
|
||||
/// Destroy the object.
|
||||
impl Drop for Request {
|
||||
fn drop(&mut self) {
|
||||
(_RAPI.RequestUnUse)(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies the object.
|
||||
///
|
||||
/// All allocated objects are reference counted so copying is just a matter of increasing reference counts.
|
||||
impl Clone for Request {
|
||||
fn clone(&self) -> Self {
|
||||
let dst = Request(self.0);
|
||||
(_RAPI.RequestUse)(dst.0);
|
||||
dst
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a Request object from `HREQUEST` handle.
|
||||
impl From<HREQUEST> for Request {
|
||||
fn from(hrq: HREQUEST) -> Request {
|
||||
assert!(!hrq.is_null());
|
||||
(_RAPI.RequestUse)(hrq);
|
||||
Request(hrq)
|
||||
}
|
||||
}
|
||||
|
||||
impl Request {
|
||||
/// Mark the request as complete with status and optional data.
|
||||
pub fn succeeded(&mut self, status: u32, data: Option<&[u8]>) -> Result<()> {
|
||||
let (ptr, size) = if let Some(data) = data {
|
||||
(data.as_ptr(), data.len() as u32)
|
||||
} else {
|
||||
(std::ptr::null(), 0_u32)
|
||||
};
|
||||
let ok = (_RAPI.RequestSetSucceeded)(self.0, status, ptr, size);
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Mark the request as complete with failure.
|
||||
pub fn failed(&mut self, status: u32, data: Option<&[u8]>) -> Result<()> {
|
||||
let (ptr, size) = if let Some(data) = data {
|
||||
(data.as_ptr(), data.len() as u32)
|
||||
} else {
|
||||
(std::ptr::null(), 0_u32)
|
||||
};
|
||||
let ok = (_RAPI.RequestSetSucceeded)(self.0, status, ptr, size);
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Append a data chunk to the received data.
|
||||
pub fn append_received_data(&mut self, data: &[u8]) -> Result<()> {
|
||||
let (ptr, size) = (data.as_ptr(), data.len() as u32);
|
||||
let ok = (_RAPI.RequestAppendDataChunk)(self.0, ptr, size);
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Get received (so far) data.
|
||||
pub fn get_received_data(&self) -> Result<Vec<u8>> {
|
||||
let mut data = Vec::new();
|
||||
let ok = (_RAPI.RequestGetData)(self.0, store_bstr, &mut data as *mut _ as LPVOID);
|
||||
ok_or!(data, ok)
|
||||
}
|
||||
|
||||
/// Get the URL of the request.
|
||||
pub fn url(&self) -> Result<String> {
|
||||
let mut s = String::new();
|
||||
let ok = (_RAPI.RequestUrl)(self.0, store_astr, &mut s as *mut _ as LPVOID);
|
||||
ok_or!(s, ok)
|
||||
}
|
||||
|
||||
/// Get a real URL of the content (e.g., after possible redirection).
|
||||
pub fn content_url(&self) -> Result<String> {
|
||||
let mut s = String::new();
|
||||
let ok = (_RAPI.RequestContentUrl)(self.0, store_astr, &mut s as *mut _ as LPVOID);
|
||||
ok_or!(s, ok)
|
||||
}
|
||||
|
||||
/// Get the data type of the request.
|
||||
pub fn method(&self) -> Result<REQUEST_METHOD> {
|
||||
let mut t = REQUEST_METHOD::GET;
|
||||
let ok = (_RAPI.RequestGetRequestType)(self.0, &mut t);
|
||||
ok_or!(t, ok)
|
||||
}
|
||||
|
||||
/// Get the resource data type of the request.
|
||||
pub fn request_type(&self) -> Result<RESOURCE_TYPE> {
|
||||
let mut t = RESOURCE_TYPE::RAW;
|
||||
let ok = (_RAPI.RequestGetRequestedDataType)(self.0, &mut t);
|
||||
ok_or!(t, ok)
|
||||
}
|
||||
|
||||
/// Get the MIME type of the received data.
|
||||
pub fn response_type(&self) -> Result<String> {
|
||||
let mut s = String::new();
|
||||
let ok = (_RAPI.RequestGetReceivedDataType)(self.0, store_astr, &mut s as *mut _ as LPVOID);
|
||||
ok_or!(s, ok)
|
||||
}
|
||||
|
||||
/// Set the MIME type of the received data.
|
||||
pub fn set_response_type(&mut self, mime_type: &str) -> Result<()> {
|
||||
let text = s2u!(mime_type);
|
||||
let ok = (_RAPI.RequestSetReceivedDataType)(self.0, text.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set the data encoding for the received data.
|
||||
pub fn set_response_encoding(&mut self, encoding_type: &str) -> Result<()> {
|
||||
let text = s2u!(encoding_type);
|
||||
let ok = (_RAPI.RequestSetReceivedDataEncoding)(self.0, text.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
fn get_collection_impl(&self, get_count: GetCountFn, get_name: GetNameFn, get_value: GetValueFn) -> Result<std::collections::HashMap<String, String>> {
|
||||
let mut count = 0;
|
||||
let ok = get_count(self.0, &mut count);
|
||||
if ok != REQUEST_RESULT::OK {
|
||||
return Err(ok);
|
||||
}
|
||||
|
||||
let mut args = std::collections::HashMap::with_capacity(count as usize);
|
||||
for i in 0..count {
|
||||
let mut name = String::new();
|
||||
let mut ok = get_name(self.0, i, store_wstr, &mut name as *mut _ as LPVOID);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
let mut value = String::new();
|
||||
ok = get_value(self.0, i, store_wstr, &mut value as *mut _ as LPVOID);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
args.insert(name, value);
|
||||
}
|
||||
}
|
||||
if ok != REQUEST_RESULT::OK {
|
||||
return Err(ok);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
/// Get the parameters of the request.
|
||||
pub fn parameters(&self) -> Result<std::collections::HashMap<String, String>> {
|
||||
self.get_collection_impl(_RAPI.RequestGetNumberOfParameters, _RAPI.RequestGetNthParameterName, _RAPI.RequestGetNthParameterValue)
|
||||
}
|
||||
|
||||
/// Get the headers of the request.
|
||||
pub fn request_headers(&self) -> Result<std::collections::HashMap<String, String>> {
|
||||
self.get_collection_impl(_RAPI.RequestGetNumberOfRqHeaders, _RAPI.RequestGetNthRqHeaderName, _RAPI.RequestGetNthRqHeaderValue)
|
||||
}
|
||||
|
||||
/// Set request header (a single item).
|
||||
pub fn set_request_header(&mut self, name: &str, value: &str) -> Result<()> {
|
||||
let wname = s2w!(name);
|
||||
let wtext = s2w!(value);
|
||||
let ok = (_RAPI.RequestSetRqHeader)(self.0, wname.as_ptr(), wtext.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Get the headers of the response.
|
||||
pub fn response_headers(&self) -> Result<std::collections::HashMap<String, String>> {
|
||||
self.get_collection_impl(_RAPI.RequestGetNumberOfRspHeaders, _RAPI.RequestGetNthRspHeaderName, _RAPI.RequestGetNthRspHeaderValue)
|
||||
}
|
||||
|
||||
/// Set respone header (a single item).
|
||||
pub fn set_response_header(&mut self, name: &str, value: &str) -> Result<()> {
|
||||
let wname = s2w!(name);
|
||||
let wtext = s2w!(value);
|
||||
let ok = (_RAPI.RequestSetRspHeader)(self.0, wname.as_ptr(), wtext.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Get proxy host and port (if any).
|
||||
pub fn proxy(&self) -> Result<(String, u16)> {
|
||||
let mut s = String::new();
|
||||
let mut ok = (_RAPI.RequestGetProxyHost)(self.0, store_astr, &mut s as *mut _ as LPVOID);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
let mut n = 0_u32;
|
||||
ok = (_RAPI.RequestGetProxyPort)(self.0, &mut n);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
return Ok((s, n as u16));
|
||||
}
|
||||
}
|
||||
Err(ok)
|
||||
}
|
||||
|
||||
/// Get the current completion status of the request.
|
||||
///
|
||||
/// Returns current state and HTTP response code.
|
||||
pub fn completion_status(&self) -> Result<(REQUEST_STATE, u32)> {
|
||||
let mut state = REQUEST_STATE::SUCCESS;
|
||||
let mut code = 0_u32;
|
||||
let ok = (_RAPI.RequestGetCompletionStatus)(self.0, &mut state, &mut code);
|
||||
ok_or!((state, code), ok)
|
||||
}
|
||||
|
||||
/// Get the execution duratiom of the request.
|
||||
pub fn request_duration(&self) -> Result<std::time::Duration> {
|
||||
let mut started = 0;
|
||||
let mut ended = 0;
|
||||
let ok = (_RAPI.RequestGetTimes)(self.0, &mut started, &mut ended);
|
||||
if ok == REQUEST_RESULT::OK && ended > started {
|
||||
let d = std::time::Duration::from_millis(ended as u64 - started as u64);
|
||||
Ok(d)
|
||||
} else {
|
||||
Err(ok)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the execution `started` and `ended` time of the request, in milliseconds.
|
||||
pub fn request_time(&self) -> Result<(std::time::Duration, std::time::Duration)> {
|
||||
let mut started = 0;
|
||||
let mut ended = 0;
|
||||
let ok = (_RAPI.RequestGetTimes)(self.0, &mut started, &mut ended);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
use std::time::Duration;
|
||||
let s = Duration::from_millis(started as u64);
|
||||
let e = Duration::from_millis(ended as u64);
|
||||
Ok((s, e))
|
||||
} else {
|
||||
Err(ok)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
5
libs/rust-sciter/src/types.rs
Normal file
5
libs/rust-sciter/src/types.rs
Normal file
@ -0,0 +1,5 @@
|
||||
//! Export platform-dependent types used by Sciter.
|
||||
|
||||
pub use capi::sctypes::*;
|
||||
pub use capi::scdef::*;
|
||||
pub use capi::scvalue::VALUE;
|
281
libs/rust-sciter/src/utf.rs
Normal file
281
libs/rust-sciter/src/utf.rs
Normal file
@ -0,0 +1,281 @@
|
||||
//! UTF-8 <> UTF-16 conversion support.
|
||||
|
||||
// Since Rust haven't stable support of UTF-16, I've ported this code
|
||||
// from Sciter SDK (aux-cvt.h)
|
||||
|
||||
// (C) 2003-2015, Andrew Fedoniouk (andrew@terrainformatica.com)
|
||||
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use capi::sctypes::{LPCSTR, LPCWSTR, LPCBYTE};
|
||||
|
||||
|
||||
/// UTF-8 to UTF-16* converter.
|
||||
#[allow(unused_parens)]
|
||||
fn towcs(utf: &[u8], outbuf: &mut Vec<u16>) -> bool
|
||||
{
|
||||
let errc = 0x003F; // '?'
|
||||
let mut num_errors = 0;
|
||||
|
||||
let last = utf.len();
|
||||
let mut pc = 0;
|
||||
while (pc < last) {
|
||||
let mut b = u32::from(utf[pc]); pc += 1;
|
||||
if (b == 0) { break; }
|
||||
|
||||
if ((b & 0x80) == 0) {
|
||||
// 1-BYTE sequence: 000000000xxxxxxx = 0xxxxxxx
|
||||
|
||||
} else if ((b & 0xE0) == 0xC0) {
|
||||
// 2-BYTE sequence: 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
|
||||
if (pc == last) {
|
||||
outbuf.push(errc);
|
||||
num_errors += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
b = (b & 0x1f) << 6;
|
||||
b |= (u32::from(utf[pc]) & 0x3f); pc += 1;
|
||||
|
||||
} else if ((b & 0xf0) == 0xe0) {
|
||||
// 3-BYTE sequence: zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
|
||||
if (pc >= last - 1) {
|
||||
outbuf.push(errc);
|
||||
num_errors += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
b = (b & 0x0f) << 12;
|
||||
b |= (u32::from(utf[pc]) & 0x3f) << 6; pc += 1;
|
||||
b |= (u32::from(utf[pc]) & 0x3f); pc += 1;
|
||||
|
||||
if (b == 0xFEFF && outbuf.is_empty()) { // bom at start
|
||||
continue; // skip it
|
||||
}
|
||||
|
||||
} else if ((b & 0xf8) == 0xf0) {
|
||||
// 4-BYTE sequence: 11101110wwwwzzzzyy + 110111yyyyxxxxxx = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
|
||||
if(pc >= last - 2) { outbuf.push(errc); break; }
|
||||
|
||||
b = (b & 0x07) << 18;
|
||||
b |= (u32::from(utf[pc]) & 0x3f) << 12; pc += 1;
|
||||
b |= (u32::from(utf[pc]) & 0x3f) << 6; pc += 1;
|
||||
b |= (u32::from(utf[pc]) & 0x3f); pc += 1;
|
||||
|
||||
// b shall contain now full 21-bit unicode code point.
|
||||
assert!((b & 0x1f_ffff) == b);
|
||||
if((b & 0x1f_ffff) != b) {
|
||||
outbuf.push(errc);
|
||||
num_errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
outbuf.push( (0xd7c0 + (b >> 10)) as u16 );
|
||||
outbuf.push( (0xdc00 | (b & 0x3ff)) as u16 );
|
||||
|
||||
} else {
|
||||
num_errors += 1;
|
||||
b = u32::from(errc);
|
||||
}
|
||||
|
||||
outbuf.push(b as u16);
|
||||
}
|
||||
return num_errors == 0;
|
||||
}
|
||||
|
||||
|
||||
/// UTF-16 to UTF-8 converter.
|
||||
#[allow(unused_parens)]
|
||||
fn fromwcs(wcs: &[u16], outbuf: &mut Vec<u8>) -> bool
|
||||
{
|
||||
let mut num_errors = 0;
|
||||
|
||||
let last = wcs.len();
|
||||
let mut pc = 0;
|
||||
while (pc < last) {
|
||||
let c = u32::from(wcs[pc]);
|
||||
if (c < (1 << 7)) {
|
||||
outbuf.push(c as u8);
|
||||
|
||||
} else if (c < (1 << 11)) {
|
||||
outbuf.push(((c >> 6) | 0xc0) as u8);
|
||||
outbuf.push(((c & 0x3f) | 0x80) as u8);
|
||||
|
||||
} else if (c < (1 << 16)) {
|
||||
outbuf.push(((c >> 12) | 0xe0) as u8);
|
||||
outbuf.push((((c >> 6) & 0x3f) | 0x80) as u8);
|
||||
outbuf.push(((c & 0x3f) | 0x80) as u8);
|
||||
|
||||
} else if (c < (1 << 21)) {
|
||||
outbuf.push(((c >> 18) | 0xf0) as u8);
|
||||
outbuf.push((((c >> 12) & 0x3f) | 0x80) as u8);
|
||||
outbuf.push((((c >> 6) & 0x3f) | 0x80) as u8);
|
||||
outbuf.push(((c & 0x3f) | 0x80) as u8);
|
||||
|
||||
} else {
|
||||
num_errors += 1;
|
||||
}
|
||||
pc += 1;
|
||||
}
|
||||
return num_errors == 0;
|
||||
}
|
||||
|
||||
|
||||
/// UTF-16 string length like `libc::wcslen`.
|
||||
fn wcslen(sz: LPCWSTR) -> usize
|
||||
{
|
||||
if sz.is_null() {
|
||||
return 0;
|
||||
}
|
||||
let mut i: isize = 0;
|
||||
loop {
|
||||
let c = unsafe { *sz.offset(i) };
|
||||
if c == 0 {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return i as usize;
|
||||
}
|
||||
|
||||
/// UTF8 to Rust string conversion. See also [`s2u!`](../macro.s2u.html).
|
||||
pub fn u2s(sz: LPCSTR) -> String
|
||||
{
|
||||
if sz.is_null() {
|
||||
return String::new();
|
||||
}
|
||||
let cs = unsafe { CStr::from_ptr(sz) };
|
||||
let cow = cs.to_string_lossy();
|
||||
return cow.into_owned();
|
||||
}
|
||||
|
||||
/// UTF8 to Rust string conversion. See also [`s2u!`](../macro.s2u.html).
|
||||
pub fn u2sn(sz: LPCSTR, len: usize) -> String
|
||||
{
|
||||
let chars = unsafe { ::std::slice::from_raw_parts(sz as LPCBYTE, len) };
|
||||
let s = String::from_utf8_lossy(chars).into_owned();
|
||||
return s;
|
||||
}
|
||||
|
||||
/// UTF-16 to Rust string conversion. See also [`s2w!`](../macro.s2w.html).
|
||||
pub fn w2s(sz: LPCWSTR) -> String
|
||||
{
|
||||
return w2sn(sz, wcslen(sz));
|
||||
}
|
||||
|
||||
/// UTF-16 to Rust string conversion. See also [`s2w!`](../macro.s2w.html).
|
||||
pub fn w2sn(sz: LPCWSTR, len: usize) -> String
|
||||
{
|
||||
if sz.is_null() {
|
||||
return String::new();
|
||||
}
|
||||
let chars = unsafe { ::std::slice::from_raw_parts(sz, len) };
|
||||
let s = String::from_utf16_lossy(chars);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Rust string to UTF-8 conversion.
|
||||
pub fn s2un(s: &str) -> (CString, u32) {
|
||||
let cs = CString::new(s.trim_end_matches('\0')).unwrap_or(CString::new("").unwrap());
|
||||
let n = cs.as_bytes().len() as u32;
|
||||
return (cs, n);
|
||||
}
|
||||
|
||||
/// Rust string to UTF-16 conversion.
|
||||
pub fn s2vec(s: &str) -> Vec<u16> {
|
||||
s2vecn(s).0
|
||||
}
|
||||
|
||||
/// Rust string to UTF-16 conversion.
|
||||
pub fn s2vecn(s: &str) -> (Vec<u16>, u32) {
|
||||
let cs = CString::new(s.trim_end_matches('\0')).unwrap_or(CString::new("").unwrap());
|
||||
let mut out = Vec::with_capacity(s.len() * 2);
|
||||
towcs(cs.to_bytes(), &mut out);
|
||||
let n = out.len() as u32;
|
||||
if n > 0 {
|
||||
out.push(0);
|
||||
}
|
||||
return (out, n);
|
||||
}
|
||||
|
||||
use capi::sctypes::{UINT, LPVOID};
|
||||
|
||||
/// Convert an incoming UTF-16 to `String`.
|
||||
pub(crate) extern "system" fn store_wstr(szstr: LPCWSTR, str_length: UINT, param: LPVOID) {
|
||||
let s = self::w2sn(szstr, str_length as usize);
|
||||
let out = param as *mut String;
|
||||
unsafe { *out = s };
|
||||
}
|
||||
|
||||
/// Convert an incoming UTF-8 to `String`.
|
||||
pub(crate) extern "system" fn store_astr(szstr: LPCSTR, str_length: UINT, param: LPVOID) {
|
||||
let s = self::u2sn(szstr, str_length as usize);
|
||||
let out = param as *mut String;
|
||||
unsafe { *out = s };
|
||||
}
|
||||
|
||||
/// Convert an incoming html string (UTF-8 in fact) to `String`.
|
||||
pub(crate) extern "system" fn store_bstr(szstr: LPCBYTE, str_length: UINT, param: LPVOID) {
|
||||
let s = unsafe { ::std::slice::from_raw_parts(szstr, str_length as usize) };
|
||||
let pout = param as *mut Vec<u8>;
|
||||
let out = unsafe {&mut *pout};
|
||||
out.extend_from_slice(s);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use capi::sctypes::{LPCWSTR, LPCSTR};
|
||||
use super::{wcslen, u2s, w2s, s2vec};
|
||||
|
||||
#[test]
|
||||
fn test_wcslen() {
|
||||
let nullptr: LPCWSTR = ::std::ptr::null();
|
||||
assert_eq!(wcslen(nullptr), 0);
|
||||
|
||||
let v = vec![0 as u16];
|
||||
assert_eq!(wcslen(v.as_ptr()), 0);
|
||||
|
||||
let v = vec![32, 32, 0];
|
||||
assert_eq!(wcslen(v.as_ptr()), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_u2s() {
|
||||
let nullptr: LPCSTR = ::std::ptr::null();
|
||||
assert_eq!(u2s(nullptr), String::new());
|
||||
|
||||
let s = "hi, there";
|
||||
assert_eq!(u2s(CString::new(s.trim_end_matches('\0')).unwrap_or(CString::new("").unwrap()).as_ptr()), s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_w2s() {
|
||||
let nullptr: LPCWSTR = ::std::ptr::null();
|
||||
assert_eq!(w2s(nullptr), String::new());
|
||||
|
||||
let v = vec![32, 32, 0]; // SP
|
||||
assert_eq!(w2s(v.as_ptr()), " ");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn s2w_test() {
|
||||
let v = s2vec("");
|
||||
assert_eq!(v, []);
|
||||
|
||||
assert_eq!(s2vec(""), []);
|
||||
|
||||
assert_eq!(s2vec("A"), ['A' as u16, 0]);
|
||||
|
||||
assert_eq!(s2vec("AB"), ['A' as u16, 'B' as u16, 0]);
|
||||
|
||||
let (cs, n) = s2wn!("");
|
||||
assert_eq!(n, 0);
|
||||
assert_eq!(cs, []);
|
||||
}
|
||||
}
|
1336
libs/rust-sciter/src/value.rs
Normal file
1336
libs/rust-sciter/src/value.rs
Normal file
File diff suppressed because it is too large
Load Diff
494
libs/rust-sciter/src/video.rs
Normal file
494
libs/rust-sciter/src/video.rs
Normal file
@ -0,0 +1,494 @@
|
||||
/*! Sciter video rendering.
|
||||
|
||||
Host application can render custom video streams using `<video>` infrastructure.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
use capi::sctypes::{UINT, LPCBYTE, LPCSTR};
|
||||
use capi::scom::som_passport_t;
|
||||
|
||||
/// A type alias for Sciter functions that return `bool`.
|
||||
pub type Result<T> = ::std::result::Result<T, ()>;
|
||||
|
||||
|
||||
/// Color space for video frame.
|
||||
#[repr(C)]
|
||||
pub enum COLOR_SPACE {
|
||||
Unknown,
|
||||
|
||||
Yv12,
|
||||
/// I420
|
||||
Iyuv,
|
||||
Nv12,
|
||||
Yuy2,
|
||||
|
||||
Rgb24,
|
||||
Rgb555,
|
||||
Rgb565,
|
||||
Rgb32,
|
||||
}
|
||||
|
||||
macro_rules! cppcall {
|
||||
// self.func()
|
||||
($this:ident . $func:ident ()) => {
|
||||
unsafe {
|
||||
((*$this.vtbl).$func)($this as *mut _)
|
||||
}
|
||||
};
|
||||
(const $this:ident . $func:ident ()) => {
|
||||
unsafe {
|
||||
((*$this.vtbl).$func)($this as *const _)
|
||||
}
|
||||
};
|
||||
|
||||
// self.func(args...)
|
||||
($this:ident . $func:ident ( $( $arg:expr ),* )) => {
|
||||
unsafe {
|
||||
((*$this.vtbl).$func)($this as *mut _, $($arg),* )
|
||||
}
|
||||
};
|
||||
(const $this:ident . $func:ident ( $( $arg:expr ),* )) => {
|
||||
unsafe {
|
||||
((*$this.vtbl).$func)($this as *const _, $($arg),* )
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! cppresult {
|
||||
( $( $t:tt )* ) => {
|
||||
if cppcall!( $($t)* ) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait NamedInterface {
|
||||
fn get_interface_name() -> &'static [u8];
|
||||
|
||||
fn query_interface(from: &mut iasset) -> Option<* mut iasset> {
|
||||
let mut out: *mut iasset = ::std::ptr::null_mut();
|
||||
from.get_interface(Self::get_interface_name().as_ptr() as LPCSTR, &mut out as *mut _);
|
||||
if !out.is_null() {
|
||||
Some(out)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NamedInterface for video_source {
|
||||
fn get_interface_name() -> &'static [u8] {
|
||||
b"source.video.sciter.com\0"
|
||||
}
|
||||
}
|
||||
|
||||
impl NamedInterface for video_destination {
|
||||
fn get_interface_name() -> &'static [u8] {
|
||||
b"destination.video.sciter.com\0"
|
||||
}
|
||||
}
|
||||
|
||||
impl NamedInterface for fragmented_video_destination {
|
||||
fn get_interface_name() -> &'static [u8] {
|
||||
b"fragmented.destination.video.sciter.com\0"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// COM `IUnknown` alike thing.
|
||||
#[repr(C)]
|
||||
struct iasset_vtbl {
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(this: *mut iasset) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(this: *mut iasset) -> i32,
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub get_interface: extern "C" fn(this: *mut iasset, name: LPCSTR, out: *mut *mut iasset) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
|
||||
}
|
||||
|
||||
/// COM `IUnknown` alike thing.
|
||||
#[repr(C)]
|
||||
pub struct iasset {
|
||||
vtbl: *const iasset_vtbl,
|
||||
}
|
||||
|
||||
impl iasset {
|
||||
/// Increments the reference count for an interface on an object.
|
||||
fn add_ref(&mut self) -> i32 {
|
||||
cppcall!(self.add_ref())
|
||||
}
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
fn release(&mut self) -> i32 {
|
||||
cppcall!(self.release())
|
||||
}
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub fn get_interface(&mut self, name: LPCSTR, out: *mut *mut iasset) -> bool {
|
||||
cppcall!(self.get_interface(name, out))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Video source interface, used by engine to query video state.
|
||||
#[repr(C)]
|
||||
struct video_source_vtbl {
|
||||
// <-- iasset:
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(this: *mut video_source) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(this: *mut video_source) -> i32,
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub get_interface: extern "C" fn(this: *mut video_source, name: *const u8, out: *mut *mut iasset) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
|
||||
// -->
|
||||
|
||||
// <-- video_source
|
||||
pub play: extern "C" fn(this: *mut video_source) -> bool,
|
||||
pub pause: extern "C" fn(this: *mut video_source) -> bool,
|
||||
pub stop: extern "C" fn(this: *mut video_source) -> bool,
|
||||
|
||||
pub get_is_ended: extern "C" fn(this: *const video_source, is_end: *mut bool) -> bool,
|
||||
|
||||
pub get_position: extern "C" fn(this: *const video_source, seconds: *mut f64) -> bool,
|
||||
pub set_position: extern "C" fn(this: *mut video_source, seconds: f64) -> bool,
|
||||
|
||||
pub get_duration: extern "C" fn(this: *const video_source, seconds: *mut f64) -> bool,
|
||||
|
||||
pub get_volume: extern "C" fn(this: *const video_source, volume: *mut f64) -> bool,
|
||||
pub set_volume: extern "C" fn(this: *mut video_source, volume: f64) -> bool,
|
||||
|
||||
pub get_balance: extern "C" fn(this: *const video_source, balance: *mut f64) -> bool,
|
||||
pub set_balance: extern "C" fn(this: *mut video_source, balance: f64) -> bool,
|
||||
// -->
|
||||
}
|
||||
|
||||
/// Video source interface to query video state.
|
||||
#[repr(C)]
|
||||
pub struct video_source {
|
||||
vtbl: *const video_source_vtbl,
|
||||
}
|
||||
|
||||
impl video_source {
|
||||
/// Starts playback from the current position.
|
||||
pub fn play(&mut self) -> Result<()> {
|
||||
cppresult!(self.play())
|
||||
}
|
||||
|
||||
/// Pauses playback.
|
||||
pub fn pause(&mut self) -> Result<()> {
|
||||
cppresult!(self.pause())
|
||||
}
|
||||
|
||||
/// Stops playback.
|
||||
pub fn stop(&mut self) -> Result<()> {
|
||||
cppresult!(self.stop())
|
||||
}
|
||||
|
||||
/// Whether playback has reached the end of the video.
|
||||
pub fn is_ended(&self) -> Result<bool> {
|
||||
let mut r = false;
|
||||
cppresult!(const self.get_is_ended(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Reports the current playback position.
|
||||
pub fn get_position(&self) -> Result<f64> {
|
||||
let mut r = 0f64;
|
||||
cppresult!(const self.get_position(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Sets the current playback position.
|
||||
pub fn set_position(&mut self, seconds: f64) -> Result<()> {
|
||||
cppresult!(self.set_position(seconds))
|
||||
}
|
||||
|
||||
/// Reports the duration of the video in seconds.
|
||||
///
|
||||
/// If duration is not available, returns `0`.
|
||||
pub fn get_duration(&self) -> Result<f64> {
|
||||
let mut r = 0f64;
|
||||
cppresult!(const self.get_duration(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Reports the current volume level of an audio track of the movie.
|
||||
///
|
||||
/// `1.0` corresponds to `0db`, `0.0` (mute) to `-100db`.
|
||||
pub fn get_volume(&self) -> Result<f64> {
|
||||
let mut r = 0f64;
|
||||
cppresult!(const self.get_volume(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Sets the current volume level between `0.0` (mute) and `1.0` (`0db`).
|
||||
pub fn set_volume(&mut self, volume: f64) -> Result<()> {
|
||||
cppresult!(self.set_volume(volume))
|
||||
}
|
||||
|
||||
/// Reports the current stereo balance.
|
||||
pub fn get_balance(&self) -> Result<f64> {
|
||||
let mut r = 0f64;
|
||||
cppresult!(const self.get_balance(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Sets a new value of the stereo balance.
|
||||
pub fn set_balance(&mut self, balance: f64) -> Result<()> {
|
||||
cppresult!(self.set_balance(balance))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Video destination interface, represents video rendering site.
|
||||
#[repr(C)]
|
||||
struct video_destination_vtbl {
|
||||
// <-- iasset:
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(this: *mut video_destination) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(this: *mut video_destination) -> i32,
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub get_interface: extern "C" fn(this: *mut video_destination, name: *const u8, out: *mut *mut iasset) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
|
||||
// -->
|
||||
|
||||
// <-- video_destination
|
||||
/// Whether this instance of `video_renderer` is attached to a DOM element and is capable of playing.
|
||||
pub is_alive: extern "C" fn(this: *const video_destination) -> bool,
|
||||
|
||||
/// Start streaming/rendering.
|
||||
pub start_streaming: extern "C" fn(this: *mut video_destination, frame_width: i32, frame_height: i32, color_space: COLOR_SPACE, src: *const video_source) -> bool,
|
||||
|
||||
/// Stop streaming.
|
||||
pub stop_streaming: extern "C" fn(this: *mut video_destination) -> bool,
|
||||
|
||||
/// Render the next frame.
|
||||
pub render_frame: extern "C" fn(this: *mut video_destination, data: LPCBYTE, size: UINT) -> bool,
|
||||
// -->
|
||||
}
|
||||
|
||||
/// Video destination interface, represents video rendering site.
|
||||
#[repr(C)]
|
||||
pub struct video_destination {
|
||||
vtbl: *const video_destination_vtbl,
|
||||
}
|
||||
|
||||
impl video_destination {
|
||||
|
||||
/// Whether this instance of `video_renderer` is attached to a DOM element and is capable of playing.
|
||||
pub fn is_alive(&self) -> bool {
|
||||
cppcall!(const self.is_alive())
|
||||
}
|
||||
|
||||
/// Start streaming/rendering.
|
||||
///
|
||||
/// * `frame_size` - the width and the height of the video frame.
|
||||
/// * `color_space` - the color space format of the video frame.
|
||||
/// * `src` - an optional custom [`video_source`](struct.video_source.html) interface implementation, provided by the application.
|
||||
pub fn start_streaming(&mut self, frame_size: (i32, i32), color_space: COLOR_SPACE, src: Option<&video_source>) -> Result<()> {
|
||||
let src_ptr = if let Some(ptr) = src { ptr as *const _ } else { ::std::ptr::null() };
|
||||
cppresult!(self.start_streaming(frame_size.0, frame_size.1, color_space, src_ptr))
|
||||
}
|
||||
|
||||
/// Stop streaming.
|
||||
pub fn stop_streaming(&mut self) -> Result<()> {
|
||||
cppresult!(self.stop_streaming())
|
||||
}
|
||||
|
||||
/// Render the next frame.
|
||||
pub fn render_frame(&mut self, data: &[u8]) -> Result<()> {
|
||||
cppresult!(self.render_frame(data.as_ptr(), data.len() as UINT))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Fragmented destination interface, used for partial updates.
|
||||
#[repr(C)]
|
||||
struct fragmented_video_destination_vtbl {
|
||||
// <-- iasset:
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(this: *mut fragmented_video_destination) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(this: *mut fragmented_video_destination) -> i32,
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub get_interface: extern "C" fn(this: *mut fragmented_video_destination, name: *const u8, out: *mut *mut iasset) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
|
||||
// -->
|
||||
|
||||
// <-- video_destination
|
||||
/// Whether this instance of `video_renderer` is attached to a DOM element and is capable of playing.
|
||||
pub is_alive: extern "C" fn(this: *const fragmented_video_destination) -> bool,
|
||||
|
||||
/// Start streaming/rendering.
|
||||
pub start_streaming: extern "C" fn(this: *mut fragmented_video_destination, frame_width: i32, frame_height: i32, color_space: COLOR_SPACE, src: *const video_source) -> bool,
|
||||
|
||||
/// Stop streaming.
|
||||
pub stop_streaming: extern "C" fn(this: *mut fragmented_video_destination) -> bool,
|
||||
|
||||
/// Render the next frame.
|
||||
pub render_frame: extern "C" fn(this: *mut fragmented_video_destination, data: LPCBYTE, size: UINT) -> bool,
|
||||
// -->
|
||||
|
||||
// <-- fragmented_video_destination
|
||||
/// Render the specified part of the current frame.
|
||||
pub render_frame_part: extern "C" fn(this: *mut fragmented_video_destination, data: LPCBYTE, size: UINT, x: i32, y: i32, width: i32, height: i32) -> bool,
|
||||
// -->
|
||||
}
|
||||
|
||||
/// Fragmented destination interface, used for partial updates.
|
||||
#[repr(C)]
|
||||
pub struct fragmented_video_destination {
|
||||
vtbl: *const fragmented_video_destination_vtbl,
|
||||
}
|
||||
|
||||
impl fragmented_video_destination {
|
||||
|
||||
/// Whether this instance of `video_renderer` is attached to a DOM element and is capable of playing.
|
||||
pub fn is_alive(&self) -> bool {
|
||||
cppcall!(const self.is_alive())
|
||||
}
|
||||
|
||||
/// Start streaming/rendering.
|
||||
///
|
||||
/// * `frame_size` - the width and the height of the video frame.
|
||||
/// * `color_space` - the color space format of the video frame.
|
||||
/// * `src` - an optional custom [`video_source`](struct.video_source.html) interface implementation, provided by the application.
|
||||
pub fn start_streaming(&mut self, frame_size: (i32, i32), color_space: COLOR_SPACE, src: Option<&video_source>) -> Result<()> {
|
||||
let src_ptr = if let Some(ptr) = src { ptr as *const _ } else { ::std::ptr::null() };
|
||||
cppresult!(self.start_streaming(frame_size.0, frame_size.1, color_space, src_ptr))
|
||||
}
|
||||
|
||||
/// Stop streaming.
|
||||
pub fn stop_streaming(&mut self) -> Result<()> {
|
||||
cppresult!(self.stop_streaming())
|
||||
}
|
||||
|
||||
/// Render the next frame.
|
||||
pub fn render_frame(&mut self, data: &[u8]) -> Result<()> {
|
||||
cppresult!(self.render_frame(data.as_ptr(), data.len() as UINT))
|
||||
}
|
||||
|
||||
/// Render the specified part of the current frame.
|
||||
///
|
||||
/// * `update_point` - X and Y coordinates of the update portion.
|
||||
/// * `update_size` - width and height of the update portion.
|
||||
pub fn render_frame_part(&mut self, data: &[u8], update_point: (i32, i32), update_size: (i32, i32)) -> Result<()> {
|
||||
cppresult!(self.render_frame_part(data.as_ptr(), data.len() as UINT, update_point.0, update_point.1, update_size.0, update_size.1))
|
||||
}
|
||||
}
|
||||
|
||||
/// A managed `iasset` pointer.
|
||||
pub struct AssetPtr<T> {
|
||||
ptr: *mut T,
|
||||
}
|
||||
|
||||
/// It's okay to transfer video pointers between threads.
|
||||
unsafe impl<T> Send for AssetPtr<T> {}
|
||||
|
||||
use ::std::ops::{Deref, DerefMut};
|
||||
|
||||
impl Deref for AssetPtr<video_destination> {
|
||||
type Target = video_destination;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for AssetPtr<video_destination> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { &mut *self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AssetPtr<fragmented_video_destination> {
|
||||
type Target = fragmented_video_destination;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for AssetPtr<fragmented_video_destination> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { &mut *self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
/// Decrements the reference count of a managed pointer.
|
||||
impl<T> Drop for AssetPtr<T> {
|
||||
fn drop(&mut self) {
|
||||
self.get().release();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AssetPtr<T> {
|
||||
/// Attach to an existing `iasset` pointer without reference increment.
|
||||
fn attach(lp: *mut T) -> Self {
|
||||
assert!(!lp.is_null());
|
||||
Self {
|
||||
ptr: lp
|
||||
}
|
||||
}
|
||||
|
||||
/// Attach to an `iasset` pointer and increment its reference count.
|
||||
pub fn adopt(lp: *mut T) -> Self {
|
||||
let mut me = Self::attach(lp);
|
||||
me.get().add_ref();
|
||||
me
|
||||
}
|
||||
|
||||
/// Get as an `iasset` type.
|
||||
fn get(&mut self) -> &mut iasset {
|
||||
let ptr = self.ptr as *mut iasset;
|
||||
unsafe { &mut *ptr }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Attach to an `iasset` pointer.
|
||||
impl<T> From<*mut T> for AssetPtr<T> {
|
||||
/// Attach to a pointer and increment its reference count.
|
||||
fn from(lp: *mut T) -> Self {
|
||||
AssetPtr::adopt(lp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Attempt to construct `Self` via a conversion.
|
||||
impl<T: NamedInterface> AssetPtr<T> {
|
||||
|
||||
/// Retrieve a supported interface of the managed pointer.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use sciter::video::{AssetPtr, iasset, video_source};
|
||||
/// # let external_ptr: *mut iasset = ::std::ptr::null_mut();
|
||||
/// let mut site = AssetPtr::adopt(external_ptr);
|
||||
/// let source = AssetPtr::<video_source>::try_from(&mut site);
|
||||
/// assert!(source.is_ok());
|
||||
/// ```
|
||||
pub fn try_from<U>(other: &mut AssetPtr<U>) -> Result<Self> {
|
||||
let me = T::query_interface(other.get());
|
||||
me.map(|p| AssetPtr::adopt(p as *mut T)).ok_or(())
|
||||
}
|
||||
}
|
444
libs/rust-sciter/src/window.rs
Normal file
444
libs/rust-sciter/src/window.rs
Normal file
@ -0,0 +1,444 @@
|
||||
/*! High-level native window wrapper.
|
||||
|
||||
To create an instance of Sciter you will need either to create a new Sciter window
|
||||
or to attach (mix-in) the Sciter engine to an existing window.
|
||||
|
||||
The handle of the Sciter engine is defined as `HWINDOW` type which is:
|
||||
|
||||
* `HWND` handle on Microsoft Windows.
|
||||
* `NSView*` – a pointer to [`NSView`](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/) instance that is a contentView of Sciter window on OS X.
|
||||
* `GtkWidget*` – a pointer to [`GtkWidget`](https://developer.gnome.org/gtk3/stable/GtkWidget.html) instance
|
||||
that is a root widget of Sciter window on Linux/GTK.
|
||||
|
||||
## Creation of a new window:
|
||||
|
||||
```no_run
|
||||
extern crate sciter;
|
||||
|
||||
fn main() {
|
||||
let mut frame = sciter::Window::new();
|
||||
frame.load_file("minimal.htm");
|
||||
frame.run_app();
|
||||
}
|
||||
```
|
||||
|
||||
Also you can register a [host](../host/trait.HostHandler.html) and a [DOM](../dom/event/index.html) event handlers.
|
||||
|
||||
.
|
||||
*/
|
||||
use ::{_API};
|
||||
use capi::sctypes::*;
|
||||
|
||||
use platform::{BaseWindow, OsWindow};
|
||||
use host::{Host, HostHandler};
|
||||
use dom::event::{EventHandler};
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
/// `SCITER_CREATE_WINDOW_FLAGS` alias.
|
||||
pub type Flags = SCITER_CREATE_WINDOW_FLAGS;
|
||||
|
||||
pub use capi::scdef::{SCITER_CREATE_WINDOW_FLAGS};
|
||||
|
||||
|
||||
/// Per-window Sciter engine options.
|
||||
///
|
||||
/// Used by [`Window::set_options()`](struct.Window.html#method.set_options).
|
||||
///
|
||||
/// See also [global options](../enum.RuntimeOptions.html).
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Options {
|
||||
/// Enable smooth scrolling, enabled by default.
|
||||
SmoothScroll(bool),
|
||||
|
||||
/// Font rendering, value: `0` - system default, `1` - no smoothing, `2` - standard smoothing, `3` - ClearType.
|
||||
FontSmoothing(u8),
|
||||
|
||||
/// Windows Aero support, value: `false` - normal drawing, `true` - window has transparent background after calls
|
||||
/// [`DwmExtendFrameIntoClientArea()`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969512(v=vs.85).aspx)
|
||||
/// or [`DwmEnableBlurBehindWindow()`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969508(v=vs.85).aspx).
|
||||
TransparentWindow(bool),
|
||||
|
||||
/// Transparent windows support. When enabled, window uses per pixel alpha
|
||||
/// (e.g. [`WS_EX_LAYERED`](https://msdn.microsoft.com/en-us/library/ms997507.aspx?f=255&MSPPError=-2147217396) window).
|
||||
AlphaWindow(bool),
|
||||
|
||||
/// global or per-window; enables Sciter Inspector for this window, must be called before loading HTML.
|
||||
DebugMode(bool),
|
||||
|
||||
/// global or per-window; value: combination of [`SCRIPT_RUNTIME_FEATURES`](../enum.SCRIPT_RUNTIME_FEATURES.html) flags.
|
||||
ScriptFeatures(u8),
|
||||
|
||||
/// Window is main, will destroy all other dependent windows on close, since 4.3.0.12
|
||||
MainWindow(bool),
|
||||
}
|
||||
|
||||
|
||||
/// Sciter window.
|
||||
pub struct Window
|
||||
{
|
||||
base: OsWindow,
|
||||
host: Rc<Host>,
|
||||
}
|
||||
|
||||
// `Window::new()` is rather expensive operation to make it default.
|
||||
#[allow(clippy::new_without_default)]
|
||||
impl Window {
|
||||
|
||||
/// Create a new main window.
|
||||
// #[cfg(not(feature = "windowless"))]
|
||||
#[cfg_attr(feature = "windowless", deprecated = "Sciter.Lite doesn't have OS windows in windowless mode.")]
|
||||
pub fn new() -> Window {
|
||||
Builder::main_window().create()
|
||||
}
|
||||
|
||||
/// Create a new window with the specified position, flags and an optional parent window.
|
||||
#[cfg_attr(feature = "windowless", deprecated = "Sciter.Lite doesn't have OS windows in windowless mode.")]
|
||||
pub fn create(rect: RECT, flags: Flags, parent: Option<HWINDOW>) -> Window {
|
||||
if cfg!(feature = "windowless")
|
||||
{
|
||||
panic!("Sciter.Lite doesn't have OS windows in windowless mode!");
|
||||
}
|
||||
|
||||
let mut base = OsWindow::new();
|
||||
let hwnd = base.create(rect, flags as UINT, parent.unwrap_or(0 as HWINDOW));
|
||||
assert!(!hwnd.is_null());
|
||||
|
||||
let wnd = Window { base: base, host: Rc::new(Host::attach(hwnd))};
|
||||
return wnd;
|
||||
}
|
||||
|
||||
/// Attach Sciter to an existing native window.
|
||||
pub fn attach(hwnd: HWINDOW) -> Window {
|
||||
// suppress warnings about unused method
|
||||
let _ = &OsWindow::new;
|
||||
|
||||
assert!(!hwnd.is_null());
|
||||
Window { base: OsWindow::from(hwnd), host: Rc::new(Host::attach(hwnd)) }
|
||||
}
|
||||
|
||||
/// Obtain a reference to `Host` which allows you to control Sciter engine.
|
||||
pub fn get_host(&self) -> Rc<Host> {
|
||||
self.host.clone()
|
||||
}
|
||||
|
||||
/// Set [callback](../host/trait.HostHandler.html) for Sciter engine events.
|
||||
pub fn sciter_handler<Callback: HostHandler + Sized>(&mut self, handler: Callback) {
|
||||
self.host.setup_callback(handler);
|
||||
}
|
||||
|
||||
/// Attach [`dom::EventHandler`](../dom/event/trait.EventHandler.html) to the Sciter window.
|
||||
///
|
||||
/// You should install Window event handler only once - it will survive all document reloads.
|
||||
/// Also it can be registered on an empty window before the document is loaded.
|
||||
pub fn event_handler<Handler: EventHandler>(&mut self, handler: Handler) {
|
||||
self.host.attach_handler(handler);
|
||||
}
|
||||
|
||||
/// Register an archive produced by `packfolder` tool.
|
||||
///
|
||||
/// The resources can be accessed via the `this://app/` URL.
|
||||
///
|
||||
/// See documentation of the [`Archive`](../host/struct.Archive.html).
|
||||
///
|
||||
pub fn archive_handler(&mut self, resource: &[u8]) -> Result<(), ()> {
|
||||
self.host.register_archive(resource)
|
||||
}
|
||||
|
||||
/// Register a native event handler for the specified behavior name.
|
||||
///
|
||||
/// Behavior is a named event handler which is created for a particular DOM element.
|
||||
/// In Sciter’s sense, it is a function that is called for different UI events on the DOM element.
|
||||
/// Essentially it is an analog of the [WindowProc](https://en.wikipedia.org/wiki/WindowProc) in Windows.
|
||||
///
|
||||
/// In HTML, there is a `behavior` CSS property that defines the name of a native module
|
||||
/// that is responsible for the initialization and event handling on the element.
|
||||
/// For example, by defining `div { behavior:button; }` you are asking all `<div>` elements in your markup
|
||||
/// to behave as buttons: generate [`BUTTON_CLICK`](../dom/event/enum.BEHAVIOR_EVENTS.html#variant.BUTTON_CLICK)
|
||||
/// DOM events when the user clicks on that element, and be focusable.
|
||||
///
|
||||
/// When the engine discovers an element having `behavior: xyz;` defined in its style,
|
||||
/// it sends the [`SC_ATTACH_BEHAVIOR`](../host/trait.HostHandler.html#method.on_attach_behavior) host notification
|
||||
/// with the name `"xyz"` and an element handle to the application.
|
||||
/// You can consume the notification and respond to it yourself,
|
||||
/// or the default handler walks through the list of registered behavior factories
|
||||
/// and creates an instance of the corresponding [`dom::EventHandler`](../dom/event/trait.EventHandler.html).
|
||||
///
|
||||
/// ## Example:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// struct Button;
|
||||
///
|
||||
/// impl sciter::EventHandler for Button {}
|
||||
///
|
||||
/// let mut frame = sciter::Window::new();
|
||||
///
|
||||
/// // register a factory method that creates a new event handler
|
||||
/// // for each element that has "custom-button" behavior:
|
||||
/// frame.register_behavior("custom-button", || { Box::new(Button) });
|
||||
/// ```
|
||||
///
|
||||
/// And in HTML it can be used as:
|
||||
///
|
||||
/// ```html
|
||||
/// <button style="behavior: custom-button">Rusty button</button>
|
||||
/// ```
|
||||
pub fn register_behavior<Factory>(&mut self, name: &str, factory: Factory)
|
||||
where
|
||||
Factory: Fn() -> Box<dyn EventHandler> + 'static
|
||||
{
|
||||
self.host.register_behavior(name, factory);
|
||||
}
|
||||
|
||||
/// Load an HTML document from file.
|
||||
///
|
||||
/// The specified `uri` should be either an absolute file path
|
||||
/// or a full URL to the HTML to load.
|
||||
///
|
||||
/// Supported URL schemes are: `http://`, `file://`, `this://app/` (when used with [`archive_handler`](#archive_handler)).
|
||||
pub fn load_file(&mut self, uri: &str) -> bool {
|
||||
self.host.load_file(uri)
|
||||
}
|
||||
|
||||
/// Load an HTML document from memory.
|
||||
pub fn load_html(&mut self, html: &[u8], uri: Option<&str>) -> bool {
|
||||
self.host.load_html(html, uri)
|
||||
}
|
||||
|
||||
/// Get native window handle.
|
||||
pub fn get_hwnd(&self) -> HWINDOW {
|
||||
self.base.get_hwnd()
|
||||
}
|
||||
|
||||
/// Minimize or hide window.
|
||||
pub fn collapse(&self, hide: bool) {
|
||||
self.base.collapse(hide)
|
||||
}
|
||||
|
||||
/// Show or maximize window.
|
||||
pub fn expand(&self, maximize: bool) {
|
||||
self.base.expand(maximize)
|
||||
}
|
||||
|
||||
/// Close window.
|
||||
pub fn dismiss(&self) {
|
||||
self.base.dismiss()
|
||||
}
|
||||
|
||||
/// Set title of native window.
|
||||
pub fn set_title(&mut self, title: &str) {
|
||||
self.base.set_title(title)
|
||||
}
|
||||
|
||||
/// Get native window title.
|
||||
pub fn get_title(&self) -> String {
|
||||
self.base.get_title()
|
||||
}
|
||||
|
||||
/// Set various Sciter engine options, see the [`Options`](enum.Options.html).
|
||||
pub fn set_options(&self, options: Options) -> Result<(), ()> {
|
||||
use capi::scdef::SCITER_RT_OPTIONS::*;
|
||||
use self::Options::*;
|
||||
let (option, value) = match options {
|
||||
SmoothScroll(enable) => (SCITER_SMOOTH_SCROLL, enable as usize),
|
||||
FontSmoothing(technology) => (SCITER_FONT_SMOOTHING, technology as usize),
|
||||
TransparentWindow(enable) => (SCITER_TRANSPARENT_WINDOW, enable as usize),
|
||||
AlphaWindow(enable) => (SCITER_ALPHA_WINDOW, enable as usize),
|
||||
MainWindow(enable) => (SCITER_SET_MAIN_WINDOW, enable as usize),
|
||||
DebugMode(enable) => (SCITER_SET_DEBUG_MODE, enable as usize),
|
||||
ScriptFeatures(mask) => (SCITER_SET_SCRIPT_RUNTIME_FEATURES, mask as usize),
|
||||
};
|
||||
let ok = (_API.SciterSetOption)(self.get_hwnd(), option, value);
|
||||
if ok != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Show window and run the main app message loop until window been closed.
|
||||
pub fn run_app(self) {
|
||||
self.base.expand(false);
|
||||
self.base.run_app();
|
||||
}
|
||||
|
||||
/// Run the main app message loop with already configured window.
|
||||
pub fn run_loop(&self) {
|
||||
self.base.run_app();
|
||||
}
|
||||
|
||||
/// Post app quit message.
|
||||
pub fn quit_app(&self) {
|
||||
self.base.quit_app()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Generic rectangle struct.
|
||||
/// NOTE that this is different from the [`RECT`](../types/struct.RECT.html) type as it specifies width and height.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Rectangle {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub width: i32,
|
||||
pub height: i32
|
||||
}
|
||||
|
||||
|
||||
/// Builder pattern for window creation.
|
||||
///
|
||||
/// For example,
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// let mut frame = sciter::window::Builder::main_window()
|
||||
/// .with_size((800,600))
|
||||
/// .resizeable()
|
||||
/// .glassy()
|
||||
/// .create();
|
||||
/// ```
|
||||
#[derive(Default)]
|
||||
pub struct Builder {
|
||||
flags: Flags,
|
||||
rect: RECT,
|
||||
parent: Option<HWINDOW>,
|
||||
}
|
||||
|
||||
// Note: https://rust-lang-nursery.github.io/api-guidelines/type-safety.html#non-consuming-builders-preferred
|
||||
impl Builder {
|
||||
|
||||
/// Main application window (resizeable with min/max buttons and title).
|
||||
/// Will terminate the app on close.
|
||||
pub fn main_window() -> Self {
|
||||
Builder::main()
|
||||
.resizeable()
|
||||
.closeable()
|
||||
.with_title()
|
||||
}
|
||||
|
||||
/// Popup window (with min/max buttons and title).
|
||||
pub fn popup_window() -> Self {
|
||||
Builder::popup()
|
||||
.closeable()
|
||||
.with_title()
|
||||
}
|
||||
|
||||
/// Child window style. if this flag is set all other flags are ignored.
|
||||
pub fn child_window() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_CHILD)
|
||||
}
|
||||
|
||||
/// If you want to start from scratch.
|
||||
pub fn none() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_CHILD) // 0
|
||||
}
|
||||
|
||||
/// Start with some flags.
|
||||
pub fn with_flags(flags: Flags) -> Self {
|
||||
let mut me = Builder::default();
|
||||
me.flags = flags;
|
||||
me
|
||||
}
|
||||
|
||||
/// Main window style (appears in taskbar).
|
||||
/// Will terminate the app on close.
|
||||
pub fn main() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_MAIN)
|
||||
}
|
||||
|
||||
/// Popup style, window is created as topmost.
|
||||
pub fn popup() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_POPUP)
|
||||
}
|
||||
|
||||
/// Tool window style (with thin titlebar).
|
||||
pub fn tool() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_TOOL)
|
||||
}
|
||||
|
||||
/// Specify the parent window (e.g. for child creation).
|
||||
pub fn with_parent(mut self, parent: HWINDOW) -> Self {
|
||||
self.parent = Some(parent);
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify the precise window size in `(width, height)` form.
|
||||
pub fn with_size(mut self, size: (i32, i32)) -> Self {
|
||||
self.rect.right = self.rect.left + size.0;
|
||||
self.rect.bottom = self.rect.top + size.1;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify the precise window position in `(X, Y)` form.
|
||||
pub fn with_pos(mut self, position: (i32, i32)) -> Self {
|
||||
let size = self.rect.size();
|
||||
self.rect.left = position.0;
|
||||
self.rect.top = position.1;
|
||||
self.rect.right = position.0 + size.cx;
|
||||
self.rect.bottom = position.1 + size.cy;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify the exact window rectangle in `(X, Y, W, H)` form.
|
||||
pub fn with_rect(mut self, rect: Rectangle) -> Self {
|
||||
self.rect = RECT {
|
||||
left: rect.x,
|
||||
top: rect.y,
|
||||
right: rect.x + rect.width,
|
||||
bottom: rect.y + rect.height,
|
||||
};
|
||||
self
|
||||
}
|
||||
|
||||
/// Top level window, has titlebar.
|
||||
pub fn with_title(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_TITLEBAR)
|
||||
}
|
||||
|
||||
/// Can be resized.
|
||||
pub fn resizeable(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_RESIZEABLE)
|
||||
}
|
||||
|
||||
/// Can not be resized.
|
||||
pub fn fixed(self) -> Self {
|
||||
self.and(SCITER_CREATE_WINDOW_FLAGS::SW_RESIZEABLE)
|
||||
}
|
||||
|
||||
/// Has minimize / maximize buttons.
|
||||
pub fn closeable(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_CONTROLS)
|
||||
}
|
||||
|
||||
/// Glassy window ("Acrylic" on Windows and "Vibrant" on macOS).
|
||||
pub fn glassy(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_GLASSY)
|
||||
}
|
||||
|
||||
/// Transparent window.
|
||||
pub fn alpha(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_ALPHA)
|
||||
}
|
||||
|
||||
/// Can be debugged with Inspector.
|
||||
pub fn debug(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_ENABLE_DEBUG)
|
||||
}
|
||||
|
||||
fn or(mut self, flag: Flags) -> Self {
|
||||
self.flags = self.flags | flag;
|
||||
self
|
||||
}
|
||||
|
||||
fn and(mut self, flag: Flags) -> Self {
|
||||
let masked = self.flags as u32 & !(flag as u32);
|
||||
self.flags = unsafe { ::std::mem::transmute(masked) };
|
||||
self
|
||||
}
|
||||
|
||||
/// Consume the builder and call [`Window::create()`](struct.Window.html#method.create) with built parameters.
|
||||
#[cfg_attr(feature = "windowless", deprecated = "Sciter.Lite doesn't have OS windows in windowless mode.")]
|
||||
pub fn create(self) -> Window {
|
||||
Window::create(self.rect, self.flags, self.parent)
|
||||
}
|
||||
}
|
330
libs/rust-sciter/src/windowless.rs
Normal file
330
libs/rust-sciter/src/windowless.rs
Normal file
@ -0,0 +1,330 @@
|
||||
/*! Windowless Sciter.
|
||||
|
||||
Windowless here means that Sciter does not use any `HWND`, `NSView*` or whatever OS uses for window designation.
|
||||
You just need to provide something of size `void*` that will be associated with the instance of the engine.
|
||||
|
||||
Check out [this article](https://sciter.com/sciter-lite-is-published/) on sciter.com that explains
|
||||
the difference between the desktop and the windowless Sciter engine versions.
|
||||
|
||||
*/
|
||||
|
||||
use ::{_API};
|
||||
use capi::scdef::{GFX_LAYER};
|
||||
use capi::scdom::HELEMENT;
|
||||
use capi::sctypes::{HWINDOW, POINT, UINT, BOOL, RECT, LPCBYTE, LPVOID, INT};
|
||||
use capi::scmsg::*;
|
||||
|
||||
pub use capi::scmsg::key_codes;
|
||||
pub use capi::scbehavior::{MOUSE_BUTTONS, MOUSE_EVENTS, KEYBOARD_STATES, KEY_EVENTS};
|
||||
|
||||
|
||||
/// Application-provided events to notify Sciter.
|
||||
#[derive(Debug)]
|
||||
pub enum Message {
|
||||
/// Creates an instance of Sciter assotiated with the given handle.
|
||||
Create {
|
||||
/// Graphics backend for rendering.
|
||||
backend: GFX_LAYER,
|
||||
/// Background transparency option.
|
||||
transparent: bool,
|
||||
},
|
||||
|
||||
/// Destroys the engine instance.
|
||||
Destroy,
|
||||
|
||||
/// Window size changes.
|
||||
Size {
|
||||
/// Width of the rendering surface.
|
||||
width: u32,
|
||||
/// Height of the rendering surface.
|
||||
height: u32,
|
||||
},
|
||||
|
||||
/// Screen resolution changes.
|
||||
Resolution {
|
||||
/// Pixels per inch.
|
||||
ppi: u32,
|
||||
},
|
||||
|
||||
/// Window focus event.
|
||||
Focus {
|
||||
/// Whether the window has got or lost the input focus.
|
||||
enter: bool,
|
||||
},
|
||||
|
||||
/// Time changes in order to process animations, timers and other timed things.
|
||||
Heartbit {
|
||||
/// Absolute steady clock value, e.g. `GetTickCount()` or `glfwGetTime()`.
|
||||
milliseconds: u32,
|
||||
},
|
||||
|
||||
/// Redraw the whole document.
|
||||
Redraw,
|
||||
|
||||
/// Redraw the specific layer.
|
||||
Paint(PaintLayer),
|
||||
|
||||
/// Render to a bitmap.
|
||||
RenderTo(RenderEvent),
|
||||
|
||||
#[cfg(any(windows, doc))]
|
||||
/// Render to a DXGI surface (Windows only, since 4.4.3.27).
|
||||
RenderToDxgiSurface(DxgiRenderEvent),
|
||||
|
||||
/// Mouse input.
|
||||
Mouse(MouseEvent),
|
||||
|
||||
/// Keyboard input.
|
||||
Keyboard(KeyboardEvent),
|
||||
}
|
||||
|
||||
/// Events describing the mouse input.
|
||||
#[derive(Debug)]
|
||||
pub struct MouseEvent {
|
||||
/// A specific mouse event, like "mouse down" or "mouse move".
|
||||
pub event: MOUSE_EVENTS,
|
||||
/// Which mouse button is pressed.
|
||||
pub button: MOUSE_BUTTONS,
|
||||
/// Which keyboard modifier (e.g. Ctrl or Alt) is pressed.
|
||||
pub modifiers: KEYBOARD_STATES,
|
||||
/// Mouse cursor position.
|
||||
pub pos: POINT,
|
||||
}
|
||||
|
||||
/// Events describing the keyboard input.
|
||||
#[derive(Debug)]
|
||||
pub struct KeyboardEvent {
|
||||
/// A specific key event, like "key down" or "key up".
|
||||
pub event: KEY_EVENTS,
|
||||
/// A key code:
|
||||
///
|
||||
/// * a keyboard [scan-code](key_codes/index.html)
|
||||
/// for [`KEY_DOWN`](enum.KEY_EVENTS.html#variant.KEY_DOWN)
|
||||
/// and [`KEY_UP`](enum.KEY_EVENTS.html#variant.KEY_UP) events;
|
||||
/// * a Unicode code point for [`KEY_CHAR`](enum.KEY_EVENTS.html#variant.KEY_CHAR).
|
||||
pub code: UINT,
|
||||
/// Which keyboard modifier (e.g. Ctrl or Alt) is pressed.
|
||||
pub modifiers: KEYBOARD_STATES,
|
||||
}
|
||||
|
||||
/// A specific UI layer to redraw.
|
||||
#[derive(Debug)]
|
||||
pub struct PaintLayer {
|
||||
/// A DOM element (layer) to render.
|
||||
pub element: HELEMENT,
|
||||
|
||||
/// Whether the `element` is the topmost layer or a background one.
|
||||
pub is_foreground: bool,
|
||||
}
|
||||
|
||||
/// Events for rendering UI to a bitmap.
|
||||
pub struct RenderEvent
|
||||
{
|
||||
/// Which layer to render (or the whole document if `None`).
|
||||
pub layer: Option<PaintLayer>,
|
||||
|
||||
/// The callback that receives a rendered bitmap.
|
||||
///
|
||||
/// The first argument contains a rectangle with the coordinates (position and size) of the rendered bitmap.
|
||||
///
|
||||
/// The second ardument is the rendered bitmap in the `BGRA` form. The size of the bitmap equals to `width * height * 4`.
|
||||
pub callback: Box<dyn Fn(&RECT, &[u8])>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for RenderEvent {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fmt
|
||||
.debug_struct("RenderEvent")
|
||||
.field("layer", &self.layer)
|
||||
.field("callback", &"Box<dyn Fn>")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(windows, doc))]
|
||||
#[derive(Debug)]
|
||||
/// Events for rendering UI to a DXGI surface.
|
||||
///
|
||||
/// Since 4.4.3.27.
|
||||
pub struct DxgiRenderEvent {
|
||||
/// Which layer to render (or the whole document if `None`).
|
||||
pub layer: Option<PaintLayer>,
|
||||
|
||||
/// [`IDXGISurface`](https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nn-dxgi-idxgisurface) pointer.
|
||||
pub surface: LPVOID,
|
||||
}
|
||||
|
||||
|
||||
/// Notify Sciter about UI-specific events.
|
||||
///
|
||||
/// `wnd` here is not a window handle but rather a window instance (pointer).
|
||||
pub fn handle_message(wnd: HWINDOW, event: Message) -> bool
|
||||
{
|
||||
let ok = match event {
|
||||
Message::Create { backend, transparent } => {
|
||||
let msg = SCITER_X_MSG_CREATE {
|
||||
header: SCITER_X_MSG_CODE::SXM_CREATE.into(),
|
||||
backend,
|
||||
transparent: transparent as BOOL,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Destroy => {
|
||||
let msg = SCITER_X_MSG_DESTROY {
|
||||
header: SCITER_X_MSG_CODE::SXM_DESTROY.into(),
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Size { width, height} => {
|
||||
let msg = SCITER_X_MSG_SIZE {
|
||||
header: SCITER_X_MSG_CODE::SXM_SIZE.into(),
|
||||
width,
|
||||
height,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Resolution { ppi } => {
|
||||
let msg = SCITER_X_MSG_RESOLUTION {
|
||||
header: SCITER_X_MSG_CODE::SXM_RESOLUTION.into(),
|
||||
ppi,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Focus { enter } => {
|
||||
let msg = SCITER_X_MSG_FOCUS {
|
||||
header: SCITER_X_MSG_CODE::SXM_FOCUS.into(),
|
||||
enter: enter as BOOL,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Heartbit { milliseconds } => {
|
||||
let msg = SCITER_X_MSG_HEARTBIT {
|
||||
header: SCITER_X_MSG_CODE::SXM_HEARTBIT.into(),
|
||||
time: milliseconds,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Mouse(params) => {
|
||||
let msg = SCITER_X_MSG_MOUSE {
|
||||
header: SCITER_X_MSG_CODE::SXM_MOUSE.into(),
|
||||
|
||||
event: params.event,
|
||||
button: params.button,
|
||||
modifiers: params.modifiers as u32,
|
||||
pos: params.pos,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Keyboard(params) => {
|
||||
let msg = SCITER_X_MSG_KEY {
|
||||
header: SCITER_X_MSG_CODE::SXM_KEY.into(),
|
||||
|
||||
event: params.event,
|
||||
code: params.code,
|
||||
modifiers: params.modifiers as u32,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Redraw => {
|
||||
use std::ptr;
|
||||
let msg = SCITER_X_MSG_PAINT {
|
||||
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
|
||||
element: ptr::null_mut(),
|
||||
isFore: true as BOOL,
|
||||
targetType: SCITER_PAINT_TARGET_TYPE::SPT_DEFAULT,
|
||||
context: ptr::null_mut(),
|
||||
callback: None,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Paint(paint) => {
|
||||
let msg = SCITER_X_MSG_PAINT {
|
||||
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
|
||||
element: paint.element,
|
||||
isFore: paint.is_foreground as BOOL,
|
||||
targetType: SCITER_PAINT_TARGET_TYPE::SPT_DEFAULT,
|
||||
context: std::ptr::null_mut(),
|
||||
callback: None,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
#[cfg(windows)]
|
||||
Message::RenderToDxgiSurface(paint) => {
|
||||
let layer = paint.layer.unwrap_or(PaintLayer {
|
||||
element: std::ptr::null_mut(),
|
||||
is_foreground: false,
|
||||
});
|
||||
|
||||
let msg = SCITER_X_MSG_PAINT {
|
||||
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
|
||||
element: layer.element,
|
||||
isFore: layer.is_foreground as BOOL,
|
||||
targetType: SCITER_PAINT_TARGET_TYPE::SPT_SURFACE,
|
||||
context: paint.surface,
|
||||
callback: None,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::RenderTo(paint) => {
|
||||
|
||||
struct Callback {
|
||||
callback: Box<dyn Fn(&RECT, &[u8])>,
|
||||
}
|
||||
|
||||
extern "system" fn inner(rgba: LPCBYTE, x: INT, y: INT, width: UINT, height: UINT, param: LPVOID)
|
||||
{
|
||||
assert!(!param.is_null());
|
||||
assert!(!rgba.is_null());
|
||||
if param.is_null() || rgba.is_null() { return; }
|
||||
|
||||
let bitmap_area = RECT {
|
||||
left: x,
|
||||
top: y,
|
||||
right: x + width as INT,
|
||||
bottom: y + height as INT,
|
||||
};
|
||||
|
||||
let bitmap_size = width * height * 4;
|
||||
let bitmap_data = unsafe { std::slice::from_raw_parts(rgba, bitmap_size as usize) };
|
||||
|
||||
let param = param as *const Callback;
|
||||
let wrapper = unsafe { &*param };
|
||||
(wrapper.callback)(&bitmap_area, bitmap_data);
|
||||
}
|
||||
|
||||
let wrapper = Callback {
|
||||
callback: paint.callback,
|
||||
};
|
||||
let param = &wrapper as *const _ as LPVOID;
|
||||
|
||||
let layer = paint.layer.unwrap_or(PaintLayer {
|
||||
element: std::ptr::null_mut(),
|
||||
is_foreground: false,
|
||||
});
|
||||
|
||||
let msg = SCITER_X_MSG_PAINT {
|
||||
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
|
||||
element: layer.element,
|
||||
isFore: layer.is_foreground as BOOL,
|
||||
targetType: SCITER_PAINT_TARGET_TYPE::SPT_RECEIVER,
|
||||
context: param,
|
||||
callback: Some(inner),
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
ok != 0
|
||||
}
|
195
libs/rust-sciter/tests/graphics.rs
Normal file
195
libs/rust-sciter/tests/graphics.rs
Normal file
@ -0,0 +1,195 @@
|
||||
// Note: there is an issue in Sciter that you can't just call its functions out of nowhere,
|
||||
// you are supposed to have a main thread.
|
||||
// Since Rust always spawns a thread per test (it does not matter, to spawn 1 or more threads),
|
||||
// so we have a problem here.
|
||||
// If I could create a dedicated "main" thread per test module, that would be fine.
|
||||
|
||||
#![allow(unused_variables)]
|
||||
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::graphics::*;
|
||||
|
||||
const OK: Result<()> = Ok(());
|
||||
|
||||
macro_rules! assert_ok {
|
||||
($left:expr, $right:expr) => {
|
||||
assert_eq!($left, $right.map(|_| ()));
|
||||
};
|
||||
}
|
||||
|
||||
fn get() -> Image {
|
||||
Image::create((100, 100), true).expect("Can't create a `100x100` image")
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn image_new() {
|
||||
let ok = Image::create((100, 100), false);
|
||||
assert_ok!(OK, ok);
|
||||
|
||||
let ok = Image::create((100, 100), true);
|
||||
assert_ok!(OK, ok);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn image_dimensions() {
|
||||
let size = get().dimensions().unwrap();
|
||||
assert_eq!((100, 100), size);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn image_save() {
|
||||
let ok = get().save(SaveImageEncoding::Raw);
|
||||
assert!(ok.is_ok());
|
||||
assert_eq!(ok.unwrap().len(), 100 * 100 * 4);
|
||||
|
||||
fn verify(image: &Image, format: SaveImageEncoding) -> Result<()> {
|
||||
image.save(format).map(|_| ())
|
||||
}
|
||||
|
||||
let image = get();
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Png));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Jpeg(10)));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Jpeg(100)));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Webp(0)));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Webp(10)));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Webp(100)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn image_load() {
|
||||
fn verify(image: &Image, format: SaveImageEncoding) -> Result<()> {
|
||||
let ok = image.save(format).and_then(|saved| Image::load(&saved));
|
||||
ok.map(|_| ())
|
||||
}
|
||||
|
||||
let image = get();
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Png));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Jpeg(10)));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Jpeg(100)));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Webp(0)));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Webp(10)));
|
||||
assert_ok!(OK, verify(&image, SaveImageEncoding::Webp(100)));
|
||||
|
||||
let r = image.save(SaveImageEncoding::Raw).and_then(|saved| {
|
||||
let size = image.dimensions().unwrap();
|
||||
Image::with_data(size, true, &saved)
|
||||
});
|
||||
assert_ok!(OK, r);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
fn load_formats() {
|
||||
// The following images were taken from https://github.com/mathiasbynens/small.
|
||||
|
||||
fn verify(data: &[u8]) -> Result<()> {
|
||||
Image::load(data).map(|_| ())
|
||||
}
|
||||
|
||||
let bmp = [
|
||||
0x42,0x4d,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x1a,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x01,0x00,
|
||||
0x01,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0xff,0x00
|
||||
];
|
||||
|
||||
let gif = [
|
||||
0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,
|
||||
0x80,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x21,
|
||||
0xf9,0x04,0x01,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,
|
||||
0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x01,0x44,
|
||||
0x00,0x3b
|
||||
];
|
||||
|
||||
let ico = [
|
||||
0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x01,0x00,0x00,
|
||||
0x01,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x16,0x00,
|
||||
0x00,0x00,0x28,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
|
||||
0x02,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00
|
||||
];
|
||||
|
||||
let jpeg = [ // a 121-byte one from d75477e
|
||||
0xff,0xd8,0xff,0xdb,0x00,0x43,0x00,0x01,0x01,0x01,
|
||||
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
|
||||
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
|
||||
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
|
||||
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
|
||||
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
|
||||
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
|
||||
0x01,0xff,0xc2,0x00,0x0b,0x08,0x00,0x01,0x00,0x01,
|
||||
0x01,0x01,0x11,0x00,0xff,0xc4,0x00,0x14,0x00,0x01,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xff,0xda,
|
||||
0x00,0x08,0x01,0x01,0x00,0x00,0x00,0x01,0x3f,0xff,
|
||||
0xd9
|
||||
];
|
||||
|
||||
let png = [
|
||||
0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,
|
||||
0x00,0x0d,0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x01,
|
||||
0x00,0x00,0x00,0x01,0x08,0x06,0x00,0x00,0x00,0x1f,
|
||||
0x15,0xc4,0x89,0x00,0x00,0x00,0x0a,0x49,0x44,0x41,
|
||||
0x54,0x78,0x9c,0x63,0x00,0x01,0x00,0x00,0x05,0x00,
|
||||
0x01,0x0d,0x0a,0x2d,0xb4,0x00,0x00,0x00,0x00,0x49,
|
||||
0x45,0x4e,0x44,0xae,0x42,0x60,0x82
|
||||
];
|
||||
|
||||
let webp = [
|
||||
0x52,0x49,0x46,0x46,0x12,0x00,0x00,0x00,0x57,0x45,
|
||||
0x42,0x50,0x56,0x50,0x38,0x4c,0x06,0x00,0x00,0x00,
|
||||
0x2f,0x41,0x6c,0x6f,0x00,0x6b
|
||||
];
|
||||
|
||||
println!();
|
||||
println!("verify(&bmp): {}", verify(&bmp).is_ok());
|
||||
println!("verify(&gif): {}", verify(&gif).is_ok());
|
||||
println!("verify(&ico): {}", verify(&ico).is_ok());
|
||||
println!("verify(&jpeg) {}", verify(&jpeg).is_ok());
|
||||
println!("verify(&png): {}", verify(&png).is_ok());
|
||||
println!("verify(&webp) {}", verify(&webp).is_ok());
|
||||
|
||||
#[cfg(windows)]
|
||||
assert_ok!(OK, verify(&bmp));
|
||||
assert_ok!(OK, verify(&gif));
|
||||
#[cfg(windows)]
|
||||
assert_ok!(OK, verify(&ico));
|
||||
assert_ok!(OK, verify(&jpeg));
|
||||
assert_ok!(OK, verify(&png));
|
||||
assert_ok!(OK, verify(&webp));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn image_clear() {
|
||||
assert_eq!(OK, get().clear());
|
||||
assert_eq!(OK, get().clear_with(rgb(255, 255, 255)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn make_color() {
|
||||
// ABGR
|
||||
assert_eq!(0xFF000000, rgb(0, 0, 0));
|
||||
assert_eq!(0x00000000, rgba((0, 0, 0), 0));
|
||||
|
||||
assert_eq!(0xFF112233, rgb(0x33, 0x22, 0x11));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn paint() {
|
||||
let mut image = Image::create((100, 100), false).unwrap();
|
||||
let ok = image.paint(|gfx, size| {
|
||||
gfx.rectangle((5.0, 5.0), (size.0 - 5.0, size.1 - 5.0))?;
|
||||
Ok(())
|
||||
});
|
||||
assert_ok!(OK, ok);
|
||||
}
|
468
libs/rust-sciter/tests/value.rs
Normal file
468
libs/rust-sciter/tests/value.rs
Normal file
@ -0,0 +1,468 @@
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate sciter;
|
||||
|
||||
use sciter::value::*;
|
||||
|
||||
|
||||
#[test]
|
||||
fn new_works() {
|
||||
let v = Value::new();
|
||||
assert!(v.is_undefined());
|
||||
assert!(!v.is_null());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn varray_works() {
|
||||
let val = varray![];
|
||||
assert!(val.is_array());
|
||||
assert_eq!(val.len(), 0);
|
||||
|
||||
let val = varray![42];
|
||||
assert!(val.is_array());
|
||||
assert_eq!(val.len(), 1);
|
||||
|
||||
let val = varray![1, 2.0, "three"];
|
||||
assert!(val.is_array());
|
||||
assert_eq!(val.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vmap_works() {
|
||||
let map = vmap!{};
|
||||
assert!(map.is_map());
|
||||
assert_eq!(map.len(), 0);
|
||||
|
||||
let map = vmap! {
|
||||
"one" => 1,
|
||||
};
|
||||
assert!(map.is_map());
|
||||
assert_eq!(map.len(), 1);
|
||||
|
||||
let map = vmap! {
|
||||
"one" => 1,
|
||||
"two" => 2.0,
|
||||
"three" => "",
|
||||
};
|
||||
assert!(map.is_map());
|
||||
assert_eq!(map.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn null_works() {
|
||||
let v = Value::null();
|
||||
assert!(!v.is_undefined());
|
||||
assert!(v.is_null());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clear_works() {
|
||||
let mut v = Value::null();
|
||||
assert!(v.is_null());
|
||||
|
||||
v.clear();
|
||||
assert!(!v.is_null());
|
||||
assert!(v.is_undefined());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn symbol_works() {
|
||||
let mut v = Value::symbol("hello");
|
||||
assert!(v.is_symbol());
|
||||
assert!(v.is_string());
|
||||
|
||||
v.clear();
|
||||
assert!(v.is_undefined());
|
||||
}
|
||||
|
||||
fn is_color_supported() -> bool {
|
||||
// e.g. `0x04000100`
|
||||
sciter::version_num() > 0x0400_0100
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn color_works() {
|
||||
if !is_color_supported() { return; }
|
||||
|
||||
// yellow R255, G255, B000
|
||||
// RGBA form in memory, ABGR in integer.
|
||||
let v = Value::color(0x0000_FFFF);
|
||||
assert!(v.is_color());
|
||||
assert_eq!(v.to_color(), Some(0x0000_FFFF));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duration_works() {
|
||||
if !is_color_supported() { return; }
|
||||
|
||||
let v = Value::duration(12.5);
|
||||
assert!(v.is_duration());
|
||||
assert_eq!(v.to_duration(), Some(12.5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn angle_works() {
|
||||
if !is_color_supported() { return; }
|
||||
|
||||
let v = Value::angle(1.0);
|
||||
assert!(v.is_angle());
|
||||
assert_eq!(v.to_angle(), Some(1.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_works() {
|
||||
let v = Value::array(0);
|
||||
assert!(v.is_array());
|
||||
assert!(v.is_empty());
|
||||
|
||||
let v = Value::array(17);
|
||||
assert!(v.is_array());
|
||||
assert!(v.len() == 17);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_works() {
|
||||
let v = Value::map();
|
||||
assert!(v.is_map());
|
||||
assert!(v.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_bool_works() {
|
||||
let v = Value::from(true);
|
||||
assert!(v.is_bool());
|
||||
let v = Value::from(false);
|
||||
assert!(v.is_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_int_works() {
|
||||
let v = Value::from(1);
|
||||
assert!(v.is_int());
|
||||
assert!(!v.is_bool());
|
||||
|
||||
Value::from(1 as i32);
|
||||
// Value::from(1 as u32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_float_works() {
|
||||
let v = Value::from(1.0);
|
||||
assert!(v.is_float());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn from_str_works() {
|
||||
use std::str::FromStr;
|
||||
|
||||
let v = Value::from("hello");
|
||||
assert!(v.is_string());
|
||||
|
||||
let s = String::from("hello");
|
||||
let v = Value::from(s.as_str());
|
||||
|
||||
let v = Value::from_str("hello");
|
||||
let v = Value::from_str(&s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_int_seq_works() {
|
||||
let v: Value = [1,2,3].iter().cloned().collect();
|
||||
assert!(v.is_array());
|
||||
assert_eq!(v.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_seq_works() {
|
||||
// &str
|
||||
let v: Value = ["1","2","3"].iter().cloned().collect();
|
||||
assert!(v.is_array());
|
||||
assert_eq!(v.len(), 3);
|
||||
|
||||
// String
|
||||
let v: Value = ["1","2","3"].iter().map(|x| x.to_string()).collect();
|
||||
assert!(v.is_array());
|
||||
assert_eq!(v.len(), 3);
|
||||
assert_eq!(v[2].as_string(), Some("3".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_function_works() {
|
||||
// create from lambda
|
||||
let v = Value::from(|args: &[Value]| Value::from(args.len() as i32));
|
||||
assert!(v.is_native_function());
|
||||
|
||||
let args = [Value::from(17), Value::from(42)];
|
||||
let r = v.call(None, &args, None);
|
||||
|
||||
assert!(r.is_ok());
|
||||
assert_eq!(r.unwrap(), Value::from(args.len() as i32));
|
||||
|
||||
// create from function
|
||||
fn inner_fn(args: &[Value]) -> Value {
|
||||
Value::array(args.len())
|
||||
}
|
||||
|
||||
let v = Value::from(inner_fn);
|
||||
assert!(v.is_native_function());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_result_works() {
|
||||
// create Err variant
|
||||
let result: Result<i32, String> = Err("unknown error".to_string());
|
||||
let v = Value::from(result);
|
||||
assert_eq!(v.as_string().unwrap(), "unknown error");
|
||||
|
||||
// create Ok variant
|
||||
let result: Result<i32, String> = Ok(100);
|
||||
let v = Value::from(result);
|
||||
assert_eq!(v.to_int().unwrap(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_works() {
|
||||
let items = ["", "null", "1", "\"2\"", "2.0", "true", "[3, 4]", r##"{"5": 5, "6": 6, seven: "seven"}"##];
|
||||
for item in &items {
|
||||
let r = Value::parse(item);
|
||||
if let Err(num) = r {
|
||||
panic!("parse({}) failed on character {} of {}", item, num, item.len());
|
||||
}
|
||||
}
|
||||
|
||||
let v :Value = "4".parse().unwrap();
|
||||
assert_eq!(v.to_int(), Some(4));
|
||||
|
||||
let v = "true".parse::<Value>().unwrap();
|
||||
assert_eq!(v.to_bool(), Some(true));
|
||||
}
|
||||
|
||||
#[test] // crashes with 1.7.0 i686-pc-windows-msvc
|
||||
#[should_panic(expected="failed on character")]
|
||||
fn parse_fail_works() {
|
||||
let item = "{item: "; // invalid json
|
||||
let r = Value::parse(item);
|
||||
if let Err(num) = r {
|
||||
panic!("parse({}) failed on character {} of {}", item, num, item.len());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pack_args_works() {
|
||||
let args = pack_args!();
|
||||
assert_eq!(args.len(), 0);
|
||||
|
||||
let args = pack_args!(777);
|
||||
assert_eq!(args.len(), 1);
|
||||
|
||||
let args = pack_args!(1,2,3);
|
||||
assert_eq!(args.len(), 3);
|
||||
|
||||
let args = pack_args!(1, "2", 3.0);
|
||||
assert_eq!(args.len(), 3);
|
||||
|
||||
let args = pack_args!(1,2,3);
|
||||
let unpacked = unsafe { Value::unpack_from(args.as_ptr(), args.len() as u32) };
|
||||
assert_eq!(unpacked.len(), 3);
|
||||
assert_eq!(unpacked[0], Value::from(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn make_args_works() {
|
||||
let args = make_args!();
|
||||
assert_eq!(args.len(), 0);
|
||||
|
||||
let args = make_args!(777);
|
||||
assert_eq!(args.len(), 1);
|
||||
|
||||
let args = make_args!(1,2,3);
|
||||
assert_eq!(args.len(), 3);
|
||||
|
||||
let args = make_args!(1, "2", 3.0);
|
||||
assert_eq!(args.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn append_works() {
|
||||
let mut v = Value::new();
|
||||
v.push(Value::from(1));
|
||||
v.push(Value::from("2"));
|
||||
v.push(Value::from(3.0));
|
||||
v.push(Value::from(false));
|
||||
|
||||
assert!(v.is_array());
|
||||
assert_eq!(v.len(), 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_works() {
|
||||
// Value has some implicit conversions:
|
||||
// bool or int -> int
|
||||
// int or float or length -> float
|
||||
// function or string -> string
|
||||
|
||||
let vint = Value::from(1);
|
||||
assert!(vint.is_int());
|
||||
assert!(vint.to_int().is_some());
|
||||
assert!(vint.to_float().is_some());
|
||||
assert_eq!(vint.to_int().unwrap(), 1);
|
||||
|
||||
let vbool = Value::from(false);
|
||||
assert!(vbool.is_bool());
|
||||
assert!(!vbool.is_int());
|
||||
assert!(vbool.to_bool().is_some());
|
||||
assert!(vbool.to_int().is_some());
|
||||
assert_eq!(vbool.to_bool().unwrap(), false);
|
||||
|
||||
assert_eq!(Value::from(4.2).to_float().unwrap(), 4.2);
|
||||
|
||||
assert_eq!(Value::from("4.2").as_string().unwrap(), "4.2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into_works() {
|
||||
|
||||
let v = Value::from(1);
|
||||
assert!(v.is_int());
|
||||
|
||||
let v: Value = Value::from(1);
|
||||
assert!(v.is_int());
|
||||
|
||||
let v: Value = 1.into();
|
||||
assert!(v.is_int());
|
||||
|
||||
let mut v = Value::new();
|
||||
v.push(false);
|
||||
v.push(1);
|
||||
v.push(3.0);
|
||||
v.push("2");
|
||||
assert!(v.is_array());
|
||||
assert_eq!(v.len(), 4);
|
||||
|
||||
assert_eq!(Value::from(1).into_string(), "1");
|
||||
assert_eq!(Value::from("hello").into_string(), r#""hello""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_work() {
|
||||
let b = [1,2,3];
|
||||
let v = Value::from(&b[..]);
|
||||
assert!(v.is_bytes());
|
||||
assert_eq!(v.as_bytes().expect("must be bytes"), [1,2,3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn index_works() {
|
||||
let mut v = Value::new();
|
||||
v.push(Value::from(1));
|
||||
v.push(Value::from(2));
|
||||
v.push(Value::from(3));
|
||||
|
||||
println!("v {:?}", v);
|
||||
|
||||
assert_eq!(v.len(), 3);
|
||||
assert_eq!(v[0], 1.into());
|
||||
|
||||
v.set(1, 17);
|
||||
assert_eq!(v[1], 17.into());
|
||||
|
||||
let mut v: Value = r##"{"5": 5, "6": 6, seven: "seven"}"##.parse().unwrap();
|
||||
let key = Value::from("seven");
|
||||
v.set_item(key.clone(), Value::from(7.0));
|
||||
println!("map {:?}", v);
|
||||
assert_eq!(v.get_item(key), Value::from(7.0));
|
||||
|
||||
assert_eq!(v.key_at(0), Value::from("5"));
|
||||
assert_eq!(v.key_at(2), Value::symbol("seven"));
|
||||
assert_eq!(v.get_item(v.key_at(1)), Value::from(6));
|
||||
|
||||
// simple syntax:
|
||||
let mut v = Value::map();
|
||||
v.set_item("seven", 7);
|
||||
v.set_item("ten", 10);
|
||||
v.set_item("six", 6);
|
||||
assert_eq!(v["seven"], 7.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_works() {
|
||||
println!("\nvalue strings: new {}, null {}, bool {}, int {}, float {}, symbol {}, str {}",
|
||||
Value::new(), Value::null(), Value::from(true), Value::from(123), Value::from(4.2),
|
||||
Value::symbol("symbol"), Value::from("hello"));
|
||||
|
||||
// assert!(false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn debug_works() {
|
||||
println!("\nvalue strings: {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}",
|
||||
Value::new(), Value::null(), Value::from(true), Value::from(123), Value::from(4.2),
|
||||
Value::symbol("symbol"), Value::from("hello"));
|
||||
|
||||
// assert!(false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thread_works() {
|
||||
let mut v = Value::map();
|
||||
let tid = std::thread::spawn(move || {
|
||||
v.set_item("seven", 7);
|
||||
assert_eq!(v.len(), 1);
|
||||
});
|
||||
tid.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterators_work() {
|
||||
let v: Value = [1,2,3].iter().cloned().collect();
|
||||
|
||||
// `&v` == `v.into_iter()`
|
||||
for a in &v {
|
||||
assert!(a.is_int());
|
||||
}
|
||||
|
||||
for a in v.into_iter() {
|
||||
assert!(a.is_int());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn back_iter() {
|
||||
let v: Value = [1,2,3].iter().cloned().collect();
|
||||
|
||||
let mut iter = v.into_iter();
|
||||
assert_eq!(Some(1.into()), iter.next());
|
||||
assert_eq!(Some(3.into()), iter.next_back());
|
||||
assert_eq!(Some(2.into()), iter.next_back());
|
||||
assert_eq!(None, iter.next_back());
|
||||
assert_eq!(None, iter.next());
|
||||
|
||||
assert_eq!(v.into_iter().rev().map(|a| a.to_int().unwrap()).sum::<i32>(), 1 + 2 + 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keys_work() {
|
||||
let v = Value::parse("five: 5, seven: 7").unwrap();
|
||||
for k in v.keys() {
|
||||
assert!(k.is_string());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn values_work() {
|
||||
let v = Value::parse("five: 5, seven: 7").unwrap();
|
||||
for a in v.values() {
|
||||
assert!(a.is_int());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn items_work() {
|
||||
let v = Value::parse("five: 5, seven: 7").unwrap();
|
||||
for (k,a) in v.items() {
|
||||
assert!(k.is_string());
|
||||
assert!(a.is_int());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user