More tests (#21)
* More tests * Add some tests, refactor code * Some additional tests * Add some tests * Add some tests * Add pixel based tests for UI * Add some tests * Fix surface format * Fix surface format
This commit is contained in:
parent
60d4c0be88
commit
7c01076cc1
110
Cargo.lock
generated
110
Cargo.lock
generated
@ -137,6 +137,38 @@ name = "constant_time_eq"
|
|||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs"
|
name = "dirs"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@ -179,6 +211,11 @@ dependencies = [
|
|||||||
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fuchsia-zircon"
|
name = "fuchsia-zircon"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@ -201,6 +238,11 @@ dependencies = [
|
|||||||
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@ -301,6 +343,14 @@ dependencies = [
|
|||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-error"
|
name = "quick-error"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
@ -314,6 +364,14 @@ dependencies = [
|
|||||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.3.22"
|
version = "0.3.22"
|
||||||
@ -440,6 +498,16 @@ dependencies = [
|
|||||||
"simplelog 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"simplelog 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rider-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rider-editor"
|
name = "rider-editor"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -449,7 +517,9 @@ dependencies = [
|
|||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rider-config 0.1.0",
|
"rider-config 0.1.0",
|
||||||
|
"rider-derive 0.1.0",
|
||||||
"rider-lexers 0.1.0",
|
"rider-lexers 0.1.0",
|
||||||
|
"rider-match-widget 0.1.0",
|
||||||
"rider-themes 0.1.0",
|
"rider-themes 0.1.0",
|
||||||
"sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -483,6 +553,16 @@ dependencies = [
|
|||||||
"simplelog 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"simplelog 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rider-match-widget"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rider-themes"
|
name = "rider-themes"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -566,6 +646,11 @@ dependencies = [
|
|||||||
"term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "0.14.9"
|
version = "0.14.9"
|
||||||
@ -586,6 +671,16 @@ dependencies = [
|
|||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "synstructure"
|
name = "synstructure"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@ -652,6 +747,11 @@ name = "unicode-xid"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8-ranges"
|
name = "utf8-ranges"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -731,13 +831,18 @@ dependencies = [
|
|||||||
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
|
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
|
||||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||||
|
"checksum darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
|
||||||
|
"checksum darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
|
||||||
|
"checksum darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
|
||||||
"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
|
"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
|
||||||
"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
|
"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
|
||||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||||
|
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
|
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
|
||||||
|
"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||||
"checksum lalr 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "106d7548f95adbe3019b4fc4954554d7b72535867aa9ce326d2f766b68958de7"
|
"checksum lalr 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "106d7548f95adbe3019b4fc4954554d7b72535867aa9ce326d2f766b68958de7"
|
||||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||||
@ -752,8 +857,10 @@ dependencies = [
|
|||||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||||
"checksum plex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "59d79bd74b3d0be2619e58217e8b2b96372e3feca8426e5c560623205d70c146"
|
"checksum plex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "59d79bd74b3d0be2619e58217e8b2b96372e3feca8426e5c560623205d70c146"
|
||||||
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
|
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
|
||||||
|
"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
|
||||||
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||||
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
|
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
|
||||||
|
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
||||||
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
|
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
|
||||||
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
|
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
|
||||||
"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
|
"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
|
||||||
@ -774,8 +881,10 @@ dependencies = [
|
|||||||
"checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b"
|
"checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b"
|
||||||
"checksum serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "bdf540260cfee6da923831f4776ddc495ada940c30117977c70f1313a6130545"
|
"checksum serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "bdf540260cfee6da923831f4776ddc495ada940c30117977c70f1313a6130545"
|
||||||
"checksum simplelog 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e95345f185d5adeb8ec93459d2dc99654e294cc6ccf5b75414d8ea262de9a13"
|
"checksum simplelog 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e95345f185d5adeb8ec93459d2dc99654e294cc6ccf5b75414d8ea262de9a13"
|
||||||
|
"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
|
||||||
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
||||||
"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc"
|
"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc"
|
||||||
|
"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
|
||||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||||
"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
|
"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
|
||||||
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
||||||
@ -784,6 +893,7 @@ dependencies = [
|
|||||||
"checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c"
|
"checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c"
|
||||||
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
|
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
|
||||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
|
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||||
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
|
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
|
||||||
"checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6"
|
"checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6"
|
||||||
"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
|
"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
|
||||||
|
@ -10,14 +10,16 @@ members = [
|
|||||||
"rider-config",
|
"rider-config",
|
||||||
"rider-themes",
|
"rider-themes",
|
||||||
"rider-lexers",
|
"rider-lexers",
|
||||||
"rider-editor"
|
"rider-editor",
|
||||||
|
"rider-match-widget"
|
||||||
]
|
]
|
||||||
default-members = [
|
default-members = [
|
||||||
"rider-generator",
|
"rider-generator",
|
||||||
"rider-config",
|
"rider-config",
|
||||||
"rider-themes",
|
"rider-themes",
|
||||||
"rider-lexers",
|
"rider-lexers",
|
||||||
"rider-editor"
|
"rider-editor",
|
||||||
|
"rider-match-widget"
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -102,20 +102,15 @@ impl Config {
|
|||||||
impl Config {
|
impl Config {
|
||||||
pub fn load_theme(&self, theme_name: String) -> Theme {
|
pub fn load_theme(&self, theme_name: String) -> Theme {
|
||||||
let home_dir = dirs::config_dir().unwrap();
|
let home_dir = dirs::config_dir().unwrap();
|
||||||
let mut config_dir = home_dir;
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
config_dir.push("rider");
|
fs::create_dir_all(&home_dir.join("rider"))
|
||||||
fs::create_dir_all(&config_dir)
|
|
||||||
.unwrap_or_else(|_| panic!("Cannot create config directory"));
|
.unwrap_or_else(|_| panic!("Cannot create config directory"));
|
||||||
self.load_theme_content(format!("{}.json", theme_name).as_str())
|
self.load_theme_content(format!("{}.json", theme_name).as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_theme_content(&self, file_name: &str) -> Theme {
|
fn load_theme_content(&self, file_name: &str) -> Theme {
|
||||||
let mut config_file = self.directories.themes_dir.clone();
|
let config_file = self.directories.themes_dir.clone();
|
||||||
config_file.push(file_name);
|
let contents = fs::read_to_string(&config_file.join(file_name)).unwrap_or_default();
|
||||||
let contents = match fs::read_to_string(&config_file) {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(_) => fs::read_to_string(&config_file).unwrap_or_else(|_| "".to_owned()),
|
|
||||||
};
|
|
||||||
serde_json::from_str(&contents).unwrap_or_default()
|
serde_json::from_str(&contents).unwrap_or_default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,21 +189,21 @@ mod test_getters {
|
|||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn assert_editor_config() {
|
fn assert_editor_config() {
|
||||||
// let config = Config::new();
|
let config = Config::new();
|
||||||
// let result = config.editor_config();
|
let result = config.editor_config();
|
||||||
// let expected = 1;
|
let expected = EditorConfig::new(&Directories::new(None, None));
|
||||||
// assert_eq!(result, expected);
|
assert_eq!(result, &expected);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn assert_theme() {
|
fn assert_theme() {
|
||||||
// let config = Config::new();
|
let config = Config::new();
|
||||||
// let result = config.theme();
|
let result = config.theme();
|
||||||
// let expected = 1;
|
let expected = Theme::default();
|
||||||
// assert_eq!(result, expected);
|
assert_eq!(result, &expected);
|
||||||
// }
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_menu_height() {
|
fn assert_menu_height() {
|
||||||
|
@ -21,10 +21,8 @@ impl Directories {
|
|||||||
config_dir.push(path);
|
config_dir.push(path);
|
||||||
config_dir.push("rider");
|
config_dir.push("rider");
|
||||||
|
|
||||||
let path = match project_dir {
|
let path = project_dir
|
||||||
Some(s) => s,
|
.unwrap_or_else(|| dirs::runtime_dir().unwrap().to_str().unwrap().to_owned());
|
||||||
None => dirs::runtime_dir().unwrap().to_str().unwrap().to_owned(),
|
|
||||||
};
|
|
||||||
let mut project_dir = PathBuf::new();
|
let mut project_dir = PathBuf::new();
|
||||||
project_dir.push(path);
|
project_dir.push(path);
|
||||||
project_dir.push(".rider");
|
project_dir.push(".rider");
|
||||||
@ -56,19 +54,12 @@ pub fn themes_dir(config_dir: &PathBuf) -> PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fonts_dir(config_dir: &PathBuf) -> PathBuf {
|
pub fn fonts_dir(config_dir: &PathBuf) -> PathBuf {
|
||||||
let path = config_dir.to_str().unwrap().to_owned();
|
PathBuf::from(config_dir.to_str().unwrap().to_owned()).join("fonts")
|
||||||
let mut path_buf = PathBuf::new();
|
|
||||||
path_buf.push(path);
|
|
||||||
path_buf.push("fonts");
|
|
||||||
path_buf
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
pub fn project_dir() -> PathBuf {
|
pub fn project_dir() -> PathBuf {
|
||||||
let path = dirs::runtime_dir().unwrap().to_str().unwrap().to_owned();
|
PathBuf::from(dirs::runtime_dir().unwrap().to_str().unwrap().to_owned()).join(".rider")
|
||||||
let mut path_buf = PathBuf::new();
|
|
||||||
path_buf.push(path);
|
|
||||||
path_buf.push(".rider");
|
|
||||||
path_buf
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
@ -110,11 +101,10 @@ pub fn binaries_directory() -> Result<PathBuf, String> {
|
|||||||
Err("Cannot find binaries!".to_string())
|
Err("Cannot find binaries!".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
pub fn get_binary_path(name: &str) -> Result<String, String> {
|
pub fn get_binary_path(name: &str) -> Result<String, String> {
|
||||||
if cfg!(test) {
|
if cfg!(test) {
|
||||||
use std::fs;
|
use std::fs;
|
||||||
println!("#[cfg(test)]");
|
|
||||||
|
|
||||||
let mut current_dir = env::current_dir().unwrap();
|
let mut current_dir = env::current_dir().unwrap();
|
||||||
current_dir.push("target");
|
current_dir.push("target");
|
||||||
current_dir.push("debug");
|
current_dir.push("debug");
|
||||||
@ -132,7 +122,6 @@ pub fn get_binary_path(name: &str) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
Err(format!("Cannot find {:?}", name))
|
Err(format!("Cannot find {:?}", name))
|
||||||
} else {
|
} else {
|
||||||
println!("#[cfg(not(test))]");
|
|
||||||
let r = binaries_directory();
|
let r = binaries_directory();
|
||||||
let mut binaries: PathBuf = r.unwrap_or_else(|e| panic!(e));
|
let mut binaries: PathBuf = r.unwrap_or_else(|e| panic!(e));
|
||||||
binaries.push(name.to_string());
|
binaries.push(name.to_string());
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::directories::Directories;
|
use crate::directories::Directories;
|
||||||
|
|
||||||
|
#[cfg_attr(test, derive(PartialEq))]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct EditorConfig {
|
pub struct EditorConfig {
|
||||||
character_size: u16,
|
character_size: u16,
|
||||||
@ -26,8 +27,15 @@ impl EditorConfig {
|
|||||||
self.character_size
|
self.character_size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn font_path(&self) -> &String {
|
pub fn font_path(&self) -> &str {
|
||||||
&self.font_path
|
self.font_path.as_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_font_path<S>(&mut self, path: S)
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
self.font_path = path.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_theme(&self) -> &String {
|
pub fn current_theme(&self) -> &String {
|
||||||
@ -49,9 +57,14 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn assert_font_path() {
|
fn assert_font_path() {
|
||||||
let directories = Directories::new(Some("/tmp".to_owned()), None);
|
let directories = Directories::new(Some("/tmp".to_owned()), None);
|
||||||
let config = EditorConfig::new(&directories);
|
let mut config = EditorConfig::new(&directories);
|
||||||
let path = config.font_path().to_owned();
|
let path = config.font_path();
|
||||||
let expected: String = "/tmp/rider/fonts/DejaVuSansMono.ttf".to_owned();
|
let expected = "/tmp/rider/fonts/DejaVuSansMono.ttf";
|
||||||
|
assert_eq!(path, expected);
|
||||||
|
|
||||||
|
config.set_font_path("/a");
|
||||||
|
let path = config.font_path();
|
||||||
|
let expected = "/a";
|
||||||
assert_eq!(path, expected);
|
assert_eq!(path, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,14 @@ impl Default for ScrollConfig {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_default() {
|
||||||
|
let config = ScrollConfig::default();
|
||||||
|
assert_eq!(config.width, 4);
|
||||||
|
assert_eq!(config.margin_right, 5);
|
||||||
|
assert_eq!(config.speed, 10);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_width() {
|
fn assert_width() {
|
||||||
let config = ScrollConfig::new();
|
let config = ScrollConfig::new();
|
||||||
|
21
rider-derive/Cargo.toml
Normal file
21
rider-derive/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
[package]
|
||||||
|
name = "rider-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Adrian Woźniak <adrian.wozniak.1986@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
darling = { version = "*" }
|
||||||
|
|
||||||
|
[dependencies.proc-macro2]
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
[dependencies.quote]
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
[dependencies.syn]
|
||||||
|
version = "1.0"
|
||||||
|
features = ["full", "extra-traits"]
|
27
rider-derive/src/lib.rs
Normal file
27
rider-derive/src/lib.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use proc_macro;
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn build_test_renderer(input: TokenStream) -> TokenStream {
|
||||||
|
let renderer_name = format_ident!("{}", input.to_string());
|
||||||
|
|
||||||
|
let exp = quote! {
|
||||||
|
let mut character_sizes = std::collections::HashMap::new();
|
||||||
|
let mut canvas = CanvasMock::new();
|
||||||
|
let config = build_config();
|
||||||
|
let mut surface =
|
||||||
|
sdl2::surface::Surface::new(512, 512, sdl2::pixels::PixelFormatEnum::RGB24).unwrap();
|
||||||
|
let mut surface_canvas = sdl2::render::Canvas::from_surface(surface).unwrap();
|
||||||
|
let mut texture_creator = surface_canvas.texture_creator();
|
||||||
|
let mut texture_manager = crate::renderer::managers::TextureManager::new(&texture_creator);
|
||||||
|
let mut ttf_context = sdl2::ttf::Sdl2TtfContext {};
|
||||||
|
let mut #renderer_name = SimpleRendererMock {
|
||||||
|
config: config.clone(),
|
||||||
|
ttf: ttf_context,
|
||||||
|
character_sizes,
|
||||||
|
texture_manager,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
exp.into()
|
||||||
|
}
|
@ -8,6 +8,8 @@ edition = "2018"
|
|||||||
rider-config = { path = "../rider-config", version = "0.1.0" }
|
rider-config = { path = "../rider-config", version = "0.1.0" }
|
||||||
rider-lexers = { path = "../rider-lexers", version = "0.1.0" }
|
rider-lexers = { path = "../rider-lexers", version = "0.1.0" }
|
||||||
rider-themes = { path = "../rider-themes", version = "0.1.0" }
|
rider-themes = { path = "../rider-themes", version = "0.1.0" }
|
||||||
|
rider-derive = { path = "../rider-derive", version = "0.1.0" }
|
||||||
|
rider-match-widget = { path = "../rider-match-widget", version = "0.1.0" }
|
||||||
rand = "0.5"
|
rand = "0.5"
|
||||||
dirs = "*"
|
dirs = "*"
|
||||||
serde = "*"
|
serde = "*"
|
||||||
|
@ -21,13 +21,13 @@ pub struct AppState {
|
|||||||
impl AppState {
|
impl AppState {
|
||||||
pub fn new(config: Arc<RwLock<Config>>) -> Self {
|
pub fn new(config: Arc<RwLock<Config>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
menu_bar: MenuBar::new(Arc::clone(&config)),
|
menu_bar: MenuBar::new(config.clone()),
|
||||||
project_tree: ProjectTreeSidebar::new(
|
project_tree: ProjectTreeSidebar::new(
|
||||||
Application::current_working_directory(),
|
Application::current_working_directory(),
|
||||||
config.clone(),
|
config.clone(),
|
||||||
),
|
),
|
||||||
files: vec![],
|
files: vec![],
|
||||||
file_editor: FileEditor::new(Arc::clone(&config)),
|
file_editor: FileEditor::new(config.clone()),
|
||||||
modal: None,
|
modal: None,
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ impl AppState {
|
|||||||
|
|
||||||
pub fn open_settings<R>(&mut self, renderer: &mut R) -> Result<(), String>
|
pub fn open_settings<R>(&mut self, renderer: &mut R) -> Result<(), String>
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
match self.modal {
|
match self.modal {
|
||||||
None => {
|
None => {
|
||||||
@ -87,7 +87,7 @@ impl AppState {
|
|||||||
|
|
||||||
pub fn open_directory<R>(&mut self, dir_path: String, renderer: &mut R)
|
pub fn open_directory<R>(&mut self, dir_path: String, renderer: &mut R)
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
match self.modal.as_mut() {
|
match self.modal.as_mut() {
|
||||||
Some(ModalType::OpenFile(modal)) => modal.open_directory(dir_path, renderer),
|
Some(ModalType::OpenFile(modal)) => modal.open_directory(dir_path, renderer),
|
||||||
@ -145,14 +145,16 @@ impl AppState {
|
|||||||
R: Renderer + ConfigHolder + CharacterSizeManager,
|
R: Renderer + ConfigHolder + CharacterSizeManager,
|
||||||
{
|
{
|
||||||
// file editor
|
// file editor
|
||||||
self.file_editor.render(canvas, renderer);
|
self.file_editor
|
||||||
|
.render(canvas, renderer, &RenderContext::Nothing);
|
||||||
|
|
||||||
// menu bar
|
// menu bar
|
||||||
self.menu_bar
|
self.menu_bar
|
||||||
.render(canvas, renderer, &RenderContext::Nothing);
|
.render(canvas, renderer, &RenderContext::Nothing);
|
||||||
|
|
||||||
// project tree
|
// project tree
|
||||||
self.project_tree.render(canvas, renderer);
|
self.project_tree
|
||||||
|
.render(canvas, renderer, &RenderContext::Nothing);
|
||||||
|
|
||||||
// settings modal
|
// settings modal
|
||||||
match self.modal.as_ref() {
|
match self.modal.as_ref() {
|
||||||
@ -168,7 +170,7 @@ impl AppState {
|
|||||||
|
|
||||||
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
self.menu_bar.prepare_ui();
|
self.menu_bar.prepare_ui();
|
||||||
self.project_tree.prepare_ui(renderer);
|
self.project_tree.prepare_ui(renderer);
|
||||||
@ -189,7 +191,7 @@ impl AppState {
|
|||||||
self.menu_bar.update(ticks, context);
|
self.menu_bar.update(ticks, context);
|
||||||
|
|
||||||
// sidebar
|
// sidebar
|
||||||
self.project_tree.update(ticks);
|
self.project_tree.update(ticks, context);
|
||||||
|
|
||||||
// file editor
|
// file editor
|
||||||
let context = UpdateContext::ParentPosition(
|
let context = UpdateContext::ParentPosition(
|
||||||
@ -253,21 +255,21 @@ impl ConfigHolder for AppState {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use std::sync::Arc;
|
use rider_derive::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_none_for_default_file() {
|
fn must_return_none_for_default_file() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let state = AppState::new(Arc::clone(&config));
|
let state = AppState::new(config.clone());
|
||||||
let file = state.file_editor().file();
|
let file = state.file_editor().file();
|
||||||
assert_eq!(file.is_none(), true);
|
assert_eq!(file.is_none(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_scroll_file_when_no_modal() {
|
fn must_scroll_file_when_no_modal() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut state = AppState::new(Arc::clone(&config));
|
let mut state = AppState::new(config.clone());
|
||||||
let old_scroll = state.file_editor().scroll();
|
let old_scroll = state.file_editor().scroll();
|
||||||
state.set_open_file_modal(None);
|
state.set_open_file_modal(None);
|
||||||
state.scroll_by(10, 10);
|
state.scroll_by(10, 10);
|
||||||
@ -276,9 +278,9 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_scroll_modal_when_modal_was_set() {
|
fn must_scroll_modal_when_modal_was_set() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut state = AppState::new(Arc::clone(&config));
|
let mut state = AppState::new(config.clone());
|
||||||
let modal = OpenFile::new("/".to_owned(), 100, 100, Arc::clone(&config));
|
let modal = OpenFile::new("/".to_owned(), 100, 100, config.clone());
|
||||||
let file_scroll = state.file_editor().scroll();
|
let file_scroll = state.file_editor().scroll();
|
||||||
let old_scroll = state.file_editor().scroll();
|
let old_scroll = state.file_editor().scroll();
|
||||||
state.set_open_file_modal(Some(modal));
|
state.set_open_file_modal(Some(modal));
|
||||||
@ -295,8 +297,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_fail_save_file_when_none_is_open() {
|
fn must_fail_save_file_when_none_is_open() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let state = AppState::new(Arc::clone(&config));
|
let state = AppState::new(config.clone());
|
||||||
let result = state.save_file();
|
let result = state.save_file();
|
||||||
assert_eq!(result, Err(format!("No buffer found")));
|
assert_eq!(result, Err(format!("No buffer found")));
|
||||||
}
|
}
|
||||||
@ -313,9 +315,8 @@ mod tests {
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = support::SimpleRendererMock::new(config.clone());
|
let mut state = AppState::new(config.clone());
|
||||||
let mut state = AppState::new(Arc::clone(&config));
|
|
||||||
let result = state.open_file(
|
let result = state.open_file(
|
||||||
format!("/tmp/must_succeed_save_file_when_file_is_open.md"),
|
format!("/tmp/must_succeed_save_file_when_file_is_open.md"),
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
@ -337,9 +338,8 @@ mod tests {
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = support::SimpleRendererMock::new(config.clone());
|
let mut state = AppState::new(config.clone());
|
||||||
let mut state = AppState::new(Arc::clone(&config));
|
|
||||||
let result = state.open_file(
|
let result = state.open_file(
|
||||||
format!("/tmp/must_succeed_save_file_when_file_does_not_exists.md"),
|
format!("/tmp/must_succeed_save_file_when_file_does_not_exists.md"),
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
@ -351,34 +351,32 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_close_modal_when_no_modal_is_open() {
|
fn must_close_modal_when_no_modal_is_open() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut state = AppState::new(Arc::clone(&config));
|
let mut state = AppState::new(config.clone());
|
||||||
assert_eq!(state.close_modal(), Ok(()));
|
assert_eq!(state.close_modal(), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_close_modal_when_some_modal_is_open() {
|
fn must_close_modal_when_some_modal_is_open() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut state = AppState::new(Arc::clone(&config));
|
let mut state = AppState::new(config.clone());
|
||||||
let modal = OpenFile::new("/".to_owned(), 100, 100, Arc::clone(&config));
|
let modal = OpenFile::new("/".to_owned(), 100, 100, config.clone());
|
||||||
state.set_open_file_modal(Some(modal));
|
state.set_open_file_modal(Some(modal));
|
||||||
assert_eq!(state.close_modal(), Ok(()));
|
assert_eq!(state.close_modal(), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_settings_when_there_is_no_other_modal() {
|
fn open_settings_when_there_is_no_other_modal() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = support::SimpleRendererMock::new(config.clone());
|
let mut state = AppState::new(config.clone());
|
||||||
let mut state = AppState::new(Arc::clone(&config));
|
|
||||||
assert_eq!(state.open_settings(&mut renderer), Ok(()));
|
assert_eq!(state.open_settings(&mut renderer), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_settings_when_other_modal_is_open() {
|
fn open_settings_when_other_modal_is_open() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = support::SimpleRendererMock::new(config.clone());
|
let mut state = AppState::new(config.clone());
|
||||||
let mut state = AppState::new(Arc::clone(&config));
|
let modal = OpenFile::new("/".to_owned(), 100, 100, config.clone());
|
||||||
let modal = OpenFile::new("/".to_owned(), 100, 100, Arc::clone(&config));
|
|
||||||
state.set_open_file_modal(Some(modal));
|
state.set_open_file_modal(Some(modal));
|
||||||
assert_eq!(state.open_settings(&mut renderer), Ok(()));
|
assert_eq!(state.open_settings(&mut renderer), Ok(()));
|
||||||
}
|
}
|
||||||
@ -390,9 +388,8 @@ mod tests {
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = support::SimpleRendererMock::new(config.clone());
|
let mut state = AppState::new(config.clone());
|
||||||
let mut state = AppState::new(Arc::clone(&config));
|
|
||||||
state.open_directory("/must_open_directory".to_owned(), &mut renderer);
|
state.open_directory("/must_open_directory".to_owned(), &mut renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
|
|
||||||
pub fn move_caret_right(file_editor: &mut FileEditor) -> Option<TextCharacter> {
|
pub fn move_caret_right<C>(file_editor: &mut C) -> Option<TextCharacter>
|
||||||
|
where
|
||||||
|
C: CaretAccess + FileAccess + ?Sized,
|
||||||
|
{
|
||||||
let text_character: TextCharacter = file_editor
|
let text_character: TextCharacter = file_editor
|
||||||
.file()
|
.file()
|
||||||
.map(|file| file.get_character_at(file_editor.caret().text_position() + 1))??;
|
.map(|file| file.get_character_at(file_editor.caret().text_position() + 1))??;
|
||||||
@ -12,7 +15,10 @@ pub fn move_caret_right(file_editor: &mut FileEditor) -> Option<TextCharacter> {
|
|||||||
Some(text_character)
|
Some(text_character)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_caret_left(file_editor: &mut FileEditor) -> Option<TextCharacter> {
|
pub fn move_caret_left<C>(file_editor: &mut C) -> Option<TextCharacter>
|
||||||
|
where
|
||||||
|
C: CaretAccess + FileAccess + ?Sized,
|
||||||
|
{
|
||||||
if file_editor.caret().text_position() == 0 {
|
if file_editor.caret().text_position() == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -28,7 +34,10 @@ pub fn move_caret_left(file_editor: &mut FileEditor) -> Option<TextCharacter> {
|
|||||||
Some(text_character)
|
Some(text_character)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_caret_down(file_editor: &mut FileEditor) -> Option<TextCharacter> {
|
pub fn move_caret_down<C>(file_editor: &mut C) -> Option<TextCharacter>
|
||||||
|
where
|
||||||
|
C: CaretAccess + FileAccess + ?Sized,
|
||||||
|
{
|
||||||
if file_editor.caret().text_position() == 0 {
|
if file_editor.caret().text_position() == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -68,7 +77,10 @@ pub fn move_caret_down(file_editor: &mut FileEditor) -> Option<TextCharacter> {
|
|||||||
Some(text_character.clone())
|
Some(text_character.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_caret_up(file_editor: &mut FileEditor) -> Option<TextCharacter> {
|
pub fn move_caret_up<C>(file_editor: &mut C) -> Option<TextCharacter>
|
||||||
|
where
|
||||||
|
C: CaretAccess + FileAccess + ?Sized,
|
||||||
|
{
|
||||||
if file_editor.caret().text_position() == 0 {
|
if file_editor.caret().text_position() == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -121,12 +133,12 @@ pub fn move_caret_up(file_editor: &mut FileEditor) -> Option<TextCharacter> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_move_right {
|
mod test_move_right {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use crate::tests::support::SimpleRendererMock;
|
use rider_derive::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_with_no_file() {
|
fn assert_move_with_no_file() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut editor = FileEditor::new(config);
|
let mut editor = FileEditor::new(config);
|
||||||
|
|
||||||
assert_eq!(move_caret_right(&mut editor).is_some(), false);
|
assert_eq!(move_caret_right(&mut editor).is_some(), false);
|
||||||
@ -134,8 +146,7 @@ mod test_move_right {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret_with_empty_file() {
|
fn assert_move_caret_with_empty_file() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut editor = FileEditor::new(config.clone());
|
let mut editor = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("test.txt".to_owned(), "".to_owned(), config);
|
let mut file = EditorFile::new("test.txt".to_owned(), "".to_owned(), config);
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
@ -147,8 +158,7 @@ mod test_move_right {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret_with_filled_file() {
|
fn assert_move_caret_with_filled_file() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut editor = FileEditor::new(config.clone());
|
let mut editor = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("test.txt".to_owned(), "hello".to_owned(), config);
|
let mut file = EditorFile::new("test.txt".to_owned(), "hello".to_owned(), config);
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
@ -162,12 +172,12 @@ mod test_move_right {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_move_left {
|
mod test_move_left {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use crate::tests::support::SimpleRendererMock;
|
use rider_derive::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret_without_file() {
|
fn assert_move_caret_without_file() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut editor = FileEditor::new(config);
|
let mut editor = FileEditor::new(config);
|
||||||
|
|
||||||
assert_eq!(move_caret_left(&mut editor).is_some(), false);
|
assert_eq!(move_caret_left(&mut editor).is_some(), false);
|
||||||
@ -175,8 +185,7 @@ mod test_move_left {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret_with_empty_file() {
|
fn assert_move_caret_with_empty_file() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut editor = FileEditor::new(config.clone());
|
let mut editor = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("test.txt".to_owned(), "".to_owned(), config);
|
let mut file = EditorFile::new("test.txt".to_owned(), "".to_owned(), config);
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
@ -188,8 +197,7 @@ mod test_move_left {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret_with_filled_file() {
|
fn assert_move_caret_with_filled_file() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut editor = FileEditor::new(config.clone());
|
let mut editor = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("test.txt".to_owned(), "hello".to_owned(), config);
|
let mut file = EditorFile::new("test.txt".to_owned(), "hello".to_owned(), config);
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
@ -209,13 +217,12 @@ mod test_move_left {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_move_up {
|
mod test_move_up {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use crate::tests::support::SimpleRendererMock;
|
use rider_derive::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret_with_top_of_filled_file() {
|
fn assert_move_caret_with_top_of_filled_file() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut editor = FileEditor::new(config.clone());
|
let mut editor = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("test.txt".to_owned(), "he\nll\no".to_owned(), config);
|
let mut file = EditorFile::new("test.txt".to_owned(), "he\nll\no".to_owned(), config);
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
@ -227,8 +234,7 @@ mod test_move_up {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret_with_filled_file() {
|
fn assert_move_caret_with_filled_file() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut editor = FileEditor::new(config.clone());
|
let mut editor = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("test.txt".to_owned(), "he\nll\no".to_owned(), config);
|
let mut file = EditorFile::new("test.txt".to_owned(), "he\nll\no".to_owned(), config);
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
@ -249,13 +255,12 @@ mod test_move_up {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_move_down {
|
mod test_move_down {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use crate::tests::support::SimpleRendererMock;
|
use rider_derive::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret_with_bottom_of_filled_file() {
|
fn assert_move_caret_with_bottom_of_filled_file() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut editor = FileEditor::new(config.clone());
|
let mut editor = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("test.txt".to_owned(), "he\nll\no".to_owned(), config);
|
let mut file = EditorFile::new("test.txt".to_owned(), "he\nll\no".to_owned(), config);
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
@ -270,8 +275,9 @@ mod test_move_down {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret_with_filled_file() {
|
fn assert_move_caret_with_filled_file() {
|
||||||
let config = support::build_config();
|
use crate::tests::*;
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
|
build_test_renderer!(renderer);
|
||||||
let mut editor = FileEditor::new(config.clone());
|
let mut editor = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("test.txt".to_owned(), "he\nll\nod".to_owned(), config);
|
let mut file = EditorFile::new("test.txt".to_owned(), "he\nll\nod".to_owned(), config);
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
|
@ -34,7 +34,7 @@ where
|
|||||||
let move_to = file_editor
|
let move_to = file_editor
|
||||||
.file()
|
.file()
|
||||||
.and_then(|f| f.get_character_at(position.text_position()))
|
.and_then(|f| f.get_character_at(position.text_position()))
|
||||||
.map(|character| character.dest())
|
.map(|character| character.dest().clone())
|
||||||
.map(|dest| (position, Point::new(dest.x(), dest.y())));
|
.map(|dest| (position, Point::new(dest.x(), dest.y())));
|
||||||
match move_to {
|
match move_to {
|
||||||
Some((position, point)) => file_editor.caret_mut().move_caret(position, point),
|
Some((position, point)) => file_editor.caret_mut().move_caret(position, point),
|
||||||
@ -171,7 +171,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::renderer::managers::FontDetails;
|
use crate::renderer::managers::FontDetails;
|
||||||
use crate::renderer::managers::TextDetails;
|
use crate::renderer::managers::TextDetails;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use sdl2::rect::Rect;
|
use sdl2::rect::Rect;
|
||||||
use sdl2::render::Texture;
|
use sdl2::render::Texture;
|
||||||
use sdl2::ttf::Font;
|
use sdl2::ttf::Font;
|
||||||
@ -226,7 +226,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_empty_string_when_no_file() {
|
fn must_return_empty_string_when_no_file() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut editor = FileEditor::new(config);
|
let mut editor = FileEditor::new(config);
|
||||||
let result = current_file_path(&mut editor);
|
let result = current_file_path(&mut editor);
|
||||||
assert_eq!(result, String::new());
|
assert_eq!(result, String::new());
|
||||||
@ -234,7 +234,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_path_string_when_file_was_set() {
|
fn must_return_path_string_when_file_was_set() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut editor = FileEditor::new(Arc::clone(&config));
|
let mut editor = FileEditor::new(Arc::clone(&config));
|
||||||
let file = EditorFile::new(
|
let file = EditorFile::new(
|
||||||
"/foo/bar".to_owned(),
|
"/foo/bar".to_owned(),
|
||||||
@ -252,7 +252,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_insert_text_without_file() {
|
fn assert_insert_text_without_file() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut widget = FileEditor::new(config.clone());
|
let mut widget = FileEditor::new(config.clone());
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -263,7 +263,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_insert_text_to_empty_file() {
|
fn assert_insert_text_to_empty_file() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut widget = FileEditor::new(config.clone());
|
let mut widget = FileEditor::new(config.clone());
|
||||||
let file = EditorFile::new("".to_owned(), "".to_owned(), config.clone());
|
let file = EditorFile::new("".to_owned(), "".to_owned(), config.clone());
|
||||||
@ -276,7 +276,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_insert_text_to_file_without_new_line() {
|
fn assert_insert_text_to_file_without_new_line() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut widget = FileEditor::new(config.clone());
|
let mut widget = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("".to_owned(), "bar".to_owned(), config.clone());
|
let mut file = EditorFile::new("".to_owned(), "bar".to_owned(), config.clone());
|
||||||
@ -294,7 +294,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_insert_text_to_file_with_new_line() {
|
fn assert_insert_text_to_file_with_new_line() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut widget = FileEditor::new(config.clone());
|
let mut widget = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("".to_owned(), "bar\n".to_owned(), config.clone());
|
let mut file = EditorFile::new("".to_owned(), "bar\n".to_owned(), config.clone());
|
||||||
@ -312,7 +312,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_insert_text_to_file_with_new_line_with_caret_at_new_line() {
|
fn assert_insert_text_to_file_with_new_line_with_caret_at_new_line() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut widget = FileEditor::new(config.clone());
|
let mut widget = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("".to_owned(), "old content\n".to_owned(), config.clone());
|
let mut file = EditorFile::new("".to_owned(), "old content\n".to_owned(), config.clone());
|
||||||
@ -335,7 +335,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_insert_new_line_without_file() {
|
fn assert_insert_new_line_without_file() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut widget = FileEditor::new(config.clone());
|
let mut widget = FileEditor::new(config.clone());
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -344,12 +344,12 @@ mod tests {
|
|||||||
let expected = CaretPosition::new(0, 0, 0);
|
let expected = CaretPosition::new(0, 0, 0);
|
||||||
assert_eq!(widget.caret().position(), &expected);
|
assert_eq!(widget.caret().position(), &expected);
|
||||||
let expected = Rect::new(0, 0, 6, 15);
|
let expected = Rect::new(0, 0, 6, 15);
|
||||||
assert_eq!(widget.caret().dest(), expected);
|
assert_eq!(widget.caret().dest(), &expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_insert_new_line_to_empty_file() {
|
fn assert_insert_new_line_to_empty_file() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut widget = FileEditor::new(config.clone());
|
let mut widget = FileEditor::new(config.clone());
|
||||||
let file = EditorFile::new("".to_owned(), "".to_owned(), config.clone());
|
let file = EditorFile::new("".to_owned(), "".to_owned(), config.clone());
|
||||||
@ -360,12 +360,12 @@ mod tests {
|
|||||||
let expected = CaretPosition::new(1, 1, 0);
|
let expected = CaretPosition::new(1, 1, 0);
|
||||||
assert_eq!(widget.caret().position(), &expected);
|
assert_eq!(widget.caret().position(), &expected);
|
||||||
let expected = Rect::new(0, 13, 6, 15);
|
let expected = Rect::new(0, 13, 6, 15);
|
||||||
assert_eq!(widget.caret().dest(), expected);
|
assert_eq!(widget.caret().dest(), &expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_insert_new_line_to_file_at_beginning() {
|
fn assert_insert_new_line_to_file_at_beginning() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut widget = FileEditor::new(config.clone());
|
let mut widget = FileEditor::new(config.clone());
|
||||||
let file = EditorFile::new("".to_owned(), "foo".to_owned(), config.clone());
|
let file = EditorFile::new("".to_owned(), "foo".to_owned(), config.clone());
|
||||||
@ -376,14 +376,14 @@ mod tests {
|
|||||||
let expected = CaretPosition::new(1, 1, 0);
|
let expected = CaretPosition::new(1, 1, 0);
|
||||||
assert_eq!(widget.caret().position(), &expected);
|
assert_eq!(widget.caret().position(), &expected);
|
||||||
let expected = Rect::new(0, 13, 6, 15);
|
let expected = Rect::new(0, 13, 6, 15);
|
||||||
assert_eq!(widget.caret().dest(), expected);
|
assert_eq!(widget.caret().dest(), &expected);
|
||||||
assert_eq!(widget.file().is_some(), true);
|
assert_eq!(widget.file().is_some(), true);
|
||||||
assert_eq!(widget.file().unwrap().buffer(), "\nfoo".to_owned());
|
assert_eq!(widget.file().unwrap().buffer(), "\nfoo".to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_insert_new_line_to_file_in_middle() {
|
fn assert_insert_new_line_to_file_in_middle() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut widget = FileEditor::new(config.clone());
|
let mut widget = FileEditor::new(config.clone());
|
||||||
let mut file = EditorFile::new("hello.txt".to_owned(), "abcd".to_owned(), config.clone());
|
let mut file = EditorFile::new("hello.txt".to_owned(), "abcd".to_owned(), config.clone());
|
||||||
@ -397,7 +397,7 @@ mod tests {
|
|||||||
let expected = CaretPosition::new(3, 1, 0);
|
let expected = CaretPosition::new(3, 1, 0);
|
||||||
assert_eq!(widget.caret().position(), &expected);
|
assert_eq!(widget.caret().position(), &expected);
|
||||||
let expected = Rect::new(0, 13, 6, 15);
|
let expected = Rect::new(0, 13, 6, 15);
|
||||||
assert_eq!(widget.caret().dest(), expected);
|
assert_eq!(widget.caret().dest(), &expected);
|
||||||
assert_eq!(widget.file().is_some(), true);
|
assert_eq!(widget.file().is_some(), true);
|
||||||
assert_eq!(widget.file().unwrap().buffer(), "ab\ncd".to_owned());
|
assert_eq!(widget.file().unwrap().buffer(), "ab\ncd".to_owned());
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
#![feature(clamp)]
|
#![feature(
|
||||||
|
clamp,
|
||||||
|
associated_type_bounds,
|
||||||
|
crate_visibility_modifier,
|
||||||
|
proc_macro_hygiene
|
||||||
|
)]
|
||||||
|
|
||||||
extern crate dirs;
|
extern crate dirs;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
extern crate lazy_static;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate rider_config;
|
extern crate rider_config;
|
||||||
|
extern crate rider_derive;
|
||||||
extern crate rider_lexers;
|
extern crate rider_lexers;
|
||||||
extern crate rider_themes;
|
extern crate rider_themes;
|
||||||
extern crate sdl2;
|
extern crate sdl2;
|
||||||
@ -20,14 +27,12 @@ use std::fs::File;
|
|||||||
|
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
#[cfg(test)]
|
#[macro_use]
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
fn init_logger(directories: &Directories) {
|
fn init_logger(directories: &Directories) {
|
||||||
// use simplelog::SharedLogger;
|
|
||||||
|
|
||||||
let mut log_file_path = directories.log_dir.clone();
|
let mut log_file_path = directories.log_dir.clone();
|
||||||
log_file_path.push("rider.log");
|
log_file_path.push("rider.log");
|
||||||
|
|
||||||
|
@ -41,7 +41,13 @@ pub struct FontDetails {
|
|||||||
|
|
||||||
impl From<&EditorConfig> for FontDetails {
|
impl From<&EditorConfig> for FontDetails {
|
||||||
fn from(config: &EditorConfig) -> Self {
|
fn from(config: &EditorConfig) -> Self {
|
||||||
FontDetails::new(config.font_path().as_str(), config.character_size().clone())
|
FontDetails::new(config.font_path(), config.character_size().clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(&str, u16)> for FontDetails {
|
||||||
|
fn from((path, size): (&str, u16)) -> Self {
|
||||||
|
FontDetails::new(path, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,18 +103,10 @@ impl<'a> From<&'a FontDetails> for FontDetails {
|
|||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
//noinspection RsWrongLifetimeParametersNumber
|
//noinspection RsWrongLifetimeParametersNumber
|
||||||
pub type TextureManager<'l> =
|
pub type TextureManager<'l, T> = ResourceManager<'l, String, Texture<'l>, TextureCreator<T>>;
|
||||||
ResourceManager<'l, String, Texture<'l>, TextureCreator<sdl2::video::WindowContext>>;
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
pub type FontManager<'l> = ResourceManager<'l, FontDetails, Font<'l, 'static>, Sdl2TtfContext>;
|
pub type FontManager<'l> = ResourceManager<'l, FontDetails, Font<'l, 'static>, Sdl2TtfContext>;
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
pub trait ManagersHolder<'l> {
|
|
||||||
fn font_manager(&mut self) -> &mut FontManager<'l>;
|
|
||||||
|
|
||||||
fn texture_manager(&mut self) -> &mut TextureManager<'l>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ResourceManager<'l, K, R, L>
|
pub struct ResourceManager<'l, K, R, L>
|
||||||
@ -160,7 +158,7 @@ impl<'l, T> ResourceLoader<'l, Texture<'l>> for TextureCreator<T> {
|
|||||||
type Args = str;
|
type Args = str;
|
||||||
|
|
||||||
fn load(&'l self, path: &str) -> Result<Texture, String> {
|
fn load(&'l self, path: &str) -> Result<Texture, String> {
|
||||||
println!("Loading {}...", path);
|
debug!("Loading {}...", path);
|
||||||
self.load_texture(path)
|
self.load_texture(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +168,7 @@ impl<'l> ResourceLoader<'l, Font<'l, 'static>> for Sdl2TtfContext {
|
|||||||
type Args = FontDetails;
|
type Args = FontDetails;
|
||||||
|
|
||||||
fn load(&'l self, data: &FontDetails) -> Result<Font<'l, 'static>, String> {
|
fn load(&'l self, data: &FontDetails) -> Result<Font<'l, 'static>, String> {
|
||||||
info!("Loading font {}...", data.path);
|
debug!("Loading font {}...", data.path);
|
||||||
self.load_font(&data.path, data.size)
|
self.load_font(&data.path, data.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,7 +184,7 @@ pub trait TextTextureManager<'l> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl<'l> TextTextureManager<'l> for TextureManager<'l> {
|
impl<'l, T> TextTextureManager<'l> for TextureManager<'l, T> {
|
||||||
//noinspection RsWrongLifetimeParametersNumber
|
//noinspection RsWrongLifetimeParametersNumber
|
||||||
fn load_text(
|
fn load_text(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -203,9 +201,6 @@ impl<'l> TextTextureManager<'l> for TextureManager<'l> {
|
|||||||
let texture = self.loader.create_texture_from_surface(&surface).unwrap();
|
let texture = self.loader.create_texture_from_surface(&surface).unwrap();
|
||||||
let resource = Rc::new(texture);
|
let resource = Rc::new(texture);
|
||||||
self.cache.insert(key, resource.clone());
|
self.cache.insert(key, resource.clone());
|
||||||
// for c in details.text.chars() {
|
|
||||||
// info!("texture for '{:?}' created", c);
|
|
||||||
// }
|
|
||||||
Ok(resource)
|
Ok(resource)
|
||||||
},
|
},
|
||||||
Ok,
|
Ok,
|
||||||
|
@ -26,7 +26,7 @@ pub trait Renderer {
|
|||||||
pub struct CanvasRenderer<'l> {
|
pub struct CanvasRenderer<'l> {
|
||||||
config: ConfigAccess,
|
config: ConfigAccess,
|
||||||
font_manager: FontManager<'l>,
|
font_manager: FontManager<'l>,
|
||||||
texture_manager: TextureManager<'l>,
|
texture_manager: TextureManager<'l, sdl2::video::WindowContext>,
|
||||||
character_sizes: HashMap<TextCharacterDetails, Rect>,
|
character_sizes: HashMap<TextCharacterDetails, Rect>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,13 +58,13 @@ impl<'l> CharacterSizeManager for CanvasRenderer<'l> {
|
|||||||
let (font_path, font_size) = {
|
let (font_path, font_size) = {
|
||||||
let config = self.config().read().unwrap();
|
let config = self.config().read().unwrap();
|
||||||
(
|
(
|
||||||
config.editor_config().font_path().clone(),
|
config.editor_config().font_path().to_string(),
|
||||||
config.editor_config().character_size().clone(),
|
config.editor_config().character_size().clone(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let details = TextCharacterDetails {
|
let details = TextCharacterDetails {
|
||||||
c: c.clone(),
|
c: c.clone(),
|
||||||
font_path,
|
font_path: font_path.to_string(),
|
||||||
font_size,
|
font_size,
|
||||||
};
|
};
|
||||||
self.character_sizes
|
self.character_sizes
|
||||||
@ -80,17 +80,6 @@ impl<'l> CharacterSizeManager for CanvasRenderer<'l> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl<'l> ManagersHolder<'l> for CanvasRenderer<'l> {
|
|
||||||
fn font_manager(&mut self) -> &mut FontManager<'l> {
|
|
||||||
&mut self.font_manager
|
|
||||||
}
|
|
||||||
|
|
||||||
fn texture_manager(&mut self) -> &mut TextureManager<'l> {
|
|
||||||
&mut self.texture_manager
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl<'l> ConfigHolder for CanvasRenderer<'l> {
|
impl<'l> ConfigHolder for CanvasRenderer<'l> {
|
||||||
fn config(&self) -> &ConfigAccess {
|
fn config(&self) -> &ConfigAccess {
|
||||||
@ -101,7 +90,7 @@ impl<'l> ConfigHolder for CanvasRenderer<'l> {
|
|||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl<'l> Renderer for CanvasRenderer<'l> {
|
impl<'l> Renderer for CanvasRenderer<'l> {
|
||||||
fn load_font(&mut self, details: FontDetails) -> Rc<Font> {
|
fn load_font(&mut self, details: FontDetails) -> Rc<Font> {
|
||||||
self.font_manager()
|
self.font_manager
|
||||||
.load(&details)
|
.load(&details)
|
||||||
.unwrap_or_else(|_| panic!("Font not found {:?}", details))
|
.unwrap_or_else(|_| panic!("Font not found {:?}", details))
|
||||||
}
|
}
|
||||||
@ -113,11 +102,10 @@ impl<'l> Renderer for CanvasRenderer<'l> {
|
|||||||
) -> Result<Rc<Texture>, String> {
|
) -> Result<Rc<Texture>, String> {
|
||||||
use crate::renderer::managers::*;
|
use crate::renderer::managers::*;
|
||||||
let font = self
|
let font = self
|
||||||
.font_manager()
|
.font_manager
|
||||||
.load(&font_details)
|
.load(&font_details)
|
||||||
.unwrap_or_else(|_| panic!("Font not found {:?}", details));
|
.unwrap_or_else(|_| panic!("Font not found {:?}", details));
|
||||||
let tex_manager = self.texture_manager();
|
self.texture_manager.load_text(details, font)
|
||||||
tex_manager.load_text(details, font)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_image(&mut self, path: String) -> Result<Rc<Texture>, String> {
|
fn load_image(&mut self, path: String) -> Result<Rc<Texture>, String> {
|
||||||
|
@ -1,280 +0,0 @@
|
|||||||
#[cfg(test)]
|
|
||||||
pub mod support {
|
|
||||||
use crate::renderer::managers::FontDetails;
|
|
||||||
use crate::renderer::managers::TextDetails;
|
|
||||||
use crate::renderer::renderer::Renderer;
|
|
||||||
use crate::ui::text_character::CharacterSizeManager;
|
|
||||||
use crate::ui::CanvasAccess;
|
|
||||||
use rider_config::Config;
|
|
||||||
use rider_config::ConfigAccess;
|
|
||||||
use rider_config::ConfigHolder;
|
|
||||||
use sdl2::pixels::Color;
|
|
||||||
use sdl2::rect::Point;
|
|
||||||
use sdl2::rect::Rect;
|
|
||||||
use sdl2::render::Texture;
|
|
||||||
use sdl2::ttf::Font;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::fmt::Error;
|
|
||||||
use std::fmt::Formatter;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::*;
|
|
||||||
|
|
||||||
pub fn build_path(path: String) {
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
fs::create_dir_all(path.as_str()).unwrap();
|
|
||||||
fs::write((path.clone() + &"/file1".to_owned()).as_str(), "foo").unwrap();
|
|
||||||
fs::write((path.clone() + &"/file2".to_owned()).as_str(), "bar").unwrap();
|
|
||||||
fs::create_dir_all((path.clone() + &"/dir1".to_owned()).as_str()).unwrap();
|
|
||||||
fs::create_dir_all((path.clone() + &"/dir2".to_owned()).as_str()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_config() -> Arc<RwLock<Config>> {
|
|
||||||
let mut config = Config::new();
|
|
||||||
config.set_theme(config.editor_config().current_theme().clone());
|
|
||||||
Arc::new(RwLock::new(config))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum CanvasShape {
|
|
||||||
Line,
|
|
||||||
Border,
|
|
||||||
Rectangle,
|
|
||||||
Image(Rect, Rect, String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct RendererRect {
|
|
||||||
pub rect: Rect,
|
|
||||||
pub color: Color,
|
|
||||||
pub shape: CanvasShape,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl RendererRect {
|
|
||||||
pub fn new(rect: Rect, color: Color, shape: CanvasShape) -> Self {
|
|
||||||
Self { rect, color, shape }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
pub struct CanvasMock {
|
|
||||||
pub rects: Vec<RendererRect>,
|
|
||||||
pub borders: Vec<RendererRect>,
|
|
||||||
pub lines: Vec<RendererRect>,
|
|
||||||
pub clippings: Vec<Option<Rect>>,
|
|
||||||
pub character_sizes: HashMap<char, sdl2::rect::Rect>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl Debug for CanvasMock {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"CanvasMock {{ {:?} {:?} {:?} }}",
|
|
||||||
self.rects, self.lines, self.clippings
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl PartialEq for CanvasMock {
|
|
||||||
fn eq(&self, other: &CanvasMock) -> bool {
|
|
||||||
self.rects == other.rects
|
|
||||||
&& self.borders == other.borders
|
|
||||||
&& self.clippings == other.clippings
|
|
||||||
&& self.lines == other.lines
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl CanvasMock {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
rects: vec![],
|
|
||||||
borders: vec![],
|
|
||||||
lines: vec![],
|
|
||||||
clippings: vec![],
|
|
||||||
character_sizes: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl CanvasAccess for CanvasMock {
|
|
||||||
fn render_rect(&mut self, rect: Rect, color: Color) -> Result<(), String> {
|
|
||||||
self.rects.push(RendererRect {
|
|
||||||
rect,
|
|
||||||
color,
|
|
||||||
shape: CanvasShape::Rectangle,
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_border(&mut self, rect: Rect, color: Color) -> Result<(), String> {
|
|
||||||
self.borders.push(RendererRect {
|
|
||||||
rect,
|
|
||||||
color,
|
|
||||||
shape: CanvasShape::Border,
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_image(&mut self, _tex: Rc<Texture>, src: Rect, dest: Rect) -> Result<(), String> {
|
|
||||||
self.rects.push(RendererRect::new(
|
|
||||||
dest.clone(),
|
|
||||||
Color::RGBA(0, 0, 0, 255),
|
|
||||||
CanvasShape::Image(src.clone(), dest.clone(), format!("_tex: Rc<Texture>")),
|
|
||||||
));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_line(&mut self, start: Point, end: Point, color: Color) -> Result<(), String> {
|
|
||||||
self.lines.push(RendererRect {
|
|
||||||
rect: Rect::new(start.x(), start.y(), end.x() as u32, end.y() as u32),
|
|
||||||
color,
|
|
||||||
shape: CanvasShape::Line,
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_clipping(&mut self, rect: Rect) {
|
|
||||||
self.clippings.push(Some(rect));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_clip_rect(&mut self, rect: Option<Rect>) {
|
|
||||||
self.clippings.push(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clip_rect(&self) -> Option<Rect> {
|
|
||||||
self.clippings.last().cloned().unwrap_or_else(|| None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CharacterSizeManager for CanvasMock {
|
|
||||||
fn load_character_size(&mut self, c: char) -> Rect {
|
|
||||||
match self.character_sizes.get(&c) {
|
|
||||||
Some(r) => r.clone(),
|
|
||||||
None => {
|
|
||||||
self.character_sizes.insert(c, Rect::new(0, 0, 1, 1));
|
|
||||||
self.character_sizes.get(&c).cloned().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CanvasMock {
|
|
||||||
pub fn set_character_rect(&mut self, c: char, rect: Rect) {
|
|
||||||
self.character_sizes.insert(c, rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_pixel_with_color(
|
|
||||||
&self,
|
|
||||||
point: sdl2::rect::Point,
|
|
||||||
color: sdl2::pixels::Color,
|
|
||||||
) -> Option<&RendererRect> {
|
|
||||||
for rect in self.rects.iter() {
|
|
||||||
if rect.rect.contains_point(point.clone()) && rect.color == color {
|
|
||||||
return Some(rect.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for rect in self.borders.iter() {
|
|
||||||
if rect.rect.contains_point(point.clone()) && rect.color == color {
|
|
||||||
return Some(rect.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for rect in self.lines.iter() {
|
|
||||||
if rect.rect.contains_point(point.clone()) && rect.color == color {
|
|
||||||
return Some(rect.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_rect_with_color(
|
|
||||||
&self,
|
|
||||||
subject: sdl2::rect::Rect,
|
|
||||||
color: sdl2::pixels::Color,
|
|
||||||
) -> Option<&RendererRect> {
|
|
||||||
for rect in self.rects.iter() {
|
|
||||||
if rect.rect == subject && rect.color == color {
|
|
||||||
return Some(rect.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_line_with_color(
|
|
||||||
&self,
|
|
||||||
subject: sdl2::rect::Rect,
|
|
||||||
color: sdl2::pixels::Color,
|
|
||||||
) -> Option<&RendererRect> {
|
|
||||||
for rect in self.lines.iter() {
|
|
||||||
if rect.rect == subject && rect.color == color {
|
|
||||||
return Some(rect.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_border_with_color(
|
|
||||||
&self,
|
|
||||||
subject: sdl2::rect::Rect,
|
|
||||||
color: sdl2::pixels::Color,
|
|
||||||
) -> Option<&RendererRect> {
|
|
||||||
for rect in self.borders.iter() {
|
|
||||||
if rect.rect == subject && rect.color == color {
|
|
||||||
return Some(rect.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
pub struct SimpleRendererMock {
|
|
||||||
config: ConfigAccess,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl SimpleRendererMock {
|
|
||||||
pub fn new(config: ConfigAccess) -> Self {
|
|
||||||
Self { config }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl Renderer for SimpleRendererMock {
|
|
||||||
fn load_font(&mut self, _details: FontDetails) -> Rc<Font> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_text_tex(
|
|
||||||
&mut self,
|
|
||||||
_details: &mut TextDetails,
|
|
||||||
_font_details: FontDetails,
|
|
||||||
) -> Result<Rc<Texture>, String> {
|
|
||||||
Err("skip text texture".to_owned())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_image(&mut self, _path: String) -> Result<Rc<Texture>, String> {
|
|
||||||
Err("skip img texture".to_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl CharacterSizeManager for SimpleRendererMock {
|
|
||||||
fn load_character_size(&mut self, _c: char) -> Rect {
|
|
||||||
Rect::new(0, 0, 13, 14)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
|
||||||
impl ConfigHolder for SimpleRendererMock {
|
|
||||||
fn config(&self) -> &Arc<RwLock<Config>> {
|
|
||||||
&self.config
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
402
rider-editor/src/tests/mod.rs
Normal file
402
rider-editor/src/tests/mod.rs
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
use crate::renderer::managers::FontDetails;
|
||||||
|
use crate::renderer::managers::TextDetails;
|
||||||
|
use crate::renderer::renderer::Renderer;
|
||||||
|
use crate::renderer::TextureManager;
|
||||||
|
use crate::ui::text_character::CharacterSizeManager;
|
||||||
|
use crate::ui::CanvasAccess;
|
||||||
|
use rider_config::Config;
|
||||||
|
use rider_config::ConfigAccess;
|
||||||
|
use rider_config::ConfigHolder;
|
||||||
|
use sdl2::pixels::{Color, PixelFormatEnum};
|
||||||
|
use sdl2::rect::Point;
|
||||||
|
use sdl2::rect::Rect;
|
||||||
|
use sdl2::render::{Texture, TextureCreator};
|
||||||
|
use sdl2::ttf::{Font, Sdl2TtfContext};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::fmt::Error;
|
||||||
|
use std::fmt::Formatter;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
pub fn build_path(path: String) {
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
fs::create_dir_all(path.as_str()).unwrap();
|
||||||
|
fs::write((path.clone() + &"/file1".to_owned()).as_str(), "foo").unwrap();
|
||||||
|
fs::write((path.clone() + &"/file2".to_owned()).as_str(), "bar").unwrap();
|
||||||
|
fs::create_dir_all((path.clone() + &"/dir1".to_owned()).as_str()).unwrap();
|
||||||
|
fs::create_dir_all((path.clone() + &"/dir2".to_owned()).as_str()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
pub fn build_config() -> Arc<RwLock<Config>> {
|
||||||
|
let mut config = Config::new();
|
||||||
|
config.set_theme(config.editor_config().current_theme().clone());
|
||||||
|
Arc::new(RwLock::new(config))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum CanvasShape {
|
||||||
|
Line,
|
||||||
|
Border,
|
||||||
|
Rectangle,
|
||||||
|
Image(Rect, Rect, String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct RendererRect {
|
||||||
|
pub rect: Rect,
|
||||||
|
pub color: Color,
|
||||||
|
pub shape: CanvasShape,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl RendererRect {
|
||||||
|
pub fn new(rect: Rect, color: Color, shape: CanvasShape) -> Self {
|
||||||
|
Self { rect, color, shape }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
pub struct CanvasMock {
|
||||||
|
pub rects: Vec<RendererRect>,
|
||||||
|
pub borders: Vec<RendererRect>,
|
||||||
|
pub lines: Vec<RendererRect>,
|
||||||
|
pub clippings: Vec<Option<Rect>>,
|
||||||
|
pub character_sizes: HashMap<char, sdl2::rect::Rect>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl Debug for CanvasMock {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"CanvasMock {{ {:?} {:?} {:?} }}",
|
||||||
|
self.rects, self.lines, self.clippings
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl PartialEq for CanvasMock {
|
||||||
|
fn eq(&self, other: &CanvasMock) -> bool {
|
||||||
|
self.rects == other.rects
|
||||||
|
&& self.borders == other.borders
|
||||||
|
&& self.clippings == other.clippings
|
||||||
|
&& self.lines == other.lines
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl CanvasMock {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
rects: vec![],
|
||||||
|
borders: vec![],
|
||||||
|
lines: vec![],
|
||||||
|
clippings: vec![],
|
||||||
|
character_sizes: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl CanvasAccess for CanvasMock {
|
||||||
|
fn render_rect(&mut self, rect: Rect, color: Color) -> Result<(), String> {
|
||||||
|
self.rects.push(RendererRect {
|
||||||
|
rect,
|
||||||
|
color,
|
||||||
|
shape: CanvasShape::Rectangle,
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_border(&mut self, rect: Rect, color: Color) -> Result<(), String> {
|
||||||
|
self.borders.push(RendererRect {
|
||||||
|
rect,
|
||||||
|
color,
|
||||||
|
shape: CanvasShape::Border,
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_image(&mut self, _tex: Rc<Texture>, src: Rect, dest: Rect) -> Result<(), String> {
|
||||||
|
self.rects.push(RendererRect::new(
|
||||||
|
dest.clone(),
|
||||||
|
Color::RGBA(0, 0, 0, 255),
|
||||||
|
CanvasShape::Image(src.clone(), dest.clone(), format!("_tex: Rc<Texture>")),
|
||||||
|
));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_line(&mut self, start: Point, end: Point, color: Color) -> Result<(), String> {
|
||||||
|
self.lines.push(RendererRect {
|
||||||
|
rect: Rect::new(start.x(), start.y(), end.x() as u32, end.y() as u32),
|
||||||
|
color,
|
||||||
|
shape: CanvasShape::Line,
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_clipping(&mut self, rect: Rect) {
|
||||||
|
self.clippings.push(Some(rect));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_clip_rect(&mut self, rect: Option<Rect>) {
|
||||||
|
self.clippings.push(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clip_rect(&self) -> Option<Rect> {
|
||||||
|
self.clippings.last().cloned().unwrap_or_else(|| None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl CharacterSizeManager for CanvasMock {
|
||||||
|
fn load_character_size(&mut self, c: char) -> Rect {
|
||||||
|
match self.character_sizes.get(&c) {
|
||||||
|
Some(r) => r.clone(),
|
||||||
|
None => {
|
||||||
|
self.character_sizes.insert(c, Rect::new(0, 0, 1, 1));
|
||||||
|
self.character_sizes.get(&c).cloned().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
pub trait CanvasTester {
|
||||||
|
fn set_character_rect(&mut self, c: char, rect: Rect);
|
||||||
|
|
||||||
|
fn find_pixel_with_color(
|
||||||
|
&self,
|
||||||
|
point: sdl2::rect::Point,
|
||||||
|
color: sdl2::pixels::Color,
|
||||||
|
) -> Option<&RendererRect>;
|
||||||
|
|
||||||
|
fn find_rect_with_color(
|
||||||
|
&self,
|
||||||
|
subject: sdl2::rect::Rect,
|
||||||
|
color: sdl2::pixels::Color,
|
||||||
|
) -> Option<&RendererRect>;
|
||||||
|
|
||||||
|
fn find_line_with_color(
|
||||||
|
&self,
|
||||||
|
subject: sdl2::rect::Rect,
|
||||||
|
color: sdl2::pixels::Color,
|
||||||
|
) -> Option<&RendererRect>;
|
||||||
|
|
||||||
|
fn find_border_with_color(
|
||||||
|
&self,
|
||||||
|
subject: sdl2::rect::Rect,
|
||||||
|
color: sdl2::pixels::Color,
|
||||||
|
) -> Option<&RendererRect>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl CanvasTester for CanvasMock {
|
||||||
|
fn set_character_rect(&mut self, c: char, rect: Rect) {
|
||||||
|
self.character_sizes.insert(c, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_pixel_with_color(
|
||||||
|
&self,
|
||||||
|
point: sdl2::rect::Point,
|
||||||
|
color: sdl2::pixels::Color,
|
||||||
|
) -> Option<&RendererRect> {
|
||||||
|
for rect in self.rects.iter() {
|
||||||
|
if rect.rect.contains_point(point.clone()) && rect.color == color {
|
||||||
|
return Some(rect.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for rect in self.borders.iter() {
|
||||||
|
if rect.rect.contains_point(point.clone()) && rect.color == color {
|
||||||
|
return Some(rect.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for rect in self.lines.iter() {
|
||||||
|
if rect.rect.contains_point(point.clone()) && rect.color == color {
|
||||||
|
return Some(rect.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_rect_with_color(
|
||||||
|
&self,
|
||||||
|
subject: sdl2::rect::Rect,
|
||||||
|
color: sdl2::pixels::Color,
|
||||||
|
) -> Option<&RendererRect> {
|
||||||
|
for rect in self.rects.iter() {
|
||||||
|
if rect.rect == subject && rect.color == color {
|
||||||
|
return Some(rect.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_line_with_color(
|
||||||
|
&self,
|
||||||
|
subject: sdl2::rect::Rect,
|
||||||
|
color: sdl2::pixels::Color,
|
||||||
|
) -> Option<&RendererRect> {
|
||||||
|
for rect in self.lines.iter() {
|
||||||
|
if rect.rect == subject && rect.color == color {
|
||||||
|
return Some(rect.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_border_with_color(
|
||||||
|
&self,
|
||||||
|
subject: sdl2::rect::Rect,
|
||||||
|
color: sdl2::pixels::Color,
|
||||||
|
) -> Option<&RendererRect> {
|
||||||
|
for rect in self.borders.iter() {
|
||||||
|
if rect.rect == subject && rect.color == color {
|
||||||
|
return Some(rect.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
pub struct SimpleRendererMock<'l> {
|
||||||
|
pub config: ConfigAccess,
|
||||||
|
pub ttf: Sdl2TtfContext,
|
||||||
|
pub character_sizes: HashMap<char, Rect>,
|
||||||
|
pub texture_manager: TextureManager<'l, sdl2::surface::SurfaceContext<'l>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl<'l> SimpleRendererMock<'l> {
|
||||||
|
pub fn set_character_rect(&mut self, c: char, rect: Rect) {
|
||||||
|
self.character_sizes.insert(c, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn texture_creator(&self) -> &TextureCreator<sdl2::surface::SurfaceContext<'l>> {
|
||||||
|
self.texture_manager.loader()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl<'l> Renderer for SimpleRendererMock<'l> {
|
||||||
|
fn load_font(&mut self, details: FontDetails) -> Rc<Font> {
|
||||||
|
Rc::new(
|
||||||
|
self.ttf
|
||||||
|
.load_font(details.path, details.size)
|
||||||
|
.unwrap_or_else(|e| panic!("{:?}", e)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_text_tex(
|
||||||
|
&mut self,
|
||||||
|
_details: &mut TextDetails,
|
||||||
|
_font_details: FontDetails,
|
||||||
|
) -> Result<Rc<Texture>, String> {
|
||||||
|
self.texture_creator()
|
||||||
|
.create_texture(
|
||||||
|
PixelFormatEnum::RGB24,
|
||||||
|
sdl2::render::TextureAccess::Target,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("{:?}", e))
|
||||||
|
.map(|t| Rc::new(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_image(&mut self, path: String) -> Result<Rc<Texture>, String> {
|
||||||
|
self.texture_manager.load(path.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl<'l> CharacterSizeManager for SimpleRendererMock<'l> {
|
||||||
|
fn load_character_size(&mut self, c: char) -> Rect {
|
||||||
|
match self.character_sizes.get(&c) {
|
||||||
|
Some(r) => r.clone(),
|
||||||
|
_ => {
|
||||||
|
let rect = Rect::new(0, 0, 13, 14);
|
||||||
|
self.set_character_rect(c.clone(), rect.clone());
|
||||||
|
rect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl<'l> ConfigHolder for SimpleRendererMock<'l> {
|
||||||
|
fn config(&self) -> &Arc<RwLock<Config>> {
|
||||||
|
&self.config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
pub type TestCanvas<'r> = sdl2::render::Canvas<sdl2::surface::Surface<'r>>;
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl<'r> CanvasAccess for TestCanvas<'r> {
|
||||||
|
fn render_rect(&mut self, rect: Rect, color: sdl2::pixels::Color) -> Result<(), String> {
|
||||||
|
self.set_draw_color(color);
|
||||||
|
self.fill_rect(rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_border(&mut self, rect: Rect, color: sdl2::pixels::Color) -> Result<(), String> {
|
||||||
|
self.set_draw_color(color);
|
||||||
|
self.draw_rect(rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_image(&mut self, tex: Rc<Texture>, src: Rect, dest: Rect) -> Result<(), String> {
|
||||||
|
self.copy_ex(&tex, Some(src), Some(dest), 0.0, None, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_line(
|
||||||
|
&mut self,
|
||||||
|
start: Point,
|
||||||
|
end: Point,
|
||||||
|
color: sdl2::pixels::Color,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
self.set_draw_color(color);
|
||||||
|
self.draw_line(start, end)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_clipping(&mut self, rect: Rect) {
|
||||||
|
self.set_clip_rect(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_clip_rect(&mut self, rect: Option<Rect>) {
|
||||||
|
self.set_clip_rect(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clip_rect(&self) -> Option<Rect> {
|
||||||
|
self.clip_rect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
pub trait DumpImage {
|
||||||
|
fn dump_ui<S>(&self, path: S)
|
||||||
|
where
|
||||||
|
S: Into<String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
impl<'r> DumpImage for TestCanvas<'r> {
|
||||||
|
fn dump_ui<S>(&self, path: S)
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
let p = std::path::PathBuf::from(path.into());
|
||||||
|
std::fs::create_dir_all(p.parent().unwrap()).unwrap();
|
||||||
|
self.surface()
|
||||||
|
.save_bmp(p)
|
||||||
|
.expect("Failed to save canvas as BMP file");
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ pub struct SaveButton {
|
|||||||
inner: WidgetInner,
|
inner: WidgetInner,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl std::ops::Deref for SaveButton {
|
impl std::ops::Deref for SaveButton {
|
||||||
type Target = WidgetInner;
|
type Target = WidgetInner;
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ impl std::ops::Deref for SaveButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl std::ops::DerefMut for SaveButton {
|
impl std::ops::DerefMut for SaveButton {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.inner
|
&mut self.inner
|
||||||
@ -79,11 +81,11 @@ impl SaveButton {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app::UpdateResult;
|
use crate::app::UpdateResult;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_save_on_left_click() {
|
fn must_return_save_on_left_click() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = SaveButton::new(config);
|
let mut widget = SaveButton::new(config);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
widget.on_left_click(&Point::new(0, 0), &UpdateContext::Nothing),
|
widget.on_left_click(&Point::new(0, 0), &UpdateContext::Nothing),
|
||||||
@ -93,7 +95,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_use_inner() {
|
fn must_use_inner() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = SaveButton::new(config);
|
let mut widget = SaveButton::new(config);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -113,7 +115,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_have_padding() {
|
fn must_have_padding() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = SaveButton::new(config);
|
let widget = SaveButton::new(config);
|
||||||
assert_eq!(widget.padding_width(), ICON_DEST_WIDTH);
|
assert_eq!(widget.padding_width(), ICON_DEST_WIDTH);
|
||||||
assert_eq!(widget.padding_height(), ICON_DEST_HEIGHT);
|
assert_eq!(widget.padding_height(), ICON_DEST_HEIGHT);
|
||||||
|
@ -80,11 +80,11 @@ impl SettingsButton {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app::UpdateResult;
|
use crate::app::UpdateResult;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_open_settings_on_left_click() {
|
fn must_return_open_settings_on_left_click() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = SettingsButton::new(config);
|
let mut widget = SettingsButton::new(config);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
widget.on_left_click(&Point::new(0, 0), &UpdateContext::Nothing),
|
widget.on_left_click(&Point::new(0, 0), &UpdateContext::Nothing),
|
||||||
@ -94,7 +94,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_use_inner() {
|
fn must_use_inner() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = SettingsButton::new(config);
|
let mut widget = SettingsButton::new(config);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -114,7 +114,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_have_padding() {
|
fn must_have_padding() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = SettingsButton::new(config);
|
let widget = SettingsButton::new(config);
|
||||||
assert_eq!(widget.padding_width(), ICON_DEST_WIDTH);
|
assert_eq!(widget.padding_width(), ICON_DEST_WIDTH);
|
||||||
assert_eq!(widget.padding_height(), ICON_DEST_HEIGHT);
|
assert_eq!(widget.padding_height(), ICON_DEST_HEIGHT);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::app::UpdateResult as UR;
|
use crate::app::UpdateResult;
|
||||||
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
use rider_config::ConfigAccess;
|
use rider_config::{ConfigAccess, ConfigHolder};
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
@ -69,11 +70,56 @@ impl DerefMut for Caret {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
impl Widget for Caret {
|
||||||
impl Caret {
|
fn texture_path(&self) -> Option<String> {
|
||||||
pub fn render<T>(&self, canvas: &mut T, context: &RenderContext)
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UpdateResult {
|
||||||
|
self.blink_delay += 1;
|
||||||
|
if self.blink_delay >= 15 {
|
||||||
|
self.blink_delay = 0;
|
||||||
|
self.toggle_state();
|
||||||
|
}
|
||||||
|
UpdateResult::NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
||||||
|
UR::NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
||||||
|
match context {
|
||||||
|
&UpdateContext::ParentPosition(p) => move_render_point(p, &self.dest),
|
||||||
|
_ => self.dest().clone(),
|
||||||
|
}
|
||||||
|
.contains_point(point.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_start_point(&self) -> Point {
|
||||||
|
self.dest().top_left()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<C, R>(&self, canvas: &mut C, _renderer: &mut R, context: &RenderContext)
|
||||||
where
|
where
|
||||||
T: CanvasAccess,
|
C: CanvasAccess,
|
||||||
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
use std::borrow::*;
|
use std::borrow::*;
|
||||||
|
|
||||||
@ -92,54 +138,15 @@ impl Caret {
|
|||||||
.render_line(start, end, color)
|
.render_line(start, end, color)
|
||||||
.unwrap_or_else(|_| panic!("Failed to draw a caret"));
|
.unwrap_or_else(|_| panic!("Failed to draw a caret"));
|
||||||
}
|
}
|
||||||
|
fn prepare_ui<'l, T>(&mut self, renderer: &mut T)
|
||||||
pub fn prepare_ui<T>(&mut self, renderer: &mut T)
|
|
||||||
where
|
where
|
||||||
T: CharacterSizeManager,
|
T: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
let rect = renderer.load_character_size('I');
|
let rect = renderer.load_character_size('I');
|
||||||
self.dest.set_height(rect.height());
|
self.dest.set_height(rect.height());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Caret {
|
|
||||||
pub fn update(&mut self) -> UR {
|
|
||||||
self.blink_delay += 1;
|
|
||||||
if self.blink_delay >= 15 {
|
|
||||||
self.blink_delay = 0;
|
|
||||||
self.toggle_state();
|
|
||||||
}
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClickHandler for Caret {
|
|
||||||
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
|
||||||
let dest = self.dest();
|
|
||||||
is_in_rect(
|
|
||||||
point,
|
|
||||||
&match context {
|
|
||||||
&UpdateContext::ParentPosition(p) => move_render_point(p, &dest),
|
|
||||||
_ => dest,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RenderBox for Caret {
|
|
||||||
fn render_start_point(&self) -> Point {
|
|
||||||
self.dest().top_left()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dest(&self) -> Rect {
|
|
||||||
self.dest.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_own_methods {
|
mod test_own_methods {
|
||||||
use crate::tests::*;
|
use crate::tests::*;
|
||||||
@ -149,7 +156,7 @@ mod test_own_methods {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_move_caret() {
|
fn assert_move_caret() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = Caret::new(Arc::clone(&config));
|
let mut widget = Caret::new(Arc::clone(&config));
|
||||||
widget.move_caret(widget.moved(10, 21, 34), Point::new(10, 20));
|
widget.move_caret(widget.moved(10, 21, 34), Point::new(10, 20));
|
||||||
let result = (
|
let result = (
|
||||||
@ -164,7 +171,7 @@ mod test_own_methods {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_reset() {
|
fn assert_reset() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = Caret::new(Arc::clone(&config));
|
let mut widget = Caret::new(Arc::clone(&config));
|
||||||
widget.reset_caret();
|
widget.reset_caret();
|
||||||
let result = (
|
let result = (
|
||||||
@ -179,7 +186,7 @@ mod test_own_methods {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_toggle_state() {
|
fn assert_toggle_state() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = Caret::new(Arc::clone(&config));
|
let mut widget = Caret::new(Arc::clone(&config));
|
||||||
|
|
||||||
let old = widget.state().clone();
|
let old = widget.state().clone();
|
||||||
@ -208,7 +215,7 @@ mod test_deref {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_deref_text_position() {
|
fn must_deref_text_position() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = Caret::new(Arc::clone(&config));
|
let mut widget = Caret::new(Arc::clone(&config));
|
||||||
widget.move_caret(widget.moved(10, 21, 34), Point::new(0, 0));
|
widget.move_caret(widget.moved(10, 21, 34), Point::new(0, 0));
|
||||||
let result = widget.text_position();
|
let result = widget.text_position();
|
||||||
@ -218,7 +225,7 @@ mod test_deref {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_deref_line_number() {
|
fn must_deref_line_number() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = Caret::new(Arc::clone(&config));
|
let mut widget = Caret::new(Arc::clone(&config));
|
||||||
widget.move_caret(widget.moved(10, 21, 34), Point::new(0, 0));
|
widget.move_caret(widget.moved(10, 21, 34), Point::new(0, 0));
|
||||||
let result = widget.line_number();
|
let result = widget.line_number();
|
||||||
@ -228,7 +235,7 @@ mod test_deref {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_deref_line_position() {
|
fn must_deref_line_position() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = Caret::new(Arc::clone(&config));
|
let mut widget = Caret::new(Arc::clone(&config));
|
||||||
widget.move_caret(widget.moved(10, 21, 34), Point::new(0, 0));
|
widget.move_caret(widget.moved(10, 21, 34), Point::new(0, 0));
|
||||||
let result = widget.line_position();
|
let result = widget.line_position();
|
||||||
@ -246,7 +253,7 @@ mod test_render_box {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_top_left_point() {
|
fn must_return_top_left_point() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = Caret::new(Arc::clone(&config));
|
let widget = Caret::new(Arc::clone(&config));
|
||||||
let result = widget.render_start_point();
|
let result = widget.render_start_point();
|
||||||
let expected = Point::new(0, 0);
|
let expected = Point::new(0, 0);
|
||||||
@ -264,7 +271,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_when_not_click_target() {
|
fn refute_when_not_click_target() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = Caret::new(Arc::clone(&config));
|
let widget = Caret::new(Arc::clone(&config));
|
||||||
let point = Point::new(9999, 9999);
|
let point = Point::new(9999, 9999);
|
||||||
let context = UpdateContext::Nothing;
|
let context = UpdateContext::Nothing;
|
||||||
@ -274,7 +281,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_when_click_target() {
|
fn assert_when_click_target() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = Caret::new(Arc::clone(&config));
|
let widget = Caret::new(Arc::clone(&config));
|
||||||
|
|
||||||
let point = Point::new(0, 0);
|
let point = Point::new(0, 0);
|
||||||
@ -285,7 +292,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_when_not_click_target_because_parent() {
|
fn refute_when_not_click_target_because_parent() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = Caret::new(Arc::clone(&config));
|
let widget = Caret::new(Arc::clone(&config));
|
||||||
let point = Point::new(20, 30);
|
let point = Point::new(20, 30);
|
||||||
let context = UpdateContext::ParentPosition(Point::new(9999, 9999));
|
let context = UpdateContext::ParentPosition(Point::new(9999, 9999));
|
||||||
@ -295,7 +302,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_when_click_target_because_parent() {
|
fn assert_when_click_target_because_parent() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = Caret::new(Arc::clone(&config));
|
let widget = Caret::new(Arc::clone(&config));
|
||||||
let point = Point::new(10, 10);
|
let point = Point::new(10, 10);
|
||||||
let context = UpdateContext::ParentPosition(Point::new(10, 10));
|
let context = UpdateContext::ParentPosition(Point::new(10, 10));
|
||||||
@ -305,7 +312,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_on_click_do_nothing() {
|
fn assert_on_click_do_nothing() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = Caret::new(Arc::clone(&config));
|
let mut widget = Caret::new(Arc::clone(&config));
|
||||||
let point = Point::new(12, 34);
|
let point = Point::new(12, 34);
|
||||||
let context = UpdateContext::ParentPosition(Point::new(678, 293));
|
let context = UpdateContext::ParentPosition(Point::new(678, 293));
|
||||||
@ -317,41 +324,43 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_render {
|
mod test_render {
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use crate::tests::support::build_config;
|
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
|
use rider_derive::*;
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_render_line() {
|
fn assert_render_line() {
|
||||||
let config = build_config();
|
|
||||||
let context = RenderContext::ParentPosition(Point::new(10, 14));
|
let context = RenderContext::ParentPosition(Point::new(10, 14));
|
||||||
let mut canvas = support::CanvasMock::new();
|
build_test_renderer!(renderer);
|
||||||
|
|
||||||
let mut widget = Caret::new(config);
|
let mut widget = Caret::new(config);
|
||||||
canvas.set_character_rect('I', Rect::new(11, 12, 6, 23));
|
canvas.set_character_rect('I', Rect::new(11, 12, 6, 23));
|
||||||
widget.move_caret(CaretPosition::new(0, 0, 0), Point::new(23, 23));
|
widget.move_caret(CaretPosition::new(0, 0, 0), Point::new(23, 23));
|
||||||
widget.render(&mut canvas, &context);
|
widget.render(&mut canvas, &mut renderer, &context);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
canvas.find_pixel_with_color(
|
canvas.find_pixel_with_color(
|
||||||
Point::new(33, 37),
|
Point::new(33, 37),
|
||||||
sdl2::pixels::Color::RGBA(121, 121, 121, 0)
|
sdl2::pixels::Color::RGBA(121, 121, 121, 0)
|
||||||
),
|
),
|
||||||
Some(&support::RendererRect::new(
|
Some(&RendererRect::new(
|
||||||
Rect::new(33, 37, 33, 38),
|
Rect::new(33, 37, 33, 38),
|
||||||
sdl2::pixels::Color::RGBA(121, 121, 121, 0),
|
sdl2::pixels::Color::RGBA(121, 121, 121, 0),
|
||||||
support::CanvasShape::Line
|
CanvasShape::Line
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepare_ui() {
|
fn assert_prepare_ui() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut canvas = support::CanvasMock::new();
|
renderer
|
||||||
canvas.set_character_rect('I', Rect::new(11, 12, 6, 23));
|
.character_sizes
|
||||||
|
.insert('I', Rect::new(11, 12, 6, 23));
|
||||||
|
|
||||||
let mut widget = Caret::new(config);
|
let mut widget = Caret::new(config);
|
||||||
widget.move_caret(CaretPosition::new(0, 0, 0), Point::new(11, 12));
|
widget.move_caret(CaretPosition::new(0, 0, 0), Point::new(11, 12));
|
||||||
widget.prepare_ui(&mut canvas);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.dest(), Rect::new(11, 12, 6, 23));
|
assert_eq!(widget.dest(), &Rect::new(11, 12, 6, 23));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,6 @@ impl EditorFile {
|
|||||||
self.line_height
|
self.line_height
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_position(&self) -> &Rect {
|
|
||||||
&self.dest
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_section_at_mut(&mut self, index: usize) -> Option<&mut EditorFileSection> {
|
pub fn get_section_at_mut(&mut self, index: usize) -> Option<&mut EditorFileSection> {
|
||||||
self.sections.get_mut(index)
|
self.sections.get_mut(index)
|
||||||
}
|
}
|
||||||
@ -97,9 +93,8 @@ impl TextCollection for EditorFile {
|
|||||||
fn get_line(&self, line: &usize) -> Option<Vec<&TextCharacter>> {
|
fn get_line(&self, line: &usize) -> Option<Vec<&TextCharacter>> {
|
||||||
let mut vec: Vec<&TextCharacter> = vec![];
|
let mut vec: Vec<&TextCharacter> = vec![];
|
||||||
for section in self.sections.iter() {
|
for section in self.sections.iter() {
|
||||||
match section.get_line(line) {
|
if let Some(v) = section.get_line(line) {
|
||||||
Some(v) => vec.append(&mut v.clone()),
|
vec.append(&mut v.clone());
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,32 +141,27 @@ impl TextCollection for EditorFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorFile {
|
impl Widget for EditorFile {
|
||||||
pub fn render<R, C>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
fn texture_path(&self) -> Option<String> {
|
||||||
where
|
None
|
||||||
R: Renderer + ConfigHolder,
|
|
||||||
C: CanvasAccess,
|
|
||||||
{
|
|
||||||
for section in self.sections.iter() {
|
|
||||||
section.render(canvas, renderer, context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
fn dest(&self) -> &Rect {
|
||||||
where
|
&self.dest
|
||||||
R: ConfigHolder + CharacterSizeManager + Renderer,
|
|
||||||
{
|
|
||||||
for section in self.sections.iter_mut() {
|
|
||||||
section.prepare_ui(renderer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = renderer.load_character_size('W');
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
self.line_height = r.height();
|
self.dest = rect.clone();
|
||||||
self.refresh_characters_position();
|
}
|
||||||
}
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
self.dest()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect) {
|
||||||
|
self.set_dest(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Update for EditorFile {
|
|
||||||
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
||||||
let mut result = UR::NoOp;
|
let mut result = UR::NoOp;
|
||||||
for section in self.sections.iter_mut() {
|
for section in self.sections.iter_mut() {
|
||||||
@ -179,9 +169,7 @@ impl Update for EditorFile {
|
|||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ClickHandler for EditorFile {
|
|
||||||
fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UR {
|
fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UR {
|
||||||
let mut index = -1;
|
let mut index = -1;
|
||||||
for (i, section) in self.sections.iter().enumerate() {
|
for (i, section) in self.sections.iter().enumerate() {
|
||||||
@ -207,6 +195,29 @@ impl ClickHandler for EditorFile {
|
|||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
|
where
|
||||||
|
C: CanvasAccess,
|
||||||
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
|
{
|
||||||
|
for section in self.sections.iter() {
|
||||||
|
section.render(canvas, renderer, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_ui<'l, T>(&mut self, renderer: &mut T)
|
||||||
|
where
|
||||||
|
T: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
|
{
|
||||||
|
for section in self.sections.iter_mut() {
|
||||||
|
section.prepare_ui(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = renderer.load_character_size('W');
|
||||||
|
self.line_height = r.height();
|
||||||
|
self.refresh_characters_position();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextWidget for EditorFile {
|
impl TextWidget for EditorFile {
|
||||||
@ -230,16 +241,6 @@ impl TextWidget for EditorFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderBox for EditorFile {
|
|
||||||
fn render_start_point(&self) -> Point {
|
|
||||||
self.dest.top_left()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dest(&self) -> Rect {
|
|
||||||
self.dest.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EditorFileIterator<'a> {
|
pub struct EditorFileIterator<'a> {
|
||||||
current_section: usize,
|
current_section: usize,
|
||||||
current_token: usize,
|
current_token: usize,
|
||||||
@ -298,19 +299,34 @@ impl<'a> Iterator for EditorFileIterator<'a> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use crate::tests::support::SimpleRendererMock;
|
|
||||||
|
use crate::app::UpdateResult;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
|
use rider_derive::*;
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_get_line() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut file =
|
||||||
|
EditorFile::new("./foo.txt".to_owned(), "a b c d".to_owned(), config.clone());
|
||||||
|
file.prepare_ui(&mut renderer);
|
||||||
|
|
||||||
|
let result = file.get_line(&0);
|
||||||
|
assert_eq!(result.is_some(), true);
|
||||||
|
|
||||||
|
let result = file.get_line(&1);
|
||||||
|
assert_eq!(result.is_some(), false);
|
||||||
|
}
|
||||||
|
|
||||||
//##################################################
|
//##################################################
|
||||||
// iterator
|
// iterator
|
||||||
//##################################################
|
//##################################################
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_simple_iterations() {
|
fn assert_simple_iterations() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut file =
|
let mut file =
|
||||||
EditorFile::new("./foo.txt".to_owned(), "a b c d".to_owned(), config.clone());
|
EditorFile::new("./foo.txt".to_owned(), "a b c d".to_owned(), config.clone());
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
@ -334,7 +350,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_path_txt() {
|
fn assert_path_txt() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let buffer = "".to_owned();
|
let buffer = "".to_owned();
|
||||||
let path = "/example.txt".to_owned();
|
let path = "/example.txt".to_owned();
|
||||||
let widget = EditorFile::new(path, buffer, config);
|
let widget = EditorFile::new(path, buffer, config);
|
||||||
@ -343,7 +359,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_path_rs() {
|
fn assert_path_rs() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let buffer = "".to_owned();
|
let buffer = "".to_owned();
|
||||||
let path = "/example.rs".to_owned();
|
let path = "/example.rs".to_owned();
|
||||||
let widget = EditorFile::new(path, buffer, config);
|
let widget = EditorFile::new(path, buffer, config);
|
||||||
@ -356,7 +372,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_empty_buffer() {
|
fn assert_empty_buffer() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let buffer = "".to_owned();
|
let buffer = "".to_owned();
|
||||||
let path = "/example.txt".to_owned();
|
let path = "/example.txt".to_owned();
|
||||||
let widget = EditorFile::new(path, buffer, config);
|
let widget = EditorFile::new(path, buffer, config);
|
||||||
@ -365,7 +381,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_some_buffer() {
|
fn assert_some_buffer() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let buffer = "fn main(){}".to_owned();
|
let buffer = "fn main(){}".to_owned();
|
||||||
let path = "some.rs".to_owned();
|
let path = "some.rs".to_owned();
|
||||||
let widget = EditorFile::new(path, buffer, config);
|
let widget = EditorFile::new(path, buffer, config);
|
||||||
@ -378,7 +394,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_initial_line_height() {
|
fn assert_initial_line_height() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let buffer = "".to_owned();
|
let buffer = "".to_owned();
|
||||||
let path = "/example.txt".to_owned();
|
let path = "/example.txt".to_owned();
|
||||||
let widget = EditorFile::new(path, buffer, config);
|
let widget = EditorFile::new(path, buffer, config);
|
||||||
@ -391,7 +407,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_dest() {
|
fn assert_dest() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let buffer = "".to_owned();
|
let buffer = "".to_owned();
|
||||||
let path = "/example.txt".to_owned();
|
let path = "/example.txt".to_owned();
|
||||||
let widget = EditorFile::new(path, buffer, config);
|
let widget = EditorFile::new(path, buffer, config);
|
||||||
@ -402,7 +418,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_render_start_point() {
|
fn assert_render_start_point() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let buffer = "".to_owned();
|
let buffer = "".to_owned();
|
||||||
let path = "/example.txt".to_owned();
|
let path = "/example.txt".to_owned();
|
||||||
let widget = EditorFile::new(path, buffer, config);
|
let widget = EditorFile::new(path, buffer, config);
|
||||||
@ -410,4 +426,129 @@ mod tests {
|
|||||||
let expected = Point::new(0, 0);
|
let expected = Point::new(0, 0);
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_get_section_at_mut() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let mut widget = EditorFile::new(path, buffer, config);
|
||||||
|
let result = widget.get_section_at_mut(12);
|
||||||
|
assert!(result.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
//#######################################################
|
||||||
|
// widget
|
||||||
|
//#######################################################
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_texture_path() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let widget = EditorFile::new(path, buffer, config);
|
||||||
|
let result = widget.texture_path();
|
||||||
|
assert!(result.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_set_dest() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let mut widget = EditorFile::new(path, buffer, config);
|
||||||
|
let rect = Rect::new(2, 4, 6, 8);
|
||||||
|
widget.set_dest(&rect);
|
||||||
|
assert_eq!(format!("{:?}", widget.dest()), format!("{:?}", rect));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_source() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let mut widget = EditorFile::new(path, buffer, config);
|
||||||
|
let rect = Rect::new(2, 4, 6, 8);
|
||||||
|
widget.set_source(&rect);
|
||||||
|
assert_eq!(format!("{:?}", widget.source()), format!("{:?}", rect));
|
||||||
|
assert_eq!(
|
||||||
|
format!("{:?}", widget.source()),
|
||||||
|
format!("{:?}", widget.dest())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_update() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let mut widget = EditorFile::new(path, buffer, config);
|
||||||
|
let result = widget.update(0, &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, UpdateResult::NoOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_on_left_click() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let mut widget = EditorFile::new(path, buffer, config);
|
||||||
|
let result = widget.on_left_click(&Point::new(0, 0), &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, UpdateResult::NoOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_on_left_click_with_sections() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let mut widget = EditorFile::new(path, buffer, config.clone());
|
||||||
|
widget.sections = vec![EditorFileSection::new(
|
||||||
|
"a b c d".to_string(),
|
||||||
|
"".to_string(),
|
||||||
|
config,
|
||||||
|
)];
|
||||||
|
widget.prepare_ui(&mut renderer);
|
||||||
|
let result = widget.on_left_click(&Point::new(0, 0), &UpdateContext::Nothing);
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
UpdateResult::MoveCaret(Rect::new(0, 0, 13, 14), CaretPosition::new(0, 0, 0))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_is_left_click_target() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let widget = EditorFile::new(path, buffer, config);
|
||||||
|
let result = widget.is_left_click_target(&Point::new(0, 0), &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_is_left_click_target_with_sections() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let mut widget = EditorFile::new(path, buffer, config.clone());
|
||||||
|
widget.sections = vec![EditorFileSection::new(
|
||||||
|
"a b c d".to_string(),
|
||||||
|
"".to_string(),
|
||||||
|
config,
|
||||||
|
)];
|
||||||
|
widget.prepare_ui(&mut renderer);
|
||||||
|
let result = widget.is_left_click_target(&Point::new(0, 0), &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_render() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let buffer = "a b c".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let widget = EditorFile::new(path, buffer, config.clone());
|
||||||
|
widget.render(&mut canvas, &mut renderer, &RenderContext::Nothing);
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ pub struct EditorFileSection {
|
|||||||
tokens: Vec<EditorFileToken>,
|
tokens: Vec<EditorFileToken>,
|
||||||
language: Language,
|
language: Language,
|
||||||
config: Arc<RwLock<Config>>,
|
config: Arc<RwLock<Config>>,
|
||||||
|
dest: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorFileSection {
|
impl EditorFileSection {
|
||||||
@ -48,6 +49,7 @@ impl EditorFileSection {
|
|||||||
tokens,
|
tokens,
|
||||||
language,
|
language,
|
||||||
config,
|
config,
|
||||||
|
dest: Rect::new(0, 0, 0, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,25 +63,6 @@ impl EditorFileSection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render<R, C>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
|
||||||
where
|
|
||||||
R: Renderer + ConfigHolder,
|
|
||||||
C: CanvasAccess,
|
|
||||||
{
|
|
||||||
for token in self.tokens.iter() {
|
|
||||||
token.render(canvas, renderer, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prepare_ui<'l, T>(&mut self, renderer: &mut T)
|
|
||||||
where
|
|
||||||
T: ConfigHolder + CharacterSizeManager + Renderer,
|
|
||||||
{
|
|
||||||
for token in self.tokens.iter_mut() {
|
|
||||||
token.prepare_ui(renderer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn iter_char(&self) -> EditorFileSectionIterator {
|
pub fn iter_char(&self) -> EditorFileSectionIterator {
|
||||||
EditorFileSectionIterator::new(self)
|
EditorFileSectionIterator::new(self)
|
||||||
@ -90,6 +73,83 @@ impl EditorFileSection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Widget for EditorFileSection {
|
||||||
|
fn texture_path(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
||||||
|
let mut result = UR::NoOp;
|
||||||
|
for token in self.tokens.iter_mut() {
|
||||||
|
result = token.update(ticks, context)
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UR {
|
||||||
|
for token in self.tokens.iter_mut() {
|
||||||
|
if token.is_left_click_target(point, context) {
|
||||||
|
return token.on_left_click(point, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UR::NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
||||||
|
let mut i = 0;
|
||||||
|
loop {
|
||||||
|
if i == self.tokens.len() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
match self.tokens.get(i) {
|
||||||
|
Some(token) => {
|
||||||
|
if token.is_left_click_target(point, context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
|
where
|
||||||
|
C: CanvasAccess,
|
||||||
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
|
{
|
||||||
|
for token in self.tokens.iter() {
|
||||||
|
token.render(canvas, renderer, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_ui<'l, T>(&mut self, renderer: &mut T)
|
||||||
|
where
|
||||||
|
T: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
|
{
|
||||||
|
for token in self.tokens.iter_mut() {
|
||||||
|
token.prepare_ui(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TextWidget for EditorFileSection {
|
impl TextWidget for EditorFileSection {
|
||||||
fn full_rect(&self) -> Rect {
|
fn full_rect(&self) -> Rect {
|
||||||
let mut current_line_width = 0;
|
let mut current_line_width = 0;
|
||||||
@ -157,46 +217,6 @@ impl TextCollection for EditorFileSection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Update for EditorFileSection {
|
|
||||||
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
|
||||||
let mut result = UR::NoOp;
|
|
||||||
for token in self.tokens.iter_mut() {
|
|
||||||
result = token.update(ticks, context)
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClickHandler for EditorFileSection {
|
|
||||||
fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UR {
|
|
||||||
for token in self.tokens.iter_mut() {
|
|
||||||
if token.is_left_click_target(point, context) {
|
|
||||||
return token.on_left_click(point, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
|
||||||
let mut i = 0;
|
|
||||||
loop {
|
|
||||||
if i == self.tokens.len() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
match self.tokens.get(i) {
|
|
||||||
Some(token) => {
|
|
||||||
if token.is_left_click_target(point, context) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => break,
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EditorFileSectionIterator<'a> {
|
pub struct EditorFileSectionIterator<'a> {
|
||||||
section: &'a EditorFileSection,
|
section: &'a EditorFileSection,
|
||||||
current_token: usize,
|
current_token: usize,
|
||||||
@ -243,7 +263,8 @@ impl<'a> std::iter::Iterator for EditorFileSectionIterator<'a> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support::{build_config, SimpleRendererMock};
|
use crate::tests::*;
|
||||||
|
use rider_derive::*;
|
||||||
|
|
||||||
impl EditorFileSection {
|
impl EditorFileSection {
|
||||||
pub fn tokens_count(&self) -> usize {
|
pub fn tokens_count(&self) -> usize {
|
||||||
@ -269,8 +290,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_simple_char_iteration() {
|
fn assert_simple_char_iteration() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut section = EditorFileSection::new("a b c d".to_owned(), ".txt".to_owned(), config);
|
let mut section = EditorFileSection::new("a b c d".to_owned(), ".txt".to_owned(), config);
|
||||||
section.prepare_ui(&mut renderer);
|
section.prepare_ui(&mut renderer);
|
||||||
for (index, c) in section.iter_char().enumerate() {
|
for (index, c) in section.iter_char().enumerate() {
|
||||||
@ -289,8 +309,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_complex_char_iteration() {
|
fn assert_complex_char_iteration() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut section = EditorFileSection::new("let a = 1".to_owned(), ".rs".to_owned(), config);
|
let mut section = EditorFileSection::new("let a = 1".to_owned(), ".rs".to_owned(), config);
|
||||||
section.prepare_ui(&mut renderer);
|
section.prepare_ui(&mut renderer);
|
||||||
assert_eq!(section.tokens.len(), 7);
|
assert_eq!(section.tokens.len(), 7);
|
||||||
@ -309,4 +328,40 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_texture_path() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let widget = EditorFileSection::new(path, buffer, config);
|
||||||
|
let result = widget.texture_path();
|
||||||
|
assert!(result.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_set_dest() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let mut widget = EditorFileSection::new(path, buffer, config);
|
||||||
|
let rect = Rect::new(2, 4, 6, 8);
|
||||||
|
widget.set_dest(&rect);
|
||||||
|
assert_eq!(format!("{:?}", widget.dest()), format!("{:?}", rect));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_source() {
|
||||||
|
let config = build_config();
|
||||||
|
let buffer = "".to_owned();
|
||||||
|
let path = "/example.txt".to_owned();
|
||||||
|
let mut widget = EditorFileSection::new(path, buffer, config);
|
||||||
|
let rect = Rect::new(2, 4, 6, 8);
|
||||||
|
widget.set_source(&rect);
|
||||||
|
assert_eq!(format!("{:?}", widget.source()), format!("{:?}", rect));
|
||||||
|
assert_eq!(
|
||||||
|
format!("{:?}", widget.source()),
|
||||||
|
format!("{:?}", widget.dest())
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ pub struct EditorFileToken {
|
|||||||
characters: Vec<TextCharacter>,
|
characters: Vec<TextCharacter>,
|
||||||
token_type: TokenType,
|
token_type: TokenType,
|
||||||
config: Arc<RwLock<Config>>,
|
config: Arc<RwLock<Config>>,
|
||||||
|
dest: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorFileToken {
|
impl EditorFileToken {
|
||||||
@ -23,6 +24,7 @@ impl EditorFileToken {
|
|||||||
characters: vec![],
|
characters: vec![],
|
||||||
token_type: token_type.clone(),
|
token_type: token_type.clone(),
|
||||||
config,
|
config,
|
||||||
|
dest: Rect::new(0, 0, 0, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,22 +134,68 @@ impl TextCollection for EditorFileToken {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorFileToken {
|
impl Widget for EditorFileToken {
|
||||||
|
fn texture_path(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
||||||
|
for text_character in self.characters.iter_mut() {
|
||||||
|
text_character.update(ticks, context);
|
||||||
|
}
|
||||||
|
self.set_dest(&self.full_rect());
|
||||||
|
UR::NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UR {
|
||||||
|
for text_character in self.characters.iter_mut() {
|
||||||
|
if text_character.is_left_click_target(point, context) {
|
||||||
|
return text_character.on_left_click(point, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UR::NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
||||||
|
for text_character in self.characters.iter() {
|
||||||
|
if text_character.is_left_click_target(point, context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Must first create targets so even if new line appear renderer will know
|
* Must first create targets so even if new line appear renderer will know
|
||||||
* where move render starting point
|
* where move render starting point
|
||||||
*/
|
*/
|
||||||
pub fn render<R, C>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
where
|
where
|
||||||
R: Renderer + ConfigHolder,
|
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
for text_character in self.characters.iter() {
|
for text_character in self.characters.iter() {
|
||||||
text_character.render(canvas, renderer, context);
|
text_character.render(canvas, renderer, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||||
where
|
where
|
||||||
R: ConfigHolder + CharacterSizeManager + Renderer,
|
R: ConfigHolder + CharacterSizeManager + Renderer,
|
||||||
{
|
{
|
||||||
@ -172,35 +220,6 @@ impl EditorFileToken {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Update for EditorFileToken {
|
|
||||||
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
|
||||||
for text_character in self.characters.iter_mut() {
|
|
||||||
text_character.update(ticks, context);
|
|
||||||
}
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClickHandler for EditorFileToken {
|
|
||||||
fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UR {
|
|
||||||
for text_character in self.characters.iter_mut() {
|
|
||||||
if text_character.is_left_click_target(point, context) {
|
|
||||||
return text_character.on_left_click(point, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
|
||||||
for text_character in self.characters.iter() {
|
|
||||||
if text_character.is_left_click_target(point, context) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EditorFileTokenIterator<'a> {
|
pub struct EditorFileTokenIterator<'a> {
|
||||||
editor_file_token: &'a EditorFileToken,
|
editor_file_token: &'a EditorFileToken,
|
||||||
@ -230,8 +249,8 @@ impl<'a> std::iter::Iterator for EditorFileTokenIterator<'a> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support::build_config;
|
|
||||||
use crate::tests::support::CanvasMock;
|
use crate::tests::*;
|
||||||
use rider_lexers::Token;
|
use rider_lexers::Token;
|
||||||
use sdl2::pixels::PixelFormatEnum;
|
use sdl2::pixels::PixelFormatEnum;
|
||||||
use sdl2::render::Texture;
|
use sdl2::render::Texture;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use crate::app::UpdateResult as UR;
|
|
||||||
use crate::app::*;
|
use crate::app::*;
|
||||||
use crate::renderer::renderer::Renderer;
|
use crate::renderer::renderer::Renderer;
|
||||||
use crate::ui::caret::caret::Caret;
|
use crate::ui::caret::caret::Caret;
|
||||||
@ -11,20 +10,19 @@ use crate::ui::scroll_bar::horizontal_scroll_bar::*;
|
|||||||
use crate::ui::scroll_bar::vertical_scroll_bar::*;
|
use crate::ui::scroll_bar::vertical_scroll_bar::*;
|
||||||
use crate::ui::scroll_bar::ScrollWidget;
|
use crate::ui::scroll_bar::ScrollWidget;
|
||||||
use crate::ui::text_character::CharacterSizeManager;
|
use crate::ui::text_character::CharacterSizeManager;
|
||||||
use crate::ui::CanvasAccess;
|
|
||||||
use crate::ui::ClickHandler;
|
|
||||||
use crate::ui::RenderBox;
|
|
||||||
use crate::ui::RenderContext;
|
use crate::ui::RenderContext;
|
||||||
use crate::ui::Update;
|
|
||||||
use crate::ui::UpdateContext;
|
use crate::ui::UpdateContext;
|
||||||
use crate::ui::{move_render_point, ScrollView};
|
use crate::ui::{move_render_point, ScrollView};
|
||||||
|
use crate::ui::{CanvasAccess, Widget};
|
||||||
use sdl2::rect::Point;
|
use sdl2::rect::Point;
|
||||||
use sdl2::rect::Rect;
|
use sdl2::rect::Rect;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
|
|
||||||
pub trait FileAccess {
|
pub trait FileAccess {
|
||||||
fn has_file(&self) -> bool;
|
fn has_file(&self) -> bool {
|
||||||
|
self.file().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
fn file(&self) -> Option<&EditorFile>;
|
fn file(&self) -> Option<&EditorFile>;
|
||||||
|
|
||||||
@ -34,17 +32,55 @@ pub trait FileAccess {
|
|||||||
|
|
||||||
fn drop_file(&mut self) -> Option<EditorFile>;
|
fn drop_file(&mut self) -> Option<EditorFile>;
|
||||||
|
|
||||||
fn replace_current_file(&mut self, file: EditorFile);
|
fn replace_current_file(&mut self, file: EditorFile) {
|
||||||
|
self.open_file(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CaretAccess {
|
pub trait CaretAccess: FileAccess {
|
||||||
fn caret(&self) -> &Caret;
|
fn caret(&self) -> &Caret;
|
||||||
|
|
||||||
fn caret_mut(&mut self) -> &mut Caret;
|
fn caret_mut(&mut self) -> &mut Caret;
|
||||||
|
|
||||||
fn move_caret(&mut self, dir: MoveDirection);
|
fn move_caret(&mut self, dir: MoveDirection) {
|
||||||
|
match dir {
|
||||||
|
MoveDirection::Left => caret_manager::move_caret_left(self),
|
||||||
|
MoveDirection::Right => caret_manager::move_caret_right(self),
|
||||||
|
MoveDirection::Up => caret_manager::move_caret_up(self),
|
||||||
|
MoveDirection::Down => caret_manager::move_caret_down(self),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn set_caret_to_end_of_line(&mut self, line: i32);
|
fn set_caret_to_end_of_line(&mut self, line: i32) {
|
||||||
|
let file = match self.file_mut() {
|
||||||
|
Some(f) => f,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let mut line = line;
|
||||||
|
while line >= 0 {
|
||||||
|
match file.get_last_at_line(line.clone() as usize) {
|
||||||
|
Some(text_character) => {
|
||||||
|
let rect = text_character.dest();
|
||||||
|
let position =
|
||||||
|
CaretPosition::new(text_character.position() + 1, line as usize, 0);
|
||||||
|
let p = if text_character.is_new_line() {
|
||||||
|
file.get_character_at(text_character.position() + 1)
|
||||||
|
.map_or_else(
|
||||||
|
|| text_character.dest().top_left(),
|
||||||
|
|tc| tc.dest().top_left(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
rect.top_right()
|
||||||
|
};
|
||||||
|
self.caret_mut().move_caret(position, p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
line -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FileEditor {
|
pub struct FileEditor {
|
||||||
@ -57,9 +93,144 @@ pub struct FileEditor {
|
|||||||
horizontal_scroll_bar: HorizontalScrollBar,
|
horizontal_scroll_bar: HorizontalScrollBar,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Widget for FileEditor {
|
||||||
|
fn texture_path(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, _rect: &Rect) {}
|
||||||
|
|
||||||
|
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UpdateResult {
|
||||||
|
let (width, height, editor_left_margin, editor_top_margin, scroll_width, scroll_margin) = {
|
||||||
|
let config: RwLockReadGuard<Config> = self.config.read().unwrap();
|
||||||
|
(
|
||||||
|
config.width(),
|
||||||
|
config.height(),
|
||||||
|
config.editor_left_margin() as u32,
|
||||||
|
config.editor_top_margin() as u32,
|
||||||
|
config.scroll().width(),
|
||||||
|
config.scroll().margin_right(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let editor_left_margin = match context {
|
||||||
|
UpdateContext::ParentPosition(p) => p.x() as u32,
|
||||||
|
_ => editor_left_margin as u32,
|
||||||
|
};
|
||||||
|
self.dest.set_x(editor_left_margin.clone() as i32);
|
||||||
|
self.dest.set_width(width - editor_left_margin);
|
||||||
|
self.dest.set_height(height - editor_top_margin);
|
||||||
|
|
||||||
|
self.vertical_scroll_bar
|
||||||
|
.set_full_size(self.full_rect.height());
|
||||||
|
self.vertical_scroll_bar.set_viewport(self.dest.height());
|
||||||
|
self.vertical_scroll_bar
|
||||||
|
.set_location(self.dest.width() as i32 - (scroll_width as i32 + scroll_margin));
|
||||||
|
self.vertical_scroll_bar.update(ticks, context);
|
||||||
|
|
||||||
|
self.horizontal_scroll_bar
|
||||||
|
.set_full_size(self.full_rect.width());
|
||||||
|
self.horizontal_scroll_bar.set_viewport(self.dest.width());
|
||||||
|
self.horizontal_scroll_bar
|
||||||
|
.set_location(self.dest.height() as i32 - (scroll_width as i32 + scroll_margin));
|
||||||
|
self.horizontal_scroll_bar.update(ticks, context);
|
||||||
|
|
||||||
|
self.caret.update(ticks, context);
|
||||||
|
match self.file_mut() {
|
||||||
|
Some(file) => file.update(ticks, context),
|
||||||
|
_ => UpdateResult::NoOp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_left_click(&mut self, point: &Point, _context: &UpdateContext) -> UpdateResult {
|
||||||
|
let it = match self.file() {
|
||||||
|
Some(f) => f.iter_char(),
|
||||||
|
_ => return UpdateResult::NoOp,
|
||||||
|
};
|
||||||
|
let scroll = self.scroll();
|
||||||
|
let render_point = self.render_start_point();
|
||||||
|
let moved_by = self.scroll().offset(render_point.x(), render_point.y());
|
||||||
|
let scroll_context = UpdateContext::ScrolledBy(moved_by.clone());
|
||||||
|
let mut target: Option<(Point, CaretPosition)> = None;
|
||||||
|
for char in it {
|
||||||
|
if char.is_left_click_target(point, &scroll_context) {
|
||||||
|
let position = CaretPosition::new(char.position(), char.line(), 0);
|
||||||
|
let point = char.dest().top_left();
|
||||||
|
target = Some((point, position));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some((point, position)) = target {
|
||||||
|
self.caret.move_caret(position, point);
|
||||||
|
} else {
|
||||||
|
self.set_caret_to_end_of_line(
|
||||||
|
self.resolve_line_from_point(&point.offset(-scroll.x(), -scroll.y())),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
UpdateResult::NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_left_click_target(&self, point: &Point, _context: &UpdateContext) -> bool {
|
||||||
|
self.is_text_character_clicked(point) || self.is_editor_clicked(point)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_clipping(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, _context: &RenderContext)
|
||||||
|
where
|
||||||
|
C: CanvasAccess,
|
||||||
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
|
{
|
||||||
|
if self.use_clipping() {
|
||||||
|
canvas.set_clipping(self.dest.clone());
|
||||||
|
}
|
||||||
|
match self.file() {
|
||||||
|
Some(file) => file.render(
|
||||||
|
canvas,
|
||||||
|
renderer,
|
||||||
|
&RenderContext::ParentPosition(self.render_start_point() + self.scroll()),
|
||||||
|
),
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
self.caret.render(
|
||||||
|
canvas,
|
||||||
|
renderer,
|
||||||
|
&RenderContext::ParentPosition(self.render_start_point() + self.scroll()),
|
||||||
|
);
|
||||||
|
self.vertical_scroll_bar
|
||||||
|
.render(canvas, &RenderContext::ParentPosition(self.dest.top_left()));
|
||||||
|
self.horizontal_scroll_bar
|
||||||
|
.render(canvas, &RenderContext::ParentPosition(self.dest.top_left()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_ui<T>(&mut self, renderer: &mut T)
|
||||||
|
where
|
||||||
|
T: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
|
{
|
||||||
|
if let Some(ref mut file) = self.file {
|
||||||
|
file.prepare_ui(renderer);
|
||||||
|
}
|
||||||
|
self.caret.prepare_ui(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FileEditor {
|
impl FileEditor {
|
||||||
pub fn new(config: ConfigAccess) -> Self {
|
pub fn new(config: ConfigAccess) -> Self {
|
||||||
let dest = {
|
Self {
|
||||||
|
dest: {
|
||||||
let c = config.read().unwrap();
|
let c = config.read().unwrap();
|
||||||
Rect::new(
|
Rect::new(
|
||||||
c.editor_left_margin(),
|
c.editor_left_margin(),
|
||||||
@ -67,9 +238,7 @@ impl FileEditor {
|
|||||||
c.width() - c.editor_left_margin() as u32,
|
c.width() - c.editor_left_margin() as u32,
|
||||||
c.height() - c.editor_top_margin() as u32,
|
c.height() - c.editor_top_margin() as u32,
|
||||||
)
|
)
|
||||||
};
|
},
|
||||||
Self {
|
|
||||||
dest,
|
|
||||||
full_rect: Rect::new(0, 0, 0, 0),
|
full_rect: Rect::new(0, 0, 0, 0),
|
||||||
caret: Caret::new(Arc::clone(&config)),
|
caret: Caret::new(Arc::clone(&config)),
|
||||||
vertical_scroll_bar: VerticalScrollBar::new(Arc::clone(&config)),
|
vertical_scroll_bar: VerticalScrollBar::new(Arc::clone(&config)),
|
||||||
@ -115,14 +284,25 @@ impl FileEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_text_character_clicked(&self, point: &Point) -> bool {
|
fn is_text_character_clicked(&self, point: &Point) -> bool {
|
||||||
let context = UpdateContext::ParentPosition(self.render_start_point());
|
let file = match self.file() {
|
||||||
self.file()
|
Some(f) => f,
|
||||||
.map_or(false, |file| file.is_left_click_target(point, &context))
|
_ => return false,
|
||||||
|
};
|
||||||
|
let moved_by = self
|
||||||
|
.scroll()
|
||||||
|
.offset(self.render_start_point().x(), self.render_start_point().y());
|
||||||
|
let scroll_context = UpdateContext::ScrolledBy(moved_by.clone());
|
||||||
|
for char in file.iter_char() {
|
||||||
|
if char.is_left_click_target(point, &scroll_context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_editor_clicked(&self, point: &Point) -> bool {
|
fn is_editor_clicked(&self, point: &Point) -> bool {
|
||||||
self.dest
|
self.dest()
|
||||||
.contains_point(move_render_point(point.clone(), &self.dest).top_left())
|
.contains_point(move_render_point(point.clone(), self.dest()).top_left())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_line_from_point(&self, point: &Point) -> i32 {
|
fn resolve_line_from_point(&self, point: &Point) -> i32 {
|
||||||
@ -130,11 +310,12 @@ impl FileEditor {
|
|||||||
Some(f) => f,
|
Some(f) => f,
|
||||||
_ => return 0,
|
_ => return 0,
|
||||||
};
|
};
|
||||||
let mut y = point.y() - self.render_start_point().y();
|
let y = point.y() - self.render_start_point().y();
|
||||||
if y < 0 {
|
match (y, file.line_height()) {
|
||||||
y = 0;
|
(y, _) if y <= 0 => 0,
|
||||||
|
(_, 0) => 0,
|
||||||
|
(_, line_height) => y / (line_height as i32),
|
||||||
}
|
}
|
||||||
y / (file.line_height() as i32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,10 +338,6 @@ impl ScrollView<VerticalScrollBar, HorizontalScrollBar> for FileEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FileAccess for FileEditor {
|
impl FileAccess for FileEditor {
|
||||||
fn has_file(&self) -> bool {
|
|
||||||
self.file.is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn file(&self) -> Option<&EditorFile> {
|
fn file(&self) -> Option<&EditorFile> {
|
||||||
self.file.as_ref()
|
self.file.as_ref()
|
||||||
}
|
}
|
||||||
@ -172,8 +349,8 @@ impl FileAccess for FileEditor {
|
|||||||
fn open_file(&mut self, file: EditorFile) -> Option<EditorFile> {
|
fn open_file(&mut self, file: EditorFile) -> Option<EditorFile> {
|
||||||
let new_path = file.path();
|
let new_path = file.path();
|
||||||
let mut file = Some(file);
|
let mut file = Some(file);
|
||||||
let old_path = match self.file {
|
let old_path = match self.file() {
|
||||||
Some(ref f) => f.path(),
|
Some(f) => f.path(),
|
||||||
_ => format!(""),
|
_ => format!(""),
|
||||||
};
|
};
|
||||||
mem::swap(&mut self.file, &mut file);
|
mem::swap(&mut self.file, &mut file);
|
||||||
@ -196,10 +373,6 @@ impl FileAccess for FileEditor {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_current_file(&mut self, file: EditorFile) {
|
|
||||||
self.open_file(file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CaretAccess for FileEditor {
|
impl CaretAccess for FileEditor {
|
||||||
@ -210,160 +383,6 @@ impl CaretAccess for FileEditor {
|
|||||||
fn caret_mut(&mut self) -> &mut Caret {
|
fn caret_mut(&mut self) -> &mut Caret {
|
||||||
&mut self.caret
|
&mut self.caret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_caret(&mut self, dir: MoveDirection) {
|
|
||||||
match dir {
|
|
||||||
MoveDirection::Left => caret_manager::move_caret_left(self),
|
|
||||||
MoveDirection::Right => caret_manager::move_caret_right(self),
|
|
||||||
MoveDirection::Up => caret_manager::move_caret_up(self),
|
|
||||||
MoveDirection::Down => caret_manager::move_caret_down(self),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_caret_to_end_of_line(&mut self, line: i32) {
|
|
||||||
let file = match self.file_mut() {
|
|
||||||
Some(f) => f,
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
let mut line = line;
|
|
||||||
while line >= 0 {
|
|
||||||
match file.get_last_at_line(line.clone() as usize) {
|
|
||||||
Some(text_character) => {
|
|
||||||
let rect = text_character.dest();
|
|
||||||
let position =
|
|
||||||
CaretPosition::new(text_character.position() + 1, line as usize, 0);
|
|
||||||
let p = if text_character.is_new_line() {
|
|
||||||
file.get_character_at(text_character.position() + 1)
|
|
||||||
.map_or_else(
|
|
||||||
|| text_character.dest().top_left(),
|
|
||||||
|tc| tc.dest().top_left(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
rect.top_right()
|
|
||||||
};
|
|
||||||
self.caret.move_caret(position, p);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
line -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FileEditor {
|
|
||||||
pub fn render<R, C>(&self, canvas: &mut C, renderer: &mut R)
|
|
||||||
where
|
|
||||||
R: Renderer + ConfigHolder,
|
|
||||||
C: CanvasAccess,
|
|
||||||
{
|
|
||||||
canvas.set_clipping(self.dest.clone());
|
|
||||||
match self.file() {
|
|
||||||
Some(file) => file.render(
|
|
||||||
canvas,
|
|
||||||
renderer,
|
|
||||||
&RenderContext::ParentPosition(self.render_start_point()),
|
|
||||||
),
|
|
||||||
_ => (),
|
|
||||||
};
|
|
||||||
self.caret.render(
|
|
||||||
canvas,
|
|
||||||
&RenderContext::ParentPosition(self.render_start_point()),
|
|
||||||
);
|
|
||||||
self.vertical_scroll_bar
|
|
||||||
.render(canvas, &RenderContext::ParentPosition(self.dest.top_left()));
|
|
||||||
self.horizontal_scroll_bar
|
|
||||||
.render(canvas, &RenderContext::ParentPosition(self.dest.top_left()));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prepare_ui<T>(&mut self, renderer: &mut T)
|
|
||||||
where
|
|
||||||
T: CharacterSizeManager,
|
|
||||||
{
|
|
||||||
self.caret.prepare_ui(renderer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Update for FileEditor {
|
|
||||||
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
|
||||||
let (width, height, editor_left_margin, editor_top_margin, scroll_width, scroll_margin) = {
|
|
||||||
let config: RwLockReadGuard<Config> = self.config.read().unwrap();
|
|
||||||
(
|
|
||||||
config.width(),
|
|
||||||
config.height(),
|
|
||||||
config.editor_left_margin() as u32,
|
|
||||||
config.editor_top_margin() as u32,
|
|
||||||
config.scroll().width(),
|
|
||||||
config.scroll().margin_right(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let editor_left_margin = match context {
|
|
||||||
UpdateContext::ParentPosition(p) => p.x() as u32,
|
|
||||||
_ => editor_left_margin as u32,
|
|
||||||
};
|
|
||||||
self.dest.set_x(editor_left_margin.clone() as i32);
|
|
||||||
self.dest.set_width(width - editor_left_margin);
|
|
||||||
self.dest.set_height(height - editor_top_margin);
|
|
||||||
|
|
||||||
self.vertical_scroll_bar
|
|
||||||
.set_full_size(self.full_rect.height());
|
|
||||||
self.vertical_scroll_bar.set_viewport(self.dest.height());
|
|
||||||
self.vertical_scroll_bar
|
|
||||||
.set_location(self.dest.width() as i32 - (scroll_width as i32 + scroll_margin));
|
|
||||||
self.vertical_scroll_bar.update(ticks, context);
|
|
||||||
|
|
||||||
self.horizontal_scroll_bar
|
|
||||||
.set_full_size(self.full_rect.width());
|
|
||||||
self.horizontal_scroll_bar.set_viewport(self.dest.width());
|
|
||||||
self.horizontal_scroll_bar
|
|
||||||
.set_location(self.dest.height() as i32 - (scroll_width as i32 + scroll_margin));
|
|
||||||
self.horizontal_scroll_bar.update(ticks, context);
|
|
||||||
|
|
||||||
self.caret.update();
|
|
||||||
match self.file_mut() {
|
|
||||||
Some(file) => file.update(ticks, context),
|
|
||||||
_ => UR::NoOp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClickHandler for FileEditor {
|
|
||||||
fn on_left_click(&mut self, point: &Point, _context: &UpdateContext) -> UR {
|
|
||||||
let context = UpdateContext::ParentPosition(self.render_start_point());
|
|
||||||
|
|
||||||
if self.is_text_character_clicked(point) {
|
|
||||||
let file = if let Some(file) = self.file_mut() {
|
|
||||||
file
|
|
||||||
} else {
|
|
||||||
return UR::NoOp;
|
|
||||||
};
|
|
||||||
match file.on_left_click(point, &context) {
|
|
||||||
UR::MoveCaret(rect, position) => {
|
|
||||||
self.caret
|
|
||||||
.move_caret(position, Point::new(rect.x(), rect.y()));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.set_caret_to_end_of_line(self.resolve_line_from_point(point));
|
|
||||||
}
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_left_click_target(&self, point: &Point, _context: &UpdateContext) -> bool {
|
|
||||||
self.is_text_character_clicked(point) || self.is_editor_clicked(point)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RenderBox for FileEditor {
|
|
||||||
fn render_start_point(&self) -> Point {
|
|
||||||
self.dest.top_left() + self.scroll()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dest(&self) -> Rect {
|
|
||||||
self.dest.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigHolder for FileEditor {
|
impl ConfigHolder for FileEditor {
|
||||||
@ -374,57 +393,15 @@ impl ConfigHolder for FileEditor {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::app::UpdateResult;
|
||||||
|
use crate::tests::*;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
use rider_config::Config;
|
use rider_config::{Config, ConfigHolder};
|
||||||
use std::sync::*;
|
use rider_derive::*;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn replace_file() {
|
|
||||||
let config = Arc::new(RwLock::new(Config::new()));
|
|
||||||
let mut editor = FileEditor::new(Arc::clone(&config));
|
|
||||||
let first_file =
|
|
||||||
EditorFile::new("./foo.txt".to_string(), "foo".to_string(), config.clone());
|
|
||||||
let second_file =
|
|
||||||
EditorFile::new("./bar.txt".to_string(), "bar".to_string(), config.clone());
|
|
||||||
editor.open_file(first_file.clone());
|
|
||||||
let result = editor.open_file(second_file.clone());
|
|
||||||
assert_eq!(result.is_some(), true);
|
|
||||||
let file = result.as_ref().unwrap();
|
|
||||||
assert_eq!(file.path(), first_file.path());
|
|
||||||
assert_eq!(file.buffer(), first_file.buffer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_config_holder {
|
|
||||||
use crate::app::*;
|
|
||||||
use crate::tests::support;
|
|
||||||
use crate::ui::*;
|
|
||||||
use std::sync::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn assert_config() {
|
|
||||||
let config = support::build_config();
|
|
||||||
let widget = FileEditor::new(Arc::clone(&config));
|
|
||||||
let result = widget.config();
|
|
||||||
{
|
|
||||||
let mut w = config.write().unwrap();
|
|
||||||
w.set_height(1240);
|
|
||||||
w.set_width(1024);
|
|
||||||
}
|
|
||||||
let local = config.read().unwrap();
|
|
||||||
let widget_config = result.read().unwrap();
|
|
||||||
assert_eq!(widget_config.width(), local.width());
|
|
||||||
assert_eq!(widget_config.height(), local.height());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_render_box {
|
|
||||||
use crate::tests::support;
|
|
||||||
use crate::ui::*;
|
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl FileEditor {
|
impl FileEditor {
|
||||||
pub fn set_full_rect(&mut self, r: Rect) {
|
pub fn set_full_rect(&mut self, r: Rect) {
|
||||||
self.full_rect = r;
|
self.full_rect = r;
|
||||||
@ -435,9 +412,19 @@ mod test_render_box {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Widget
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_texture_path() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = FileEditor::new(config);
|
||||||
|
let result = widget.texture_path();
|
||||||
|
assert!(result.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_dest() {
|
fn assert_dest() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let (x, y, mw, mh) = {
|
let (x, y, mw, mh) = {
|
||||||
let c = config.read().unwrap();
|
let c = config.read().unwrap();
|
||||||
(
|
(
|
||||||
@ -454,23 +441,300 @@ mod test_render_box {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_render_start_point() {
|
fn assert_set_dest() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let (x, y, ss) = {
|
|
||||||
let c = config.read().unwrap();
|
|
||||||
(
|
|
||||||
c.editor_left_margin(),
|
|
||||||
c.editor_top_margin(),
|
|
||||||
c.scroll().speed(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let mut widget = FileEditor::new(config);
|
let mut widget = FileEditor::new(config);
|
||||||
widget.set_dest(Rect::new(x.clone(), y.clone(), 999, 999));
|
widget.set_dest(Rect::new(100, 200, 300, 400));
|
||||||
widget.set_full_rect(Rect::new(0, 0, 99999, 99999));
|
assert_eq!(widget.dest(), &Rect::new(100, 200, 300, 400));
|
||||||
widget.update(1, &UpdateContext::Nothing);
|
}
|
||||||
widget.scroll_by(30, 40);
|
|
||||||
let result = widget.render_start_point().clone();
|
#[test]
|
||||||
let expected = Point::new(x - (ss * 30), y - (ss * 40));
|
fn assert_source() {
|
||||||
assert_eq!(result, expected);
|
let config = build_config();
|
||||||
|
let widget = FileEditor::new(config);
|
||||||
|
let result = widget.source();
|
||||||
|
assert_eq!(result, &Rect::new(10, 50, 1014, 810));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_set_source() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config);
|
||||||
|
widget.set_source(&Rect::new(1, 2, 3, 4));
|
||||||
|
assert_ne!(widget.source(), &Rect::new(1, 2, 3, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_update() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config);
|
||||||
|
let result = widget.update(0, &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, UpdateResult::NoOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_on_left_click() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config);
|
||||||
|
let result = widget.on_left_click(&Point::new(600, 800), &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, UpdateResult::NoOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_is_left_click_target() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = FileEditor::new(config);
|
||||||
|
let result = widget.is_left_click_target(&Point::new(600, 800), &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_use_clipping() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = FileEditor::new(config);
|
||||||
|
let result = widget.use_clipping();
|
||||||
|
assert_eq!(result, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_render() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut canvas = CanvasMock::new();
|
||||||
|
let widget = FileEditor::new(config);
|
||||||
|
let result = widget.render(&mut canvas, &mut renderer, &RenderContext::Nothing);
|
||||||
|
assert_eq!(result, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_prepare_ui() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut widget = FileEditor::new(config);
|
||||||
|
let result = widget.prepare_ui(&mut renderer);
|
||||||
|
assert_eq!(result, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
// File manipulation
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_has_file() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = FileEditor::new(config);
|
||||||
|
assert_eq!(widget.has_file(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn drop_file_when_no_file_is_selected() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config);
|
||||||
|
let result = widget.drop_file();
|
||||||
|
assert!(result.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn drop_file_when_file_is_selected() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
let file = EditorFile::new(
|
||||||
|
"/tmp/drop_file_when_file_is_selected".to_owned(),
|
||||||
|
"foo bar".to_owned(),
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
widget.open_file(file);
|
||||||
|
let result = widget.drop_file();
|
||||||
|
assert!(result.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mut_file_when_no_file_is_selected() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config);
|
||||||
|
let result = widget.file_mut();
|
||||||
|
assert!(result.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mut_file_when_file_is_selected() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
let file = EditorFile::new(
|
||||||
|
"/tmp/drop_file_when_file_is_selected".to_owned(),
|
||||||
|
"foo bar".to_owned(),
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
widget.open_file(file);
|
||||||
|
let result = widget.file_mut();
|
||||||
|
assert!(result.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn file_when_no_file_is_selected() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = FileEditor::new(config);
|
||||||
|
let result = widget.file();
|
||||||
|
assert!(result.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn file_when_file_is_selected() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
let file = EditorFile::new(
|
||||||
|
"/tmp/drop_file_when_file_is_selected".to_owned(),
|
||||||
|
"foo bar".to_owned(),
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
widget.open_file(file);
|
||||||
|
let result = widget.file();
|
||||||
|
assert!(result.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn replace_file() {
|
||||||
|
let config = Arc::new(RwLock::new(Config::new()));
|
||||||
|
let mut editor = FileEditor::new(Arc::clone(&config));
|
||||||
|
let first_file =
|
||||||
|
EditorFile::new("./foo.txt".to_string(), "foo".to_string(), config.clone());
|
||||||
|
let second_file =
|
||||||
|
EditorFile::new("./bar.txt".to_string(), "bar".to_string(), config.clone());
|
||||||
|
editor.open_file(first_file.clone());
|
||||||
|
let result = editor.open_file(second_file.clone());
|
||||||
|
assert_eq!(result.is_some(), true);
|
||||||
|
let file = result.as_ref().unwrap();
|
||||||
|
assert_eq!(file.path(), first_file.path());
|
||||||
|
assert_eq!(file.buffer(), first_file.buffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
// config
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_config() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = FileEditor::new(config.clone());
|
||||||
|
assert!(widget
|
||||||
|
.config()
|
||||||
|
.write()
|
||||||
|
.and_then(|ref mut w| {
|
||||||
|
w.set_height(1240);
|
||||||
|
w.set_width(1024);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.is_ok());
|
||||||
|
let local: (u32, u32) = config
|
||||||
|
.read()
|
||||||
|
.map_or_else(|_| (0, 0), |ref w| (w.width(), w.height()));
|
||||||
|
let widget_config: (u32, u32) = widget
|
||||||
|
.config()
|
||||||
|
.read()
|
||||||
|
.map_or_else(|_| (0, 0), |ref w| (w.width(), w.height()));
|
||||||
|
assert_eq!(widget_config, local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod own_methods_tests {
|
||||||
|
use crate::tests::*;
|
||||||
|
use crate::ui::{CaretAccess, EditorFile, FileAccess, FileEditor};
|
||||||
|
use rider_config::ConfigAccess;
|
||||||
|
use rider_derive::*;
|
||||||
|
use sdl2::rect::Point;
|
||||||
|
|
||||||
|
fn build_testable_file<S>(buffer: S, config: ConfigAccess) -> EditorFile
|
||||||
|
where
|
||||||
|
S: Into<String> + Sized,
|
||||||
|
{
|
||||||
|
EditorFile::new(
|
||||||
|
"/tmp/drop_file_when_file_is_selected".to_owned(),
|
||||||
|
buffer.into(),
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn delete_front() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
widget.open_file(build_testable_file("foo bar", config));
|
||||||
|
widget.caret_mut().set_text_position(1);
|
||||||
|
widget.delete_front(&mut renderer);
|
||||||
|
let buffer = widget
|
||||||
|
.file()
|
||||||
|
.map_or_else(|| "".to_owned(), |ref f| f.buffer());
|
||||||
|
assert_eq!(buffer, "oo bar".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn delete_back() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
widget.open_file(build_testable_file("foo bar", config));
|
||||||
|
widget.caret_mut().set_text_position(6);
|
||||||
|
widget.delete_back(&mut renderer);
|
||||||
|
let buffer = widget
|
||||||
|
.file()
|
||||||
|
.map_or_else(|| "".to_owned(), |ref f| f.buffer());
|
||||||
|
assert_eq!(buffer, "foo ba".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn insert_text() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
widget.open_file(build_testable_file("foo bar", config));
|
||||||
|
widget.insert_text("hello world ".to_owned(), &mut renderer);
|
||||||
|
let buffer = widget
|
||||||
|
.file()
|
||||||
|
.map_or_else(|| "".to_owned(), |ref f| f.buffer());
|
||||||
|
assert_eq!(buffer, "hello world foo bar".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn insert_new_line() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
widget.open_file(build_testable_file("foo bar", config));
|
||||||
|
assert!(widget.insert_new_line(&mut renderer).is_ok());
|
||||||
|
let buffer = widget
|
||||||
|
.file()
|
||||||
|
.map_or_else(|| "".to_owned(), |ref f| f.buffer());
|
||||||
|
assert_eq!(buffer, "\nfoo bar".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn delete_current_line() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
widget.open_file(build_testable_file("foo bar\nfoz baz", config));
|
||||||
|
assert!(widget.delete_current_line(&mut renderer).is_ok());
|
||||||
|
let buffer = widget
|
||||||
|
.file()
|
||||||
|
.map_or_else(|| "".to_owned(), |ref f| f.buffer());
|
||||||
|
assert_eq!(buffer, "foz baz");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn is_text_character_clicked() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
widget.open_file(build_testable_file("foo bar", config));
|
||||||
|
assert_eq!(
|
||||||
|
widget.is_text_character_clicked(&Point::new(1000, 1000)),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn is_editor_clicked() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
widget.open_file(build_testable_file("foo bar", config));
|
||||||
|
assert_eq!(widget.is_editor_clicked(&Point::new(1000, 1000)), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resolve_line_from_point() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = FileEditor::new(config.clone());
|
||||||
|
widget.open_file(build_testable_file("foo bar", config));
|
||||||
|
assert_eq!(widget.resolve_line_from_point(&Point::new(100, 100)), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ impl Widget for DirectoryView {
|
|||||||
|
|
||||||
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
{
|
{
|
||||||
let mut dest = move_render_point(
|
let mut dest = move_render_point(
|
||||||
@ -185,7 +185,7 @@ impl Widget for DirectoryView {
|
|||||||
|
|
||||||
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
let size = renderer.load_character_size('W');
|
let size = renderer.load_character_size('W');
|
||||||
self.icon.prepare_ui(renderer);
|
self.icon.prepare_ui(renderer);
|
||||||
@ -271,7 +271,7 @@ impl DirectoryView {
|
|||||||
|
|
||||||
pub fn open_directory<R>(&mut self, dir_path: String, renderer: &mut R) -> bool
|
pub fn open_directory<R>(&mut self, dir_path: String, renderer: &mut R) -> bool
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
match dir_path {
|
match dir_path {
|
||||||
_ if dir_path == self.path => {
|
_ if dir_path == self.path => {
|
||||||
@ -343,7 +343,7 @@ impl DirectoryView {
|
|||||||
|
|
||||||
fn read_directory<R>(&mut self, renderer: &mut R)
|
fn read_directory<R>(&mut self, renderer: &mut R)
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
let entries: fs::ReadDir = match fs::read_dir(self.path.clone()) {
|
let entries: fs::ReadDir = match fs::read_dir(self.path.clone()) {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
@ -387,7 +387,7 @@ impl DirectoryView {
|
|||||||
fn render_children<C, R>(&self, canvas: &mut C, renderer: &mut R, dest: &mut Rect)
|
fn render_children<C, R>(&self, canvas: &mut C, renderer: &mut R, dest: &mut Rect)
|
||||||
where
|
where
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
if !self.expanded {
|
if !self.expanded {
|
||||||
return;
|
return;
|
||||||
@ -447,10 +447,9 @@ impl ConfigHolder for DirectoryView {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support::CanvasMock;
|
use crate::tests::*;
|
||||||
use crate::tests::support::SimpleRendererMock;
|
|
||||||
use crate::tests::support::{build_config, build_path};
|
|
||||||
use crate::ui::Widget;
|
use crate::ui::Widget;
|
||||||
|
use rider_derive::*;
|
||||||
|
|
||||||
//##########################################################
|
//##########################################################
|
||||||
// name_width
|
// name_width
|
||||||
@ -465,8 +464,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_name_width() {
|
fn assert_prepared_name_width() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.name_width(), 39);
|
assert_eq!(widget.name_width(), 39);
|
||||||
@ -485,8 +483,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_icon_width() {
|
fn assert_prepared_icon_width() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.icon_width(), 14);
|
assert_eq!(widget.icon_width(), 14);
|
||||||
@ -505,8 +502,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_height() {
|
fn assert_prepared_height() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.height(), 14);
|
assert_eq!(widget.height(), 14);
|
||||||
@ -525,8 +521,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_name() {
|
fn assert_prepared_name() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.name(), "foo".to_owned());
|
assert_eq!(widget.name(), "foo".to_owned());
|
||||||
@ -545,8 +540,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_path() {
|
fn assert_prepared_path() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.path(), "/foo".to_owned());
|
assert_eq!(widget.path(), "/foo".to_owned());
|
||||||
@ -565,8 +559,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_source() {
|
fn assert_prepared_source() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.source(), &Rect::new(0, 0, 64, 64));
|
assert_eq!(widget.source(), &Rect::new(0, 0, 64, 64));
|
||||||
@ -585,21 +578,37 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_dest() {
|
fn assert_prepared_dest() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.dest(), &Rect::new(0, 0, 53, 14));
|
assert_eq!(widget.dest(), &Rect::new(0, 0, 53, 14));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_set_dest() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
|
let rect = Rect::new(1, 2, 3, 4);
|
||||||
|
widget.set_dest(&rect);
|
||||||
|
assert_ne!(widget.dest(), &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_set_source() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
|
let rect = Rect::new(1, 2, 3, 4);
|
||||||
|
widget.set_source(&rect);
|
||||||
|
assert_ne!(widget.source(), &rect);
|
||||||
|
}
|
||||||
|
|
||||||
//##########################################################
|
//##########################################################
|
||||||
// update
|
// update
|
||||||
//##########################################################
|
//##########################################################
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_update_when_doesnt_exists() {
|
fn assert_update_when_doesnt_exists() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -610,8 +619,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_update_when_does_exists() {
|
fn assert_update_when_does_exists() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = DirectoryView::new("/tmp".to_owned(), config);
|
let mut widget = DirectoryView::new("/tmp".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -624,8 +632,7 @@ mod tests {
|
|||||||
fn assert_update_expanded() {
|
fn assert_update_expanded() {
|
||||||
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget =
|
let mut widget =
|
||||||
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -648,8 +655,7 @@ mod tests {
|
|||||||
fn assert_render_no_expanded() {
|
fn assert_render_no_expanded() {
|
||||||
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget =
|
let mut widget =
|
||||||
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
@ -661,8 +667,7 @@ mod tests {
|
|||||||
fn assert_render_expanded() {
|
fn assert_render_expanded() {
|
||||||
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget =
|
let mut widget =
|
||||||
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
@ -683,8 +688,7 @@ mod tests {
|
|||||||
fn assert_is_left_click_target_when_target() {
|
fn assert_is_left_click_target_when_target() {
|
||||||
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -696,8 +700,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_is_left_click_target_when_target_with_parent() {
|
fn assert_is_left_click_target_when_target_with_parent() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -711,8 +714,7 @@ mod tests {
|
|||||||
fn assert_is_left_click_target_expanded() {
|
fn assert_is_left_click_target_expanded() {
|
||||||
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget =
|
let mut widget =
|
||||||
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
@ -730,8 +732,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_is_left_click_target_when_target() {
|
fn refute_is_left_click_target_when_target() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -743,8 +744,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_is_left_click_target_when_target_with_parent() {
|
fn refute_is_left_click_target_when_target_with_parent() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -762,8 +762,7 @@ mod tests {
|
|||||||
fn assert_on_left_click_when_target() {
|
fn assert_on_left_click_when_target() {
|
||||||
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget =
|
let mut widget =
|
||||||
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
@ -781,8 +780,7 @@ mod tests {
|
|||||||
fn assert_on_left_click_when_target_with_parent() {
|
fn assert_on_left_click_when_target_with_parent() {
|
||||||
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget =
|
let mut widget =
|
||||||
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
@ -800,8 +798,7 @@ mod tests {
|
|||||||
fn assert_on_left_click_expanded() {
|
fn assert_on_left_click_expanded() {
|
||||||
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget =
|
let mut widget =
|
||||||
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
@ -812,6 +809,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
widget.render(&mut canvas, &mut renderer, &RenderContext::Nothing);
|
widget.render(&mut canvas, &mut renderer, &RenderContext::Nothing);
|
||||||
|
widget.expanded = true;
|
||||||
let p = Point::new(0, 0);
|
let p = Point::new(0, 0);
|
||||||
let context = UpdateContext::ParentPosition(Point::new(0, 0));
|
let context = UpdateContext::ParentPosition(Point::new(0, 0));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -819,4 +817,64 @@ mod tests {
|
|||||||
UpdateResult::OpenDirectory("/tmp/rider-editor/directory-view-test".to_owned())
|
UpdateResult::OpenDirectory("/tmp/rider-editor/directory-view-test".to_owned())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_on_left_click_not_expanded() {
|
||||||
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut canvas = CanvasMock::new();
|
||||||
|
let mut widget =
|
||||||
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
|
widget.prepare_ui(&mut renderer);
|
||||||
|
widget.open_directory("/tmp".to_owned(), &mut renderer);
|
||||||
|
widget.open_directory("/tmp/rider-editor".to_owned(), &mut renderer);
|
||||||
|
widget.open_directory(
|
||||||
|
"/tmp/rider-editor/directory-view-test".to_owned(),
|
||||||
|
&mut renderer,
|
||||||
|
);
|
||||||
|
widget.prepare_ui(&mut renderer);
|
||||||
|
widget.render(&mut canvas, &mut renderer, &RenderContext::Nothing);
|
||||||
|
widget.expanded = false;
|
||||||
|
let p = Point::new(0, 0);
|
||||||
|
let context = UpdateContext::ParentPosition(Point::new(0, 0));
|
||||||
|
assert_eq!(
|
||||||
|
widget.on_left_click(&p, &context),
|
||||||
|
UpdateResult::OpenDirectory("/tmp/rider-editor/directory-view-test".to_owned())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_on_left_click_expanded_with_sub() {
|
||||||
|
build_path("/tmp/rider-editor/directory-view-test/foo/bar".to_owned());
|
||||||
|
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut widget =
|
||||||
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
|
widget.prepare_ui(&mut renderer);
|
||||||
|
widget.open_directory("/tmp".to_owned(), &mut renderer);
|
||||||
|
widget.open_directory("/tmp/rider-editor".to_owned(), &mut renderer);
|
||||||
|
widget.prepare_ui(&mut renderer);
|
||||||
|
widget.render(&mut canvas, &mut renderer, &RenderContext::Nothing);
|
||||||
|
|
||||||
|
let p = Point::new(0, 0);
|
||||||
|
let context = UpdateContext::ParentPosition(Point::new(0, 0));
|
||||||
|
assert_eq!(
|
||||||
|
widget.on_left_click(&p, &context),
|
||||||
|
UpdateResult::OpenDirectory("/tmp/rider-editor/directory-view-test".to_owned())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_config() {
|
||||||
|
build_path("/tmp/rider-editor/directory-view-test".to_owned());
|
||||||
|
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut canvas = CanvasMock::new();
|
||||||
|
let mut widget =
|
||||||
|
DirectoryView::new("/tmp/rider-editor/directory-view-test".to_owned(), config);
|
||||||
|
widget.prepare_ui(&mut renderer);
|
||||||
|
widget.config();
|
||||||
|
assert!(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ impl Widget for FileEntry {
|
|||||||
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
where
|
where
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
let dest = match context {
|
let dest = match context {
|
||||||
&RenderContext::ParentPosition(p) => move_render_point(p.clone(), self.dest()),
|
&RenderContext::ParentPosition(p) => move_render_point(p.clone(), self.dest()),
|
||||||
@ -82,7 +82,7 @@ impl Widget for FileEntry {
|
|||||||
|
|
||||||
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
let rect = renderer.load_character_size('W');
|
let rect = renderer.load_character_size('W');
|
||||||
self.icon.prepare_ui(renderer);
|
self.icon.prepare_ui(renderer);
|
||||||
@ -186,9 +186,9 @@ impl ConfigHolder for FileEntry {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support::build_config;
|
use crate::tests::*;
|
||||||
use crate::tests::support::CanvasMock;
|
use rider_derive::*;
|
||||||
use crate::tests::support::SimpleRendererMock;
|
|
||||||
use crate::ui::{UpdateContext, Widget};
|
use crate::ui::{UpdateContext, Widget};
|
||||||
|
|
||||||
//##########################################################
|
//##########################################################
|
||||||
@ -204,8 +204,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_name_width() {
|
fn assert_prepared_name_width() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.name_width(), 91);
|
assert_eq!(widget.name_width(), 91);
|
||||||
@ -224,8 +223,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_icon_width() {
|
fn assert_prepared_icon_width() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.icon_width(), 14);
|
assert_eq!(widget.icon_width(), 14);
|
||||||
@ -244,8 +242,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_height() {
|
fn assert_prepared_height() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.height(), 16);
|
assert_eq!(widget.height(), 16);
|
||||||
@ -264,8 +261,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_name() {
|
fn assert_prepared_name() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.name(), "bar.txt".to_owned());
|
assert_eq!(widget.name(), "bar.txt".to_owned());
|
||||||
@ -284,8 +280,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_path() {
|
fn assert_prepared_path() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.path(), "/foo".to_owned());
|
assert_eq!(widget.path(), "/foo".to_owned());
|
||||||
@ -304,8 +299,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_source() {
|
fn assert_prepared_source() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.source(), &Rect::new(0, 0, 64, 64));
|
assert_eq!(widget.source(), &Rect::new(0, 0, 64, 64));
|
||||||
@ -324,8 +318,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_dest() {
|
fn assert_prepared_dest() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.dest(), &Rect::new(0, 0, 105, 16));
|
assert_eq!(widget.dest(), &Rect::new(0, 0, 105, 16));
|
||||||
@ -344,8 +337,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepared_full_dest() {
|
fn assert_prepared_full_dest() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(widget.full_dest(), Rect::new(0, 0, 125, 16));
|
assert_eq!(widget.full_dest(), Rect::new(0, 0, 125, 16));
|
||||||
@ -357,8 +349,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_update_when_doesnt_exists() {
|
fn assert_update_when_doesnt_exists() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -369,8 +360,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_update_when_does_exists() {
|
fn assert_update_when_does_exists() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/tmp".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/tmp".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -385,8 +375,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_render() {
|
fn assert_render() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -400,8 +389,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_is_left_click_target_when_target() {
|
fn assert_is_left_click_target_when_target() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -413,8 +401,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_is_left_click_target_when_target_with_parent() {
|
fn assert_is_left_click_target_when_target_with_parent() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -426,8 +413,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_is_left_click_target_when_target() {
|
fn refute_is_left_click_target_when_target() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
@ -439,8 +425,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_is_left_click_target_when_target_with_parent() {
|
fn refute_is_left_click_target_when_target_with_parent() {
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
|
@ -70,13 +70,13 @@ impl Widget for Icon {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app::UpdateResult;
|
use crate::app::UpdateResult;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use crate::ui::UpdateContext;
|
use crate::ui::UpdateContext;
|
||||||
use sdl2::rect::Point;
|
use sdl2::rect::Point;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_noop_on_left_click() {
|
fn must_return_noop_on_left_click() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let dest = Rect::new(0, 10, 20, 30);
|
let dest = Rect::new(0, 10, 20, 30);
|
||||||
let src = Rect::new(40, 50, 60, 70);
|
let src = Rect::new(40, 50, 60, 70);
|
||||||
let path = "/foo/bar.png".to_owned();
|
let path = "/foo/bar.png".to_owned();
|
||||||
@ -89,7 +89,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_use_inner() {
|
fn must_use_inner() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let dest = Rect::new(0, 10, 20, 30);
|
let dest = Rect::new(0, 10, 20, 30);
|
||||||
let src = Rect::new(40, 50, 60, 70);
|
let src = Rect::new(40, 50, 60, 70);
|
||||||
let path = "/foo/bar.png".to_owned();
|
let path = "/foo/bar.png".to_owned();
|
||||||
|
@ -54,7 +54,7 @@ impl Widget for Label {
|
|||||||
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
where
|
where
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
R: Renderer,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
let dest = match context {
|
let dest = match context {
|
||||||
&RenderContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest),
|
&RenderContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest),
|
||||||
@ -62,7 +62,9 @@ impl Widget for Label {
|
|||||||
};
|
};
|
||||||
let mut d = dest.clone();
|
let mut d = dest.clone();
|
||||||
d.set_x(dest.x() + NAME_MARGIN);
|
d.set_x(dest.x() + NAME_MARGIN);
|
||||||
|
if self.use_clipping() {
|
||||||
canvas.set_clipping(d.clone());
|
canvas.set_clipping(d.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let font_details = build_font_details(self);
|
let font_details = build_font_details(self);
|
||||||
for c in self.name.chars() {
|
for c in self.name.chars() {
|
||||||
@ -147,13 +149,14 @@ impl ConfigHolder for Label {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app::UpdateResult;
|
use crate::app::UpdateResult;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use crate::ui::{UpdateContext, Widget};
|
use crate::ui::{UpdateContext, Widget};
|
||||||
|
use rider_derive::*;
|
||||||
use sdl2::rect::Point;
|
use sdl2::rect::Point;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_noop_on_left_click() {
|
fn must_return_noop_on_left_click() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let name = "Hello world".to_owned();
|
let name = "Hello world".to_owned();
|
||||||
let mut widget = Label::new(name, config);
|
let mut widget = Label::new(name, config);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -164,8 +167,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_use_inner() {
|
fn must_use_inner() {
|
||||||
let config = support::build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = support::SimpleRendererMock::new(config.clone());
|
|
||||||
let name = "Hello world".to_owned();
|
let name = "Hello world".to_owned();
|
||||||
let mut widget = Label::new(name.clone(), config);
|
let mut widget = Label::new(name.clone(), config);
|
||||||
let dest = Rect::new(0, 0, DEST_WIDTH, DEST_HEIGHT);
|
let dest = Rect::new(0, 0, DEST_WIDTH, DEST_HEIGHT);
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use crate::app::UpdateResult as UR;
|
use crate::app::UpdateResult as UR;
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
use rider_config::ConfigAccess;
|
use rider_config::{ConfigAccess, ConfigHolder};
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
|
||||||
const SAVE_BUTTON_OFFSET_LEFT: i32 = 16;
|
pub const SAVE_BUTTON_OFFSET_LEFT: i32 = 16;
|
||||||
const SAVE_BUTTON_OFFSET_TOP: i32 = 10;
|
pub const SAVE_BUTTON_OFFSET_TOP: i32 = 10;
|
||||||
|
|
||||||
pub struct MenuBar {
|
pub struct MenuBar {
|
||||||
border_color: Color,
|
border_color: Color,
|
||||||
@ -45,7 +45,7 @@ impl MenuBar {
|
|||||||
pub fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
pub fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
where
|
where
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
use std::borrow::*;
|
use std::borrow::*;
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ impl MenuBar {
|
|||||||
move_render_point(relative_position.clone(), &self.dest),
|
move_render_point(relative_position.clone(), &self.dest),
|
||||||
self.background_color.clone(),
|
self.background_color.clone(),
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|_| panic!("Failed to draw main menu background"));
|
.expect("Failed to draw main menu background");
|
||||||
canvas
|
canvas
|
||||||
.render_border(
|
.render_border(
|
||||||
match context.borrow() {
|
match context.borrow() {
|
||||||
@ -69,7 +69,7 @@ impl MenuBar {
|
|||||||
},
|
},
|
||||||
self.border_color.clone(),
|
self.border_color.clone(),
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|_| panic!("Failed to draw main menu background"));
|
.expect("Failed to draw main menu background");
|
||||||
|
|
||||||
self.save_button.render(
|
self.save_button.render(
|
||||||
canvas,
|
canvas,
|
||||||
@ -158,7 +158,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_background_color() {
|
fn assert_background_color() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = MenuBar::new(Arc::clone(&config));
|
let widget = MenuBar::new(Arc::clone(&config));
|
||||||
let result = widget.background_color().clone();
|
let result = widget.background_color().clone();
|
||||||
let expected = Color::RGBA(18, 18, 18, 0);
|
let expected = Color::RGBA(18, 18, 18, 0);
|
||||||
@ -167,7 +167,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_dest() {
|
fn assert_dest() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let (w, h) = {
|
let (w, h) = {
|
||||||
let c = config.read().unwrap();
|
let c = config.read().unwrap();
|
||||||
(c.width() as u32, c.menu_height() as u32)
|
(c.width() as u32, c.menu_height() as u32)
|
||||||
@ -188,7 +188,7 @@ mod test_render_box {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_top_left_point() {
|
fn must_return_top_left_point() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = MenuBar::new(Arc::clone(&config));
|
let widget = MenuBar::new(Arc::clone(&config));
|
||||||
let result = widget.render_start_point();
|
let result = widget.render_start_point();
|
||||||
let expected = Point::new(0, 0);
|
let expected = Point::new(0, 0);
|
||||||
@ -206,7 +206,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_when_not_click_target() {
|
fn refute_when_not_click_target() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = MenuBar::new(Arc::clone(&config));
|
let widget = MenuBar::new(Arc::clone(&config));
|
||||||
let point = Point::new(9999, 9999);
|
let point = Point::new(9999, 9999);
|
||||||
let context = UpdateContext::Nothing;
|
let context = UpdateContext::Nothing;
|
||||||
@ -216,7 +216,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_when_click_target() {
|
fn assert_when_click_target() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = MenuBar::new(Arc::clone(&config));
|
let widget = MenuBar::new(Arc::clone(&config));
|
||||||
let point = Point::new(20, 30);
|
let point = Point::new(20, 30);
|
||||||
let context = UpdateContext::Nothing;
|
let context = UpdateContext::Nothing;
|
||||||
@ -226,7 +226,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_when_not_click_target_because_parent() {
|
fn refute_when_not_click_target_because_parent() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = MenuBar::new(Arc::clone(&config));
|
let widget = MenuBar::new(Arc::clone(&config));
|
||||||
let point = Point::new(20, 30);
|
let point = Point::new(20, 30);
|
||||||
let context = UpdateContext::ParentPosition(Point::new(9999, 9999));
|
let context = UpdateContext::ParentPosition(Point::new(9999, 9999));
|
||||||
@ -236,7 +236,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_when_click_target_because_parent() {
|
fn assert_when_click_target_because_parent() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let (w, h) = {
|
let (w, h) = {
|
||||||
(
|
(
|
||||||
config.read().unwrap().width(),
|
config.read().unwrap().width(),
|
||||||
@ -252,7 +252,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_on_click_do_nothing() {
|
fn assert_on_click_do_nothing() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = MenuBar::new(Arc::clone(&config));
|
let mut widget = MenuBar::new(Arc::clone(&config));
|
||||||
let point = Point::new(12, 34);
|
let point = Point::new(12, 34);
|
||||||
let context = UpdateContext::ParentPosition(Point::new(678, 293));
|
let context = UpdateContext::ParentPosition(Point::new(678, 293));
|
||||||
@ -264,38 +264,51 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_render {
|
mod test_render {
|
||||||
use crate::tests::support::SimpleRendererMock;
|
use crate::app::UpdateResult;
|
||||||
use crate::tests::*;
|
use crate::tests::*;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
use sdl2::rect::Rect;
|
use rider_derive::*;
|
||||||
|
use rider_match_widget::*;
|
||||||
|
use sdl2::pixels::PixelFormatEnum;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_render() {
|
#[match_widgets(
|
||||||
let rect_color = sdl2::pixels::Color::RGBA(18, 18, 18, 0);
|
fn_name = "assert_save_button_child",
|
||||||
let border_color = sdl2::pixels::Color::RGBA(200, 200, 200, 0);
|
widget = "MenuBar",
|
||||||
let context = RenderContext::Nothing;
|
contains = "save_button",
|
||||||
let config = support::build_config();
|
x = 16i32,
|
||||||
let mut canvas = support::CanvasMock::new();
|
y = 10i32,
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
w = 16u32,
|
||||||
|
h = 16u32,
|
||||||
|
widget_dump_path = "/tmp/rider-images/MenuBar-saveButton.png",
|
||||||
|
child_dump_path = "/tmp/rider-images/SaveButton.png",
|
||||||
|
background_from = "background_color",
|
||||||
|
widget_variable = "widget"
|
||||||
|
)]
|
||||||
|
fn assert_save_button_child() {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[match_widgets(
|
||||||
|
fn_name = "assert_settings_button",
|
||||||
|
widget = "MenuBar",
|
||||||
|
contains = "settings_button",
|
||||||
|
x = 32i32,
|
||||||
|
y = 10i32,
|
||||||
|
w = 16u32,
|
||||||
|
h = 16u32,
|
||||||
|
widget_dump_path = "/tmp/rider-images/MenuBar-settingsButton.png",
|
||||||
|
child_dump_path = "/tmp/rider-images/SettingsButton.png",
|
||||||
|
background_from = "background_color",
|
||||||
|
widget_variable = "widget"
|
||||||
|
)]
|
||||||
|
fn assert_settings_button() {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_update() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
let mut widget = MenuBar::new(config.clone());
|
let mut widget = MenuBar::new(config.clone());
|
||||||
widget.prepare_ui();
|
widget.prepare_ui();
|
||||||
widget.render(&mut canvas, &mut renderer, &context);
|
let result = widget.update(0, &UpdateContext::Nothing);
|
||||||
assert_eq!(widget.dest(), Rect::new(0, 0, 1024, 40));
|
assert_eq!(result, UpdateResult::NoOp);
|
||||||
assert_eq!(
|
|
||||||
canvas.find_rect_with_color(Rect::new(0, 0, 1024, 40), rect_color.clone()),
|
|
||||||
Some(&support::RendererRect::new(
|
|
||||||
Rect::new(0, 0, 1024, 40),
|
|
||||||
rect_color,
|
|
||||||
support::CanvasShape::Rectangle
|
|
||||||
))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
canvas.find_border_with_color(Rect::new(0, 0, 1024, 40), border_color.clone()),
|
|
||||||
Some(&support::RendererRect::new(
|
|
||||||
Rect::new(0, 0, 1024, 40),
|
|
||||||
border_color,
|
|
||||||
support::CanvasShape::Border
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ pub enum UpdateContext<'l> {
|
|||||||
Nothing,
|
Nothing,
|
||||||
ParentPosition(Point),
|
ParentPosition(Point),
|
||||||
CurrentFile(&'l mut EditorFile),
|
CurrentFile(&'l mut EditorFile),
|
||||||
|
ScrolledBy(Point),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
@ -47,6 +48,7 @@ pub enum RenderContext {
|
|||||||
ParentPosition(Point),
|
ParentPosition(Point),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
pub trait CanvasAccess {
|
pub trait CanvasAccess {
|
||||||
fn render_rect(&mut self, rect: Rect, color: sdl2::pixels::Color) -> Result<(), String>;
|
fn render_rect(&mut self, rect: Rect, color: sdl2::pixels::Color) -> Result<(), String>;
|
||||||
fn render_border(&mut self, rect: Rect, color: sdl2::pixels::Color) -> Result<(), String>;
|
fn render_border(&mut self, rect: Rect, color: sdl2::pixels::Color) -> Result<(), String>;
|
||||||
@ -63,6 +65,7 @@ pub trait CanvasAccess {
|
|||||||
fn clip_rect(&self) -> Option<Rect>;
|
fn clip_rect(&self) -> Option<Rect>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl CanvasAccess for WindowCanvas {
|
impl CanvasAccess for WindowCanvas {
|
||||||
fn render_rect(&mut self, rect: Rect, color: sdl2::pixels::Color) -> Result<(), String> {
|
fn render_rect(&mut self, rect: Rect, color: sdl2::pixels::Color) -> Result<(), String> {
|
||||||
self.set_draw_color(color);
|
self.set_draw_color(color);
|
||||||
@ -101,33 +104,29 @@ impl CanvasAccess for WindowCanvas {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn is_in_rect(point: &Point, rect: &Rect) -> bool {
|
|
||||||
rect.contains_point(point.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build_font_details<T>(config_holder: &T) -> FontDetails
|
pub fn build_font_details<T>(config_holder: &T) -> FontDetails
|
||||||
where
|
where
|
||||||
T: ConfigHolder,
|
T: ConfigHolder,
|
||||||
{
|
{
|
||||||
let c = config_holder.config().read().unwrap();
|
let c = config_holder.config().read().unwrap();
|
||||||
FontDetails::new(
|
(
|
||||||
c.editor_config().font_path().as_str(),
|
c.editor_config().font_path(),
|
||||||
c.editor_config().character_size(),
|
c.editor_config().character_size(),
|
||||||
)
|
)
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
pub fn get_text_character_rect<'l, T>(c: char, renderer: &mut T) -> Option<Rect>
|
pub fn get_text_character_rect<'l, T>(c: char, renderer: &mut T) -> Option<Rect>
|
||||||
where
|
where
|
||||||
T: ManagersHolder<'l> + ConfigHolder,
|
T: Renderer + ConfigHolder,
|
||||||
{
|
{
|
||||||
let font_details = renderer.config().read().unwrap().editor_config().into();
|
let font_details = renderer.config().read().unwrap().editor_config().into();
|
||||||
renderer
|
renderer
|
||||||
.font_manager()
|
.load_font(font_details)
|
||||||
.load(&font_details)
|
.size_of_char(c)
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|font| font.size_of_char(c).ok())
|
|
||||||
.and_then(|(width, height)| Some(Rect::new(0, 0, width, height)))
|
.and_then(|(width, height)| Some(Rect::new(0, 0, width, height)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +188,9 @@ pub trait Widget {
|
|||||||
|
|
||||||
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
||||||
match *context {
|
match *context {
|
||||||
UpdateContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest()),
|
UpdateContext::ParentPosition(p) | UpdateContext::ScrolledBy(p) => {
|
||||||
|
move_render_point(p.clone(), &self.dest())
|
||||||
|
}
|
||||||
_ => self.dest().clone(),
|
_ => self.dest().clone(),
|
||||||
}
|
}
|
||||||
.contains_point(point.clone())
|
.contains_point(point.clone())
|
||||||
@ -216,17 +217,24 @@ pub trait Widget {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn use_clipping(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
where
|
where
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
let mut dest = match context {
|
let mut dest = match context {
|
||||||
&RenderContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest()),
|
&RenderContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest()),
|
||||||
_ => self.dest().clone(),
|
_ => self.dest().clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if self.use_clipping() {
|
||||||
canvas.set_clipping(self.clipping(&dest));
|
canvas.set_clipping(self.clipping(&dest));
|
||||||
|
}
|
||||||
|
|
||||||
self.texture_path()
|
self.texture_path()
|
||||||
.and_then(|path| renderer.load_image(path).ok())
|
.and_then(|path| renderer.load_image(path).ok())
|
||||||
.and_then(|texture| {
|
.and_then(|texture| {
|
||||||
@ -234,14 +242,14 @@ pub trait Widget {
|
|||||||
dest.set_height(self.dest().height());
|
dest.set_height(self.dest().height());
|
||||||
canvas
|
canvas
|
||||||
.render_image(texture.clone(), self.source().clone(), dest.clone())
|
.render_image(texture.clone(), self.source().clone(), dest.clone())
|
||||||
.unwrap_or_else(|_| panic!("Failed to draw widget texture"));
|
.unwrap_or_else(|e| panic!("Failed to draw widget texture. {}", e));
|
||||||
Some(())
|
Some(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_ui<'l, T>(&mut self, _renderer: &mut T)
|
fn prepare_ui<'l, T>(&mut self, _renderer: &mut T)
|
||||||
where
|
where
|
||||||
T: Renderer + CharacterSizeManager,
|
T: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,7 +257,9 @@ pub trait Widget {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
|
use rider_derive::*;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
struct ConfigWrapper {
|
struct ConfigWrapper {
|
||||||
pub inner: ConfigAccess,
|
pub inner: ConfigAccess,
|
||||||
@ -261,18 +271,52 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
struct Dummy {
|
||||||
fn must_return_true_if_inside_rect() {
|
pub inner: WidgetInner,
|
||||||
let rect = Rect::new(10, 10, 30, 30);
|
|
||||||
let point = Point::new(20, 20);
|
|
||||||
assert_eq!(is_in_rect(&point, &rect), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
impl Dummy {
|
||||||
fn must_return_not_if_not_inside_rect() {
|
pub fn new(config: ConfigAccess) -> Self {
|
||||||
let rect = Rect::new(10, 10, 30, 30);
|
Self {
|
||||||
let point = Point::new(41, 41);
|
inner: WidgetInner::new(config, Rect::new(0, 1, 2, 3), Rect::new(4, 5, 6, 7)),
|
||||||
assert_eq!(is_in_rect(&point, &rect), false);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Dummy {
|
||||||
|
type Target = WidgetInner;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for Dummy {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Dummy {
|
||||||
|
fn texture_path(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect) {
|
||||||
|
self.source = rect.clone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -284,7 +328,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_build_font_details() {
|
fn must_build_font_details() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let wrapper = ConfigWrapper {
|
let wrapper = ConfigWrapper {
|
||||||
inner: config.clone(),
|
inner: config.clone(),
|
||||||
};
|
};
|
||||||
@ -293,4 +337,137 @@ mod tests {
|
|||||||
assert_eq!(details.path, c.editor_config().font_path().to_string());
|
assert_eq!(details.path, c.editor_config().font_path().to_string());
|
||||||
assert_eq!(details.size, c.editor_config().character_size());
|
assert_eq!(details.size, c.editor_config().character_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn mut_return_character_rectangle() {
|
||||||
|
// let config = build_config();
|
||||||
|
// let mut renderer = SimpleRendererMock::new(config);
|
||||||
|
// let result = get_text_character_rect('a', &mut renderer);
|
||||||
|
// assert_eq!(result, Some(Rect::new(0, 0, 10, 10)));
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_texture_path() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(widget.texture_path(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_dest() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(widget.dest(), &Rect::new(4, 5, 6, 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_set_dest() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = Dummy::new(config);
|
||||||
|
assert_eq!(widget.set_dest(&Rect::new(9, 8, 7, 6)), ());
|
||||||
|
assert_eq!(widget.dest(), &Rect::new(9, 8, 7, 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_source() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(widget.source(), &Rect::new(0, 1, 2, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_set_source() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = Dummy::new(config);
|
||||||
|
assert_eq!(widget.set_source(&Rect::new(9, 8, 7, 6)), ());
|
||||||
|
assert_eq!(widget.source(), &Rect::new(9, 8, 7, 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_update() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = Dummy::new(config);
|
||||||
|
assert_eq!(
|
||||||
|
widget.update(0, &UpdateContext::Nothing),
|
||||||
|
UpdateResult::NoOp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_on_left_click() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = Dummy::new(config);
|
||||||
|
assert_eq!(
|
||||||
|
widget.on_left_click(&Point::new(0, 1), &UpdateContext::Nothing),
|
||||||
|
UpdateResult::NoOp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_is_left_click_target() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(
|
||||||
|
widget.is_left_click_target(&Point::new(0, 1), &UpdateContext::Nothing),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_render_start_point() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(
|
||||||
|
widget.render_start_point(),
|
||||||
|
Rect::new(4, 5, 6, 7).top_left()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_clipping() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(
|
||||||
|
widget.clipping(&Rect::new(0, 0, 1, 1)),
|
||||||
|
Rect::new(0, 0, 1, 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_padding_width() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(widget.padding_width(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_padding_height() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(widget.padding_height(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_use_clipping() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(widget.use_clipping(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_render() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let widget = Dummy::new(config);
|
||||||
|
assert_eq!(
|
||||||
|
widget.render(&mut canvas, &mut renderer, &RenderContext::Nothing),
|
||||||
|
()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_prepare_ui() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut widget = Dummy::new(config);
|
||||||
|
assert_eq!(widget.prepare_ui(&mut renderer), ());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ pub enum ModalType {
|
|||||||
Settings(Settings),
|
Settings(Settings),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl PartialEq for ModalType {
|
impl PartialEq for ModalType {
|
||||||
fn eq(&self, other: &ModalType) -> bool {
|
fn eq(&self, other: &ModalType) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
@ -19,6 +20,7 @@ impl PartialEq for ModalType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl std::fmt::Debug for ModalType {
|
impl std::fmt::Debug for ModalType {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
let name = match self {
|
let name = match self {
|
||||||
|
@ -84,26 +84,46 @@ impl OpenFile {
|
|||||||
|
|
||||||
pub fn open_directory<R>(&mut self, dir_path: String, renderer: &mut R)
|
pub fn open_directory<R>(&mut self, dir_path: String, renderer: &mut R)
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
self.directory_view.open_directory(dir_path, renderer);
|
self.directory_view.open_directory(dir_path, renderer);
|
||||||
{
|
{
|
||||||
let dest = self.directory_view.dest();
|
self.full_dest = Rect::new(
|
||||||
let full_dest = Rect::new(
|
self.directory_view.dest().x(),
|
||||||
dest.x(),
|
self.directory_view.dest().y(),
|
||||||
dest.y(),
|
self.directory_view.dest().width() + (2 * CONTENT_MARGIN_LEFT as u32),
|
||||||
dest.width() + (2 * CONTENT_MARGIN_LEFT as u32),
|
self.directory_view.dest().height() + (2 * CONTENT_MARGIN_TOP as u32),
|
||||||
dest.height() + (2 * CONTENT_MARGIN_TOP as u32),
|
|
||||||
);
|
);
|
||||||
self.full_dest = full_dest;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_rect(&self) -> &Rect {
|
pub fn full_rect(&self) -> &Rect {
|
||||||
&self.full_dest
|
&self.full_dest
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, ticks: i32, context: &UC) -> UR {
|
impl Widget for OpenFile {
|
||||||
|
fn texture_path(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
self.dest()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect) {
|
||||||
|
self.set_dest(rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, ticks: i32, context: &UC) -> UR {
|
||||||
let (window_width, window_height, color, scroll_width, scroll_margin) = {
|
let (window_width, window_height, color, scroll_width, scroll_margin) = {
|
||||||
let c = self.config.read().unwrap();
|
let c = self.config.read().unwrap();
|
||||||
(
|
(
|
||||||
@ -141,7 +161,44 @@ impl OpenFile {
|
|||||||
UR::NoOp
|
UR::NoOp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RC)
|
fn on_left_click(&mut self, point: &Point, context: &UC) -> UR {
|
||||||
|
let dest = match context {
|
||||||
|
UC::ParentPosition(p) => move_render_point(*p, &self.dest),
|
||||||
|
_ => self.dest,
|
||||||
|
};
|
||||||
|
let context = UC::ParentPosition(
|
||||||
|
dest.top_left() + Point::new(CONTENT_MARGIN_LEFT, CONTENT_MARGIN_TOP) + self.scroll(),
|
||||||
|
);
|
||||||
|
let res = self.directory_view.on_left_click(point, &context);
|
||||||
|
{
|
||||||
|
let dest = self.directory_view.dest();
|
||||||
|
let full_dest = Rect::new(
|
||||||
|
dest.x(),
|
||||||
|
dest.y(),
|
||||||
|
dest.width() + (2 * CONTENT_MARGIN_LEFT as u32),
|
||||||
|
dest.height() + (2 * CONTENT_MARGIN_TOP as u32),
|
||||||
|
);
|
||||||
|
self.full_dest = full_dest;
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_left_click_target(&self, point: &Point, context: &UC) -> bool {
|
||||||
|
let dest = match context {
|
||||||
|
UC::ParentPosition(p) => move_render_point(p.clone(), &self.dest()),
|
||||||
|
_ => self.dest().clone(),
|
||||||
|
};
|
||||||
|
let p =
|
||||||
|
dest.top_left() + Point::new(CONTENT_MARGIN_LEFT, CONTENT_MARGIN_TOP) + self.scroll();
|
||||||
|
let context = UC::ParentPosition(p);
|
||||||
|
if self.directory_view.is_left_click_target(point, &context) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
Rect::new(p.x(), p.y(), dest.width(), dest.height()).contains_point(point.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
where
|
where
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
R: Renderer + CharacterSizeManager + ConfigHolder,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
@ -174,64 +231,19 @@ impl OpenFile {
|
|||||||
.render(canvas, &RenderContext::ParentPosition(self.dest.top_left()));
|
.render(canvas, &RenderContext::ParentPosition(self.dest.top_left()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
fn prepare_ui<'l, T>(&mut self, renderer: &mut T)
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
T: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
self.directory_view.prepare_ui(renderer);
|
self.directory_view.prepare_ui(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_start_point(&self) -> Point {
|
|
||||||
self.dest.top_left()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dest(&self) -> Rect {
|
|
||||||
self.dest.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_left_click(&mut self, point: &Point, context: &UC) -> UR {
|
|
||||||
let dest = match context {
|
|
||||||
UC::ParentPosition(p) => move_render_point(*p, &self.dest),
|
|
||||||
_ => self.dest,
|
|
||||||
};
|
|
||||||
let context = UC::ParentPosition(
|
|
||||||
dest.top_left() + Point::new(CONTENT_MARGIN_LEFT, CONTENT_MARGIN_TOP) + self.scroll(),
|
|
||||||
);
|
|
||||||
let res = self.directory_view.on_left_click(point, &context);
|
|
||||||
{
|
|
||||||
let dest = self.directory_view.dest();
|
|
||||||
let full_dest = Rect::new(
|
|
||||||
dest.x(),
|
|
||||||
dest.y(),
|
|
||||||
dest.width() + (2 * CONTENT_MARGIN_LEFT as u32),
|
|
||||||
dest.height() + (2 * CONTENT_MARGIN_TOP as u32),
|
|
||||||
);
|
|
||||||
self.full_dest = full_dest;
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_left_click_target(&self, point: &Point, context: &UC) -> bool {
|
|
||||||
let dest = match context {
|
|
||||||
UC::ParentPosition(p) => move_render_point(p.clone(), &self.dest()),
|
|
||||||
_ => self.dest().clone(),
|
|
||||||
};
|
|
||||||
let p =
|
|
||||||
dest.top_left() + Point::new(CONTENT_MARGIN_LEFT, CONTENT_MARGIN_TOP) + self.scroll();
|
|
||||||
let context = UC::ParentPosition(p);
|
|
||||||
if self.directory_view.is_left_click_target(point, &context) {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
Rect::new(p.x(), p.y(), dest.width(), dest.height()).contains_point(point.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support::SimpleRendererMock;
|
use crate::tests::*;
|
||||||
use crate::tests::support::{build_config, CanvasMock};
|
use rider_derive::*;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
//#######################################################################
|
//#######################################################################
|
||||||
@ -254,7 +266,7 @@ mod tests {
|
|||||||
fn assert_dest() {
|
fn assert_dest() {
|
||||||
let config = build_config();
|
let config = build_config();
|
||||||
let widget = OpenFile::new("/tmp".to_owned(), 120, 130, config);
|
let widget = OpenFile::new("/tmp".to_owned(), 120, 130, config);
|
||||||
assert_eq!(widget.dest(), Rect::new(452, 365, 120, 130));
|
assert_eq!(widget.dest(), &Rect::new(452, 365, 120, 130));
|
||||||
}
|
}
|
||||||
|
|
||||||
//#######################################################################
|
//#######################################################################
|
||||||
@ -276,8 +288,7 @@ mod tests {
|
|||||||
fn assert_open_directory() {
|
fn assert_open_directory() {
|
||||||
let path = "/tmp/rider/test-open-file/open-directory";
|
let path = "/tmp/rider/test-open-file/open-directory";
|
||||||
fs::create_dir_all(path).unwrap();
|
fs::create_dir_all(path).unwrap();
|
||||||
let config = build_config();
|
build_test_renderer!(renderer);
|
||||||
let mut renderer = SimpleRendererMock::new(config);
|
|
||||||
let mut widget = OpenFile::new(path.to_owned(), 120, 130, renderer.config().clone());
|
let mut widget = OpenFile::new(path.to_owned(), 120, 130, renderer.config().clone());
|
||||||
widget.open_directory(path.to_owned(), &mut renderer);
|
widget.open_directory(path.to_owned(), &mut renderer);
|
||||||
}
|
}
|
||||||
@ -383,9 +394,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_render() {
|
fn assert_render() {
|
||||||
let config = build_config();
|
|
||||||
let path = "/tmp/rider/test-open-file/open-directory";
|
let path = "/tmp/rider/test-open-file/open-directory";
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
build_test_renderer!(renderer);
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let widget = OpenFile::new(path.to_owned(), 100, 100, config);
|
let widget = OpenFile::new(path.to_owned(), 100, 100, config);
|
||||||
let p = Point::new(100, 100);
|
let p = Point::new(100, 100);
|
||||||
@ -399,9 +409,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_prepare_ui() {
|
fn assert_prepare_ui() {
|
||||||
let config = build_config();
|
|
||||||
let path = "/tmp/rider/test-open-file/open-directory";
|
let path = "/tmp/rider/test-open-file/open-directory";
|
||||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
build_test_renderer!(renderer);
|
||||||
let mut widget = OpenFile::new(path.to_owned(), 100, 100, config);
|
let mut widget = OpenFile::new(path.to_owned(), 100, 100, config);
|
||||||
widget.prepare_ui(&mut renderer);
|
widget.prepare_ui(&mut renderer);
|
||||||
}
|
}
|
||||||
|
@ -27,73 +27,74 @@ pub struct Settings {
|
|||||||
character_size_value: Label,
|
character_size_value: Label,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Widget for Settings {
|
||||||
pub fn new(config: ConfigAccess) -> Self {
|
fn texture_path(&self) -> Option<String> {
|
||||||
let c = config
|
None
|
||||||
.read()
|
|
||||||
.unwrap_or_else(|_| panic!("Failed to read config"));
|
|
||||||
let theme = c.theme();
|
|
||||||
let window_width = c.width();
|
|
||||||
let window_height = c.height();
|
|
||||||
let background_color = theme.background().into();
|
|
||||||
let border_color = theme.border_color().into();
|
|
||||||
Self {
|
|
||||||
vertical_scroll_bar: VerticalScrollBar::new(Arc::clone(&config)),
|
|
||||||
horizontal_scroll_bar: HorizontalScrollBar::new(Arc::clone(&config)),
|
|
||||||
dest: Rect::new(
|
|
||||||
CONTENT_MARGIN_LEFT,
|
|
||||||
CONTENT_MARGIN_TOP,
|
|
||||||
window_width - (CONTENT_MARGIN_LEFT * 2) as u32,
|
|
||||||
window_height - (CONTENT_MARGIN_TOP * 2) as u32,
|
|
||||||
),
|
|
||||||
full_dest: Rect::new(0, 0, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE),
|
|
||||||
background_color,
|
|
||||||
border_color,
|
|
||||||
font_label: Label::new("Font path".into(), config.clone()),
|
|
||||||
font_value: Label::new(c.editor_config().font_path().clone(), config.clone()),
|
|
||||||
character_size_label: Label::new("Character size".into(), config.clone()),
|
|
||||||
character_size_value: Label::new(
|
|
||||||
format!("{}", c.editor_config().character_size()).to_owned(),
|
|
||||||
config.clone(),
|
|
||||||
),
|
|
||||||
config: config.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_rect(&self) -> &Rect {
|
fn dest(&self) -> &Rect {
|
||||||
&self.full_dest
|
&self.dest
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scroll_by(&mut self, x: i32, y: i32) {
|
fn set_dest(&mut self, _rect: &Rect) {}
|
||||||
let read_config = self.config.read().unwrap();
|
|
||||||
|
|
||||||
let value_x = read_config.scroll().speed() * x;
|
fn source(&self) -> &Rect {
|
||||||
let value_y = read_config.scroll().speed() * y;
|
&self.dest
|
||||||
let old_x = self.horizontal_scroll_bar.scroll_value();
|
|
||||||
let old_y = self.vertical_scroll_bar.scroll_value();
|
|
||||||
|
|
||||||
if value_x + old_x >= 0 {
|
|
||||||
self.horizontal_scroll_bar.scroll_to(value_x + old_x);
|
|
||||||
if self.horizontal_scroll_bar.scrolled_part() > 1.0 {
|
|
||||||
self.horizontal_scroll_bar.scroll_to(old_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if value_y + old_y >= 0 {
|
|
||||||
self.vertical_scroll_bar.scroll_to(value_y + old_y);
|
|
||||||
if self.vertical_scroll_bar.scrolled_part() > 1.0 {
|
|
||||||
self.vertical_scroll_bar.scroll_to(old_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scroll(&self) -> Point {
|
fn set_source(&mut self, _rect: &Rect) {}
|
||||||
Point::new(
|
|
||||||
-self.horizontal_scroll_bar.scroll_value(),
|
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
||||||
-self.vertical_scroll_bar.scroll_value(),
|
let (window_width, window_height, color, scroll_width, scroll_margin) = {
|
||||||
|
let c = self.config.read().unwrap();
|
||||||
|
(
|
||||||
|
c.width(),
|
||||||
|
c.height(),
|
||||||
|
c.theme().background().into(),
|
||||||
|
c.scroll().width(),
|
||||||
|
c.scroll().margin_right(),
|
||||||
)
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.dest.set_x(CONTENT_MARGIN_LEFT);
|
||||||
|
self.dest
|
||||||
|
.set_width(window_width - (CONTENT_MARGIN_LEFT * 2) as u32);
|
||||||
|
self.dest.set_y(CONTENT_MARGIN_TOP);
|
||||||
|
self.dest
|
||||||
|
.set_height(window_height - (CONTENT_MARGIN_TOP * 2) as u32);
|
||||||
|
|
||||||
|
self.background_color = color;
|
||||||
|
|
||||||
|
// Scroll bars
|
||||||
|
self.vertical_scroll_bar
|
||||||
|
.set_full_size(self.full_dest.height()); // full dest
|
||||||
|
self.vertical_scroll_bar.set_viewport(self.dest.height());
|
||||||
|
self.vertical_scroll_bar
|
||||||
|
.set_location(self.dest.width() as i32 - (scroll_width as i32 + scroll_margin));
|
||||||
|
self.vertical_scroll_bar.update(ticks, context);
|
||||||
|
|
||||||
|
self.horizontal_scroll_bar
|
||||||
|
.set_full_size(self.full_dest.width()); // full dest
|
||||||
|
self.horizontal_scroll_bar.set_viewport(self.dest.width());
|
||||||
|
self.horizontal_scroll_bar
|
||||||
|
.set_location(self.dest.height() as i32 - (scroll_width as i32 + scroll_margin));
|
||||||
|
self.horizontal_scroll_bar.update(ticks, context);
|
||||||
|
|
||||||
|
// End
|
||||||
|
UR::NoOp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RC)
|
#[inline]
|
||||||
|
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
||||||
|
UR::NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_left_click_target(&self, _point: &Point, _context: &UpdateContext) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RC)
|
||||||
where
|
where
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
R: Renderer + CharacterSizeManager + ConfigHolder,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
@ -165,9 +166,9 @@ impl Settings {
|
|||||||
.render(canvas, &RenderContext::ParentPosition(self.dest.top_left()));
|
.render(canvas, &RenderContext::ParentPosition(self.dest.top_left()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||||
where
|
where
|
||||||
R: Renderer + CharacterSizeManager,
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
self.font_label.prepare_ui(renderer);
|
self.font_label.prepare_ui(renderer);
|
||||||
self.font_value.prepare_ui(renderer);
|
self.font_value.prepare_ui(renderer);
|
||||||
@ -176,66 +177,178 @@ impl Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClickHandler for Settings {
|
impl ScrollView<VerticalScrollBar, HorizontalScrollBar> for Settings {
|
||||||
#[inline]
|
fn mut_horizontal_scroll_handler(&mut self) -> Option<&mut HorizontalScrollBar> {
|
||||||
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
Some(&mut self.horizontal_scroll_bar)
|
||||||
UR::NoOp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
fn horizontal_scroll_handler(&self) -> Option<&HorizontalScrollBar> {
|
||||||
fn is_left_click_target(&self, _point: &Point, _context: &UpdateContext) -> bool {
|
Some(&self.horizontal_scroll_bar)
|
||||||
false
|
}
|
||||||
|
|
||||||
|
fn mut_vertical_scroll_handler(&mut self) -> Option<&mut VerticalScrollBar> {
|
||||||
|
Some(&mut self.vertical_scroll_bar)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertical_scroll_handler(&self) -> Option<&VerticalScrollBar> {
|
||||||
|
Some(&self.vertical_scroll_bar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderBox for Settings {
|
impl Settings {
|
||||||
fn render_start_point(&self) -> Point {
|
pub fn new(config: ConfigAccess) -> Self {
|
||||||
self.dest.top_left()
|
let c = config
|
||||||
}
|
.read()
|
||||||
|
.unwrap_or_else(|_| panic!("Failed to read config"));
|
||||||
fn dest(&self) -> Rect {
|
let theme = c.theme();
|
||||||
self.dest.clone()
|
let window_width = c.width();
|
||||||
|
let window_height = c.height();
|
||||||
|
let background_color = theme.background().into();
|
||||||
|
let border_color = theme.border_color().into();
|
||||||
|
Self {
|
||||||
|
vertical_scroll_bar: VerticalScrollBar::new(Arc::clone(&config)),
|
||||||
|
horizontal_scroll_bar: HorizontalScrollBar::new(Arc::clone(&config)),
|
||||||
|
dest: Rect::new(
|
||||||
|
CONTENT_MARGIN_LEFT,
|
||||||
|
CONTENT_MARGIN_TOP,
|
||||||
|
window_width - (CONTENT_MARGIN_LEFT * 2) as u32,
|
||||||
|
window_height - (CONTENT_MARGIN_TOP * 2) as u32,
|
||||||
|
),
|
||||||
|
full_dest: Rect::new(0, 0, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE),
|
||||||
|
background_color,
|
||||||
|
border_color,
|
||||||
|
font_label: Label::new("Font path".into(), config.clone()),
|
||||||
|
font_value: Label::new(c.editor_config().font_path().to_string(), config.clone()),
|
||||||
|
character_size_label: Label::new("Character size".into(), config.clone()),
|
||||||
|
character_size_value: Label::new(
|
||||||
|
format!("{}", c.editor_config().character_size()).to_owned(),
|
||||||
|
config.clone(),
|
||||||
|
),
|
||||||
|
config: config.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Update for Settings {
|
pub fn full_rect(&self) -> &Rect {
|
||||||
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
&self.full_dest
|
||||||
let (window_width, window_height, color, scroll_width, scroll_margin) = {
|
}
|
||||||
let c = self.config.read().unwrap();
|
}
|
||||||
(
|
|
||||||
c.width(),
|
impl ConfigHolder for Settings {
|
||||||
c.height(),
|
fn config(&self) -> &ConfigAccess {
|
||||||
c.theme().background().into(),
|
&self.config
|
||||||
c.scroll().width(),
|
}
|
||||||
c.scroll().margin_right(),
|
}
|
||||||
)
|
|
||||||
};
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
self.dest.set_x(CONTENT_MARGIN_LEFT);
|
use crate::app::UpdateResult;
|
||||||
self.dest
|
use crate::tests::*;
|
||||||
.set_width(window_width - (CONTENT_MARGIN_LEFT * 2) as u32);
|
use crate::ui::{RenderContext, ScrollView, Settings, UpdateContext, Widget};
|
||||||
self.dest.set_y(CONTENT_MARGIN_TOP);
|
use rider_derive::*;
|
||||||
self.dest
|
use sdl2::rect::{Point, Rect};
|
||||||
.set_height(window_height - (CONTENT_MARGIN_TOP * 2) as u32);
|
|
||||||
|
#[test]
|
||||||
self.background_color = color;
|
fn must_have_vertical_scrollbar() {
|
||||||
|
let config = build_config();
|
||||||
// Scroll bars
|
let mut widget = Settings::new(config);
|
||||||
self.vertical_scroll_bar
|
assert_eq!(widget.mut_vertical_scroll_handler().is_some(), true);
|
||||||
.set_full_size(self.full_dest.height()); // full dest
|
assert_eq!(widget.vertical_scroll_handler().is_some(), true);
|
||||||
self.vertical_scroll_bar.set_viewport(self.dest.height());
|
}
|
||||||
self.vertical_scroll_bar
|
|
||||||
.set_location(self.dest.width() as i32 - (scroll_width as i32 + scroll_margin));
|
#[test]
|
||||||
self.vertical_scroll_bar.update(ticks, context);
|
fn must_have_horizontal_scrollbar() {
|
||||||
|
let config = build_config();
|
||||||
self.horizontal_scroll_bar
|
let mut widget = Settings::new(config);
|
||||||
.set_full_size(self.full_dest.width()); // full dest
|
assert_eq!(widget.mut_horizontal_scroll_handler().is_some(), true);
|
||||||
self.horizontal_scroll_bar.set_viewport(self.dest.width());
|
assert_eq!(widget.horizontal_scroll_handler().is_some(), true);
|
||||||
self.horizontal_scroll_bar
|
}
|
||||||
.set_location(self.dest.height() as i32 - (scroll_width as i32 + scroll_margin));
|
|
||||||
self.horizontal_scroll_bar.update(ticks, context);
|
// Widget
|
||||||
|
|
||||||
// End
|
#[test]
|
||||||
UR::NoOp
|
fn assert_texture_path() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Settings::new(config);
|
||||||
|
let result = widget.texture_path();
|
||||||
|
assert!(result.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_dest() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Settings::new(config);
|
||||||
|
let result = widget.dest().clone();
|
||||||
|
let expected = Rect::new(16, 24, 992, 812);
|
||||||
|
assert_eq!(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_set_dest() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = Settings::new(config);
|
||||||
|
widget.set_dest(&Rect::new(100, 200, 300, 400));
|
||||||
|
assert_ne!(widget.dest(), &Rect::new(100, 200, 300, 400));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn assert_source() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Settings::new(config);
|
||||||
|
let result = widget.source();
|
||||||
|
assert_eq!(result, &Rect::new(16, 24, 992, 812));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn assert_set_source() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = Settings::new(config);
|
||||||
|
widget.set_source(&Rect::new(1, 2, 3, 4));
|
||||||
|
assert_ne!(widget.source(), &Rect::new(1, 2, 3, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_update() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = Settings::new(config);
|
||||||
|
let result = widget.update(0, &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, UpdateResult::NoOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_on_left_click() {
|
||||||
|
let config = build_config();
|
||||||
|
let mut widget = Settings::new(config);
|
||||||
|
let result = widget.on_left_click(&Point::new(600, 800), &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, UpdateResult::NoOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_is_left_click_target() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Settings::new(config);
|
||||||
|
let result = widget.is_left_click_target(&Point::new(600, 800), &UpdateContext::Nothing);
|
||||||
|
assert_eq!(result, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_use_clipping() {
|
||||||
|
let config = build_config();
|
||||||
|
let widget = Settings::new(config);
|
||||||
|
let result = widget.use_clipping();
|
||||||
|
assert_eq!(result, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assert_render() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut canvas = CanvasMock::new();
|
||||||
|
let widget = Settings::new(config);
|
||||||
|
let result = widget.render(&mut canvas, &mut renderer, &RenderContext::Nothing);
|
||||||
|
assert_eq!(result, ());
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn assert_prepare_ui() {
|
||||||
|
build_test_renderer!(renderer);
|
||||||
|
let mut widget = Settings::new(config);
|
||||||
|
let result = widget.prepare_ui(&mut renderer);
|
||||||
|
assert_eq!(result, ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ use crate::ui::filesystem::directory::DirectoryView;
|
|||||||
use crate::ui::horizontal_scroll_bar::HorizontalScrollBar;
|
use crate::ui::horizontal_scroll_bar::HorizontalScrollBar;
|
||||||
use crate::ui::text_character::CharacterSizeManager;
|
use crate::ui::text_character::CharacterSizeManager;
|
||||||
use crate::ui::vertical_scroll_bar::VerticalScrollBar;
|
use crate::ui::vertical_scroll_bar::VerticalScrollBar;
|
||||||
use crate::ui::ClickHandler;
|
|
||||||
use crate::ui::RenderContext;
|
use crate::ui::RenderContext;
|
||||||
use crate::ui::UpdateContext;
|
use crate::ui::UpdateContext;
|
||||||
use crate::ui::{move_render_point, ScrollView};
|
use crate::ui::{move_render_point, ScrollView};
|
||||||
@ -33,31 +32,24 @@ pub struct ProjectTreeSidebar {
|
|||||||
horizontal_scroll_bar: HorizontalScrollBar,
|
horizontal_scroll_bar: HorizontalScrollBar,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectTreeSidebar {
|
impl Widget for ProjectTreeSidebar {
|
||||||
pub fn new(root: String, config: Arc<RwLock<Config>>) -> Self {
|
fn texture_path(&self) -> Option<String> {
|
||||||
let (background_color, border_color, h): (Color, Color, u32) = {
|
None
|
||||||
let c = config.read().unwrap();
|
|
||||||
(
|
|
||||||
c.theme().background().into(),
|
|
||||||
c.theme().border_color().into(),
|
|
||||||
c.height(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
|
||||||
dest: Rect::new(0, 0, 200, h),
|
|
||||||
full_dest: Rect::new(0, 0, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE),
|
|
||||||
dir_view: DirectoryView::new(root.clone(), config.clone()),
|
|
||||||
vertical_scroll_bar: VerticalScrollBar::new(Arc::clone(&config)),
|
|
||||||
horizontal_scroll_bar: HorizontalScrollBar::new(Arc::clone(&config)),
|
|
||||||
config,
|
|
||||||
root,
|
|
||||||
background_color,
|
|
||||||
border_color,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, ticks: i32) {
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, _rect: &Rect) {}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, _rect: &Rect) {}
|
||||||
|
|
||||||
|
fn update(&mut self, ticks: i32, _context: &UpdateContext) -> UpdateResult {
|
||||||
let config = self.config.read().unwrap();
|
let config = self.config.read().unwrap();
|
||||||
let height = config.height();
|
let height = config.height();
|
||||||
// let left_margin = config.editor_left_margin();
|
// let left_margin = config.editor_left_margin();
|
||||||
@ -66,70 +58,9 @@ impl ProjectTreeSidebar {
|
|||||||
self.dest.set_y(top_margin);
|
self.dest.set_y(top_margin);
|
||||||
self.dest.set_height(height - top_margin as u32);
|
self.dest.set_height(height - top_margin as u32);
|
||||||
self.dir_view.update(ticks, &UpdateContext::Nothing);
|
self.dir_view.update(ticks, &UpdateContext::Nothing);
|
||||||
|
UpdateResult::NoOp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
|
||||||
where
|
|
||||||
R: Renderer + CharacterSizeManager,
|
|
||||||
{
|
|
||||||
let config = self.config.read().unwrap();
|
|
||||||
let height = config.height();
|
|
||||||
let left_margin = 0;
|
|
||||||
let top_margin = config.menu_height() as i32;
|
|
||||||
self.dest.set_x(left_margin);
|
|
||||||
self.dest.set_y(top_margin);
|
|
||||||
self.dest.set_height(height);
|
|
||||||
self.dir_view.prepare_ui(renderer);
|
|
||||||
self.dir_view.open_directory(self.root.clone(), renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render<C, R>(&self, canvas: &mut C, renderer: &mut R)
|
|
||||||
where
|
|
||||||
R: Renderer + CharacterSizeManager,
|
|
||||||
C: CanvasAccess,
|
|
||||||
{
|
|
||||||
canvas.set_clipping(self.dest.clone());
|
|
||||||
canvas
|
|
||||||
.render_rect(self.dest.clone(), self.background_color.clone())
|
|
||||||
.unwrap();
|
|
||||||
canvas
|
|
||||||
.render_border(self.dest.clone(), self.border_color.clone())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// dir view
|
|
||||||
let context = RenderContext::ParentPosition(
|
|
||||||
self.dest.top_left() + Point::new(CONTENT_MARGIN_LEFT, CONTENT_MARGIN_TOP),
|
|
||||||
);
|
|
||||||
self.dir_view.render(canvas, renderer, &context);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn full_rect(&self) -> Rect {
|
|
||||||
self.dest.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn root(&self) -> String {
|
|
||||||
self.root.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn open_directory<R>(&mut self, dir_path: String, renderer: &mut R)
|
|
||||||
where
|
|
||||||
R: Renderer + CharacterSizeManager,
|
|
||||||
{
|
|
||||||
self.dir_view.open_directory(dir_path, renderer);
|
|
||||||
{
|
|
||||||
let dest = self.dir_view.dest();
|
|
||||||
let full_dest = Rect::new(
|
|
||||||
dest.x(),
|
|
||||||
dest.y(),
|
|
||||||
dest.width() + (2 * CONTENT_MARGIN_LEFT as u32),
|
|
||||||
dest.height() + (2 * CONTENT_MARGIN_TOP as u32),
|
|
||||||
);
|
|
||||||
self.full_dest = full_dest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClickHandler for ProjectTreeSidebar {
|
|
||||||
fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UpdateResult {
|
fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UpdateResult {
|
||||||
let dest = match context {
|
let dest = match context {
|
||||||
UpdateContext::ParentPosition(p) => move_render_point(*p, &self.dest),
|
UpdateContext::ParentPosition(p) => move_render_point(*p, &self.dest),
|
||||||
@ -166,6 +97,95 @@ impl ClickHandler for ProjectTreeSidebar {
|
|||||||
Rect::new(p.x(), p.y(), dest.width(), dest.height()).contains_point(point.clone())
|
Rect::new(p.x(), p.y(), dest.width(), dest.height()).contains_point(point.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn use_clipping(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, _context: &RenderContext)
|
||||||
|
where
|
||||||
|
C: CanvasAccess,
|
||||||
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
|
{
|
||||||
|
if self.use_clipping() {
|
||||||
|
canvas.set_clipping(self.dest.clone());
|
||||||
|
}
|
||||||
|
canvas
|
||||||
|
.render_rect(self.dest.clone(), self.background_color.clone())
|
||||||
|
.unwrap();
|
||||||
|
canvas
|
||||||
|
.render_border(self.dest.clone(), self.border_color.clone())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// dir view
|
||||||
|
let context = RenderContext::ParentPosition(
|
||||||
|
self.dest.top_left() + Point::new(CONTENT_MARGIN_LEFT, CONTENT_MARGIN_TOP),
|
||||||
|
);
|
||||||
|
self.dir_view.render(canvas, renderer, &context);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||||
|
where
|
||||||
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
|
{
|
||||||
|
let config = self.config.read().unwrap();
|
||||||
|
let height = config.height();
|
||||||
|
let left_margin = 0;
|
||||||
|
let top_margin = config.menu_height() as i32;
|
||||||
|
self.dest.set_x(left_margin);
|
||||||
|
self.dest.set_y(top_margin);
|
||||||
|
self.dest.set_height(height);
|
||||||
|
self.dir_view.prepare_ui(renderer);
|
||||||
|
self.dir_view.open_directory(self.root.clone(), renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProjectTreeSidebar {
|
||||||
|
pub fn new(root: String, config: Arc<RwLock<Config>>) -> Self {
|
||||||
|
let (background_color, border_color, h): (Color, Color, u32) = {
|
||||||
|
let c = config.read().unwrap();
|
||||||
|
(
|
||||||
|
c.theme().background().into(),
|
||||||
|
c.theme().border_color().into(),
|
||||||
|
c.height(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
dest: Rect::new(0, 0, 200, h),
|
||||||
|
full_dest: Rect::new(0, 0, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE),
|
||||||
|
dir_view: DirectoryView::new(root.clone(), config.clone()),
|
||||||
|
vertical_scroll_bar: VerticalScrollBar::new(Arc::clone(&config)),
|
||||||
|
horizontal_scroll_bar: HorizontalScrollBar::new(Arc::clone(&config)),
|
||||||
|
config,
|
||||||
|
root,
|
||||||
|
background_color,
|
||||||
|
border_color,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn full_rect(&self) -> Rect {
|
||||||
|
self.dest.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn root(&self) -> String {
|
||||||
|
self.root.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open_directory<R>(&mut self, dir_path: String, renderer: &mut R)
|
||||||
|
where
|
||||||
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
|
{
|
||||||
|
self.dir_view.open_directory(dir_path, renderer);
|
||||||
|
{
|
||||||
|
self.full_dest = Rect::new(
|
||||||
|
self.dir_view.dest().x(),
|
||||||
|
self.dir_view.dest().y(),
|
||||||
|
self.dir_view.dest().width() + (2 * CONTENT_MARGIN_LEFT as u32),
|
||||||
|
self.dir_view.dest().height() + (2 * CONTENT_MARGIN_TOP as u32),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigHolder for ProjectTreeSidebar {
|
impl ConfigHolder for ProjectTreeSidebar {
|
||||||
@ -197,13 +217,12 @@ mod tests {
|
|||||||
use crate::renderer::managers::FontDetails;
|
use crate::renderer::managers::FontDetails;
|
||||||
use crate::renderer::managers::TextDetails;
|
use crate::renderer::managers::TextDetails;
|
||||||
use crate::renderer::renderer::Renderer;
|
use crate::renderer::renderer::Renderer;
|
||||||
use crate::tests::support::build_config;
|
use crate::tests::*;
|
||||||
use crate::tests::support::CanvasMock;
|
|
||||||
use crate::ui::project_tree::ProjectTreeSidebar;
|
use crate::ui::project_tree::ProjectTreeSidebar;
|
||||||
use crate::ui::scroll_bar::ScrollView;
|
use crate::ui::scroll_bar::ScrollView;
|
||||||
use crate::ui::text_character::CharacterSizeManager;
|
use crate::ui::text_character::CharacterSizeManager;
|
||||||
use crate::ui::ClickHandler;
|
use crate::ui::Widget;
|
||||||
use crate::ui::UpdateContext;
|
use crate::ui::{RenderContext, UpdateContext};
|
||||||
use rider_config::ConfigAccess;
|
use rider_config::ConfigAccess;
|
||||||
use rider_config::ConfigHolder;
|
use rider_config::ConfigHolder;
|
||||||
use sdl2::rect::Point;
|
use sdl2::rect::Point;
|
||||||
@ -270,7 +289,7 @@ mod tests {
|
|||||||
fn assert_update() {
|
fn assert_update() {
|
||||||
let config = build_config();
|
let config = build_config();
|
||||||
let mut widget = ProjectTreeSidebar::new("/tmp".to_owned(), config);
|
let mut widget = ProjectTreeSidebar::new("/tmp".to_owned(), config);
|
||||||
widget.update(0);
|
widget.update(0, &UpdateContext::Nothing);
|
||||||
assert_eq!(widget.full_rect(), Rect::new(0, 40, 200, 820));
|
assert_eq!(widget.full_rect(), Rect::new(0, 40, 200, 820));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +308,7 @@ mod tests {
|
|||||||
let mut renderer = RendererMock::new(config.clone());
|
let mut renderer = RendererMock::new(config.clone());
|
||||||
let mut canvas = CanvasMock::new();
|
let mut canvas = CanvasMock::new();
|
||||||
let widget = ProjectTreeSidebar::new("/tmp".to_owned(), config);
|
let widget = ProjectTreeSidebar::new("/tmp".to_owned(), config);
|
||||||
widget.render(&mut canvas, &mut renderer);
|
widget.render(&mut canvas, &mut renderer, &RenderContext::Nothing);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#######################################################################
|
//#######################################################################
|
||||||
|
@ -84,7 +84,7 @@ impl ScrollWidget for HorizontalScrollBar {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_update {
|
mod test_update {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
|
|
||||||
impl HorizontalScrollBar {
|
impl HorizontalScrollBar {
|
||||||
@ -95,7 +95,7 @@ mod test_update {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_do_nothing_when_small_content() {
|
fn assert_do_nothing_when_small_content() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
||||||
widget.set_viewport(100);
|
widget.set_viewport(100);
|
||||||
widget.set_full_size(20);
|
widget.set_full_size(20);
|
||||||
@ -108,7 +108,7 @@ mod test_update {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_update_when_huge_content() {
|
fn assert_update_when_huge_content() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
||||||
widget.set_viewport(100);
|
widget.set_viewport(100);
|
||||||
widget.set_full_size(200);
|
widget.set_full_size(200);
|
||||||
@ -123,12 +123,12 @@ mod test_update {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_scrollable {
|
mod test_scrollable {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_scroll_to() {
|
fn assert_scroll_to() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
||||||
let old = widget.scroll_value();
|
let old = widget.scroll_value();
|
||||||
widget.scroll_to(157);
|
widget.scroll_to(157);
|
||||||
@ -140,14 +140,14 @@ mod test_scrollable {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_scroll_value() {
|
fn assert_scroll_value() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = HorizontalScrollBar::new(Arc::clone(&config));
|
let widget = HorizontalScrollBar::new(Arc::clone(&config));
|
||||||
assert_eq!(widget.scroll_value(), 0);
|
assert_eq!(widget.scroll_value(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_set_viewport() {
|
fn assert_set_viewport() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
||||||
let old = widget.viewport();
|
let old = widget.viewport();
|
||||||
widget.set_viewport(157);
|
widget.set_viewport(157);
|
||||||
@ -159,7 +159,7 @@ mod test_scrollable {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_set_full_size() {
|
fn assert_set_full_size() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
||||||
let old = widget.full;
|
let old = widget.full;
|
||||||
widget.set_full_size(157);
|
widget.set_full_size(157);
|
||||||
@ -171,7 +171,7 @@ mod test_scrollable {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_set_location() {
|
fn assert_set_location() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
|
||||||
let old = widget.rect().y();
|
let old = widget.rect().y();
|
||||||
widget.set_location(157);
|
widget.set_location(157);
|
||||||
|
@ -84,7 +84,7 @@ impl ScrollWidget for VerticalScrollBar {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_update {
|
mod test_update {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
|
|
||||||
impl VerticalScrollBar {
|
impl VerticalScrollBar {
|
||||||
@ -95,7 +95,7 @@ mod test_update {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_do_nothing_when_small_content() {
|
fn assert_do_nothing_when_small_content() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
||||||
widget.set_viewport(100);
|
widget.set_viewport(100);
|
||||||
widget.set_full_size(20);
|
widget.set_full_size(20);
|
||||||
@ -108,7 +108,7 @@ mod test_update {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_update_when_huge_content() {
|
fn assert_update_when_huge_content() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
||||||
widget.set_viewport(100);
|
widget.set_viewport(100);
|
||||||
widget.set_full_size(200);
|
widget.set_full_size(200);
|
||||||
@ -123,12 +123,12 @@ mod test_update {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_scrollable {
|
mod test_scrollable {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::support;
|
use crate::tests::*;
|
||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_scroll_to() {
|
fn assert_scroll_to() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
||||||
let old = widget.scroll_value();
|
let old = widget.scroll_value();
|
||||||
widget.scroll_to(157);
|
widget.scroll_to(157);
|
||||||
@ -140,14 +140,14 @@ mod test_scrollable {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_scroll_value() {
|
fn assert_scroll_value() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = VerticalScrollBar::new(Arc::clone(&config));
|
let widget = VerticalScrollBar::new(Arc::clone(&config));
|
||||||
assert_eq!(widget.scroll_value(), 0);
|
assert_eq!(widget.scroll_value(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_set_viewport() {
|
fn assert_set_viewport() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
||||||
let old = widget.viewport();
|
let old = widget.viewport();
|
||||||
widget.set_viewport(157);
|
widget.set_viewport(157);
|
||||||
@ -159,7 +159,7 @@ mod test_scrollable {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_set_full_size() {
|
fn assert_set_full_size() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
||||||
let old = widget.full;
|
let old = widget.full;
|
||||||
widget.set_full_size(157);
|
widget.set_full_size(157);
|
||||||
@ -171,7 +171,7 @@ mod test_scrollable {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_set_location() {
|
fn assert_set_location() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
let mut widget = VerticalScrollBar::new(Arc::clone(&config));
|
||||||
let old = widget.rect().x();
|
let old = widget.rect().x();
|
||||||
widget.set_location(157);
|
widget.set_location(157);
|
||||||
|
@ -51,18 +51,6 @@ impl TextCharacter {
|
|||||||
self.last_in_line
|
self.last_in_line
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source(&self) -> &Rect {
|
|
||||||
&self.source
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_dest(&mut self, rect: &Rect) {
|
|
||||||
self.dest = rect.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_source(&mut self, rect: &Rect) {
|
|
||||||
self.source = rect.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn color(&self) -> &Color {
|
pub fn color(&self) -> &Color {
|
||||||
&self.color
|
&self.color
|
||||||
}
|
}
|
||||||
@ -101,15 +89,42 @@ impl TextCharacter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextCharacter {
|
impl Widget for TextCharacter {
|
||||||
|
fn texture_path(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
|
self.dest = rect.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect) {
|
||||||
|
self.source = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
||||||
|
UR::MoveCaret(
|
||||||
|
self.dest.clone(),
|
||||||
|
CaretPosition::new(self.position(), self.line(), 0),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Must first create targets so even if new line appear renderer will know
|
* Must first create targets so even if new line appear renderer will know
|
||||||
* where move render starting point
|
* where move render starting point
|
||||||
*/
|
*/
|
||||||
pub fn render<R, C>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
where
|
where
|
||||||
R: Renderer + ConfigHolder,
|
|
||||||
C: CanvasAccess,
|
C: CanvasAccess,
|
||||||
|
R: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
let font_details: FontDetails = renderer.config().read().unwrap().editor_config().into();
|
let font_details: FontDetails = renderer.config().read().unwrap().editor_config().into();
|
||||||
|
|
||||||
@ -125,7 +140,7 @@ impl TextCharacter {
|
|||||||
};
|
};
|
||||||
let dest = match context {
|
let dest = match context {
|
||||||
RenderContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest),
|
RenderContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest),
|
||||||
_ => self.dest(),
|
_ => self.dest().clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(texture) = renderer.load_text_tex(&mut details, font_details) {
|
if let Ok(texture) = renderer.load_text_tex(&mut details, font_details) {
|
||||||
@ -135,9 +150,9 @@ impl TextCharacter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_ui<'l, T>(&mut self, renderer: &mut T)
|
fn prepare_ui<'l, T>(&mut self, renderer: &mut T)
|
||||||
where
|
where
|
||||||
T: ConfigHolder + CharacterSizeManager + Renderer,
|
T: Renderer + CharacterSizeManager + ConfigHolder,
|
||||||
{
|
{
|
||||||
let font_details: FontDetails = renderer.config().read().unwrap().editor_config().into();
|
let font_details: FontDetails = renderer.config().read().unwrap().editor_config().into();
|
||||||
let rect = renderer.load_character_size(self.text_character);
|
let rect = renderer.load_character_size(self.text_character);
|
||||||
@ -159,39 +174,6 @@ impl TextCharacter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Update for TextCharacter {
|
|
||||||
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR {
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClickHandler for TextCharacter {
|
|
||||||
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
|
||||||
UR::MoveCaret(
|
|
||||||
self.dest().clone(),
|
|
||||||
CaretPosition::new(self.position(), self.line(), 0),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
|
||||||
let rect = match context {
|
|
||||||
&UpdateContext::ParentPosition(p) => move_render_point(p, &self.dest),
|
|
||||||
_ => self.dest(),
|
|
||||||
};
|
|
||||||
is_in_rect(point, &rect)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RenderBox for TextCharacter {
|
|
||||||
fn render_start_point(&self) -> Point {
|
|
||||||
self.dest.top_left()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dest(&self) -> Rect {
|
|
||||||
self.dest
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for TextCharacter {
|
impl PartialEq for TextCharacter {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.line == other.line
|
self.line == other.line
|
||||||
@ -229,7 +211,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_valid_is_last_in_line() {
|
fn must_return_valid_is_last_in_line() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = TextCharacter::new(
|
let widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -243,7 +225,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_true_for_is_new_line_if_new_line() {
|
fn must_return_true_for_is_new_line_if_new_line() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = TextCharacter::new(
|
let widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -257,7 +239,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_false_for_is_new_line_if_new_line() {
|
fn must_return_false_for_is_new_line_if_new_line() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget =
|
let widget =
|
||||||
TextCharacter::new('W', 0, 0, true, Color::RGB(1, 12, 123), Arc::clone(&config));
|
TextCharacter::new('W', 0, 0, true, Color::RGB(1, 12, 123), Arc::clone(&config));
|
||||||
assert_eq!(widget.is_new_line(), false);
|
assert_eq!(widget.is_new_line(), false);
|
||||||
@ -265,7 +247,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_valid_position() {
|
fn must_return_valid_position() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = TextCharacter::new(
|
let widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
1,
|
1,
|
||||||
@ -279,7 +261,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_valid_line() {
|
fn must_return_valid_line() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = TextCharacter::new(
|
let widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
1,
|
1,
|
||||||
@ -293,7 +275,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_valid_text_character() {
|
fn must_return_valid_text_character() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = TextCharacter::new(
|
let widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
87,
|
87,
|
||||||
@ -307,7 +289,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_valid_source() {
|
fn must_return_valid_source() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = TextCharacter::new(
|
let widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -321,7 +303,7 @@ mod test_getters {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_valid_dest() {
|
fn must_return_valid_dest() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = TextCharacter::new(
|
let widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -330,12 +312,12 @@ mod test_getters {
|
|||||||
Color::RGB(1, 12, 123),
|
Color::RGB(1, 12, 123),
|
||||||
Arc::clone(&config),
|
Arc::clone(&config),
|
||||||
);
|
);
|
||||||
assert_eq!(widget.dest(), Rect::new(0, 0, 0, 0));
|
assert_eq!(widget.dest(), &Rect::new(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_valid_color() {
|
fn must_return_valid_color() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let widget = TextCharacter::new(
|
let widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -357,7 +339,7 @@ mod test_own_methods {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_update_position_of_new_line() {
|
fn must_update_position_of_new_line() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = TextCharacter::new(
|
let mut widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -371,13 +353,13 @@ mod test_own_methods {
|
|||||||
let mut current = Rect::new(10, 23, 0, 0);
|
let mut current = Rect::new(10, 23, 0, 0);
|
||||||
widget.update_position(&mut current);
|
widget.update_position(&mut current);
|
||||||
assert_eq!(current, Rect::new(0, 103, 1, 1));
|
assert_eq!(current, Rect::new(0, 103, 1, 1));
|
||||||
assert_eq!(widget.dest(), Rect::new(10, 23, 30, 40));
|
assert_eq!(widget.dest(), &Rect::new(10, 23, 30, 40));
|
||||||
assert_eq!(widget.source(), &Rect::new(50, 60, 70, 80));
|
assert_eq!(widget.source(), &Rect::new(50, 60, 70, 80));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_update_position_of_non_new_line() {
|
fn must_update_position_of_non_new_line() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = TextCharacter::new(
|
let mut widget = TextCharacter::new(
|
||||||
'W',
|
'W',
|
||||||
0,
|
0,
|
||||||
@ -391,7 +373,7 @@ mod test_own_methods {
|
|||||||
let mut current = Rect::new(10, 23, 0, 0);
|
let mut current = Rect::new(10, 23, 0, 0);
|
||||||
widget.update_position(&mut current);
|
widget.update_position(&mut current);
|
||||||
assert_eq!(current, Rect::new(80, 23, 1, 1));
|
assert_eq!(current, Rect::new(80, 23, 1, 1));
|
||||||
assert_eq!(widget.dest(), Rect::new(10, 23, 70, 80));
|
assert_eq!(widget.dest(), &Rect::new(10, 23, 70, 80));
|
||||||
assert_eq!(widget.source(), &Rect::new(50, 60, 70, 80));
|
assert_eq!(widget.source(), &Rect::new(50, 60, 70, 80));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -406,7 +388,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_when_not_click_target() {
|
fn refute_when_not_click_target() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = TextCharacter::new(
|
let mut widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -425,7 +407,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_when_click_target() {
|
fn assert_when_click_target() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = TextCharacter::new(
|
let mut widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -444,7 +426,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn refute_when_not_click_target_because_parent() {
|
fn refute_when_not_click_target_because_parent() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = TextCharacter::new(
|
let mut widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -463,7 +445,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_when_click_target_because_parent() {
|
fn assert_when_click_target_because_parent() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = TextCharacter::new(
|
let mut widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -482,7 +464,7 @@ mod test_click_handler {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_on_click_return_move_caret() {
|
fn assert_on_click_return_move_caret() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let position = 1233;
|
let position = 1233;
|
||||||
let line = 2893;
|
let line = 2893;
|
||||||
let mut widget = TextCharacter::new(
|
let mut widget = TextCharacter::new(
|
||||||
@ -514,7 +496,7 @@ mod test_render_box {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn must_return_top_left_point() {
|
fn must_return_top_left_point() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = TextCharacter::new(
|
let mut widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
@ -541,7 +523,7 @@ mod test_update {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assert_do_nothing() {
|
fn assert_do_nothing() {
|
||||||
let config = support::build_config();
|
let config = build_config();
|
||||||
let mut widget = TextCharacter::new(
|
let mut widget = TextCharacter::new(
|
||||||
'\n',
|
'\n',
|
||||||
0,
|
0,
|
||||||
|
@ -25,7 +25,7 @@ pub mod lexer {
|
|||||||
token: Token::new(text.to_string(), 0, 0, 0, 0)
|
token: Token::new(text.to_string(), 0, 0, 0, 0)
|
||||||
}, text),
|
}, text),
|
||||||
|
|
||||||
r"(let|fn|type|struct|pub|impl|for|self|Self|mod|use|enum|(iu)(8|16|32)|usize|bool)" => (TokenType::Keyword {
|
r"(let|fn|type|struct|trait|pub|impl|for|self|Self|mod|use|enum|(iu)(8|16|32)|usize|bool)" => (TokenType::Keyword {
|
||||||
token: Token::new(text.to_string(), 0, 0, 0, 0)
|
token: Token::new(text.to_string(), 0, 0, 0, 0)
|
||||||
}, text),
|
}, text),
|
||||||
|
|
||||||
|
21
rider-match-widget/Cargo.toml
Normal file
21
rider-match-widget/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
[package]
|
||||||
|
name = "rider-match-widget"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Adrian Woźniak <adrian.wozniak.1986@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
darling = { version = "*" }
|
||||||
|
|
||||||
|
[dependencies.proc-macro2]
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
[dependencies.quote]
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
[dependencies.syn]
|
||||||
|
version = "1.0"
|
||||||
|
features = ["full", "extra-traits"]
|
176
rider-match-widget/src/lib.rs
Normal file
176
rider-match-widget/src/lib.rs
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
use darling::{FromMeta, ToTokens};
|
||||||
|
use proc_macro;
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
use syn::{parse_macro_input, AttributeArgs};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct AssertBuilder {
|
||||||
|
widget: String,
|
||||||
|
widget_variable: Option<String>,
|
||||||
|
contains: String,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
w: u32,
|
||||||
|
h: u32,
|
||||||
|
widget_dump_path: Option<String>,
|
||||||
|
child_dump_path: Option<String>,
|
||||||
|
background_from: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for AssertBuilder {
|
||||||
|
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||||
|
let AssertBuilder {
|
||||||
|
widget,
|
||||||
|
contains,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
widget_dump_path,
|
||||||
|
child_dump_path,
|
||||||
|
widget_variable,
|
||||||
|
background_from,
|
||||||
|
} = self.clone();
|
||||||
|
|
||||||
|
let var = format_ident!(
|
||||||
|
"{}",
|
||||||
|
widget_variable
|
||||||
|
.as_ref()
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| "widget".to_string())
|
||||||
|
);
|
||||||
|
let widget_name = format_ident!("{}", widget);
|
||||||
|
let child_name = format_ident!("{}", contains);
|
||||||
|
let background = match background_from {
|
||||||
|
Some(name) => {
|
||||||
|
let ident = format_ident!("{}", name);
|
||||||
|
quote! {
|
||||||
|
surface_canvas
|
||||||
|
.render_rect(size.clone(), widget. #ident .clone())
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => quote! {},
|
||||||
|
};
|
||||||
|
let widget_dump_path = match widget_dump_path.as_ref() {
|
||||||
|
Some(t) => {
|
||||||
|
quote! { Some( #t ) }
|
||||||
|
}
|
||||||
|
None => quote! { None },
|
||||||
|
};
|
||||||
|
let child_dump_path = match child_dump_path.as_ref() {
|
||||||
|
Some(t) => {
|
||||||
|
quote! { Some( #t ) }
|
||||||
|
}
|
||||||
|
None => quote! { None },
|
||||||
|
};
|
||||||
|
|
||||||
|
let generated = quote! {
|
||||||
|
let mut character_sizes = std::collections::HashMap::new();
|
||||||
|
let config = build_config();
|
||||||
|
let mut surface =
|
||||||
|
sdl2::surface::Surface::new( #x as u32 + #w as u32 , #y as u32 + #h as u32, sdl2::pixels::PixelFormatEnum::RGBA8888).unwrap();
|
||||||
|
let mut surface_canvas = sdl2::render::Canvas::from_surface(surface).unwrap();
|
||||||
|
let mut texture_creator = surface_canvas.texture_creator();
|
||||||
|
let mut texture_manager = crate::renderer::managers::TextureManager::new(&texture_creator);
|
||||||
|
let mut ttf_context = sdl2::ttf::Sdl2TtfContext {};
|
||||||
|
let mut renderer = SimpleRendererMock {
|
||||||
|
config: config.clone(),
|
||||||
|
ttf: ttf_context,
|
||||||
|
character_sizes,
|
||||||
|
texture_manager,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut #var = #widget_name ::new(config);
|
||||||
|
#var .prepare_ui();
|
||||||
|
let size = sdl2::rect::Rect::new(
|
||||||
|
0i32,
|
||||||
|
0i32,
|
||||||
|
#w as u32 + #x as u32,
|
||||||
|
#h as u32 + #y as u32,
|
||||||
|
);
|
||||||
|
let expected_pixels = {
|
||||||
|
#background
|
||||||
|
#var . #child_name .render(
|
||||||
|
&mut surface_canvas,
|
||||||
|
&mut renderer,
|
||||||
|
&RenderContext::ParentPosition( size.top_left() .offset( #x , #y ) ),
|
||||||
|
);
|
||||||
|
surface_canvas
|
||||||
|
.read_pixels(sdl2::rect::Rect::new( #x as i32, #y as i32 , #w as u32 , #h as u32 ), PixelFormatEnum::RGBA8888)
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
if let Some(child_dump_path) = #child_dump_path {
|
||||||
|
surface_canvas.dump_ui(child_dump_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#var .render(&mut surface_canvas, &mut renderer, &RenderContext::Nothing);
|
||||||
|
if let Some(widget_dump_path) = #widget_dump_path {
|
||||||
|
surface_canvas.dump_ui(widget_dump_path);
|
||||||
|
}
|
||||||
|
let result_pixels = surface_canvas
|
||||||
|
.read_pixels(sdl2::rect::Rect::new( #x as i32, #y as i32, #w as u32, #h as u32 ), PixelFormatEnum::RGBA8888)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if expected_pixels != result_pixels {
|
||||||
|
match ( #child_dump_path, #widget_dump_path ) {
|
||||||
|
(Some(c), Some(w)) => {
|
||||||
|
assert_eq!(c, w);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
assert_eq!(result_pixels, expected_pixels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tokens.extend(generated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, FromMeta)]
|
||||||
|
struct AssertOptions {
|
||||||
|
fn_name: String,
|
||||||
|
widget: String,
|
||||||
|
contains: String,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
w: u32,
|
||||||
|
h: u32,
|
||||||
|
widget_dump_path: Option<String>,
|
||||||
|
child_dump_path: Option<String>,
|
||||||
|
widget_variable: Option<String>,
|
||||||
|
background_from: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn match_widgets(args: TokenStream, _input: TokenStream) -> TokenStream {
|
||||||
|
let attr_args = parse_macro_input!(args as AttributeArgs);
|
||||||
|
// let _input = parse_macro_input!(input as ItemFn);
|
||||||
|
|
||||||
|
let opts = match AssertOptions::from_list(&attr_args) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return TokenStream::from(e.write_errors());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let builder = AssertBuilder {
|
||||||
|
widget: opts.widget,
|
||||||
|
widget_variable: opts.widget_variable,
|
||||||
|
contains: opts.contains,
|
||||||
|
x: opts.x,
|
||||||
|
y: opts.y,
|
||||||
|
w: opts.w,
|
||||||
|
h: opts.h,
|
||||||
|
widget_dump_path: opts.widget_dump_path,
|
||||||
|
child_dump_path: opts.child_dump_path,
|
||||||
|
background_from: opts.background_from,
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = format_ident!("{}", opts.fn_name);
|
||||||
|
|
||||||
|
let output = quote! { fn #name () { #builder } };
|
||||||
|
output.into()
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
extern crate rider_config;
|
extern crate rider_config;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let generator = rider_config::directories::get_binary_path("rider-generator").unwrap();
|
let generator = rider_config::directories::get_binary_path("rider-generator").unwrap();
|
||||||
println!("generator will be {:?}", generator);
|
println!("generator will be {:?}", generator);
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
mod test_files {
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
pub mod plain;
|
pub mod plain;
|
||||||
pub mod rust_lang;
|
pub mod rust_lang;
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
|
mod test_files {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Language {
|
pub enum Language {
|
||||||
PlainText,
|
PlainText,
|
||||||
@ -152,3 +156,4 @@ pub fn parse(text: String, language: Language) -> Vec<TokenType> {
|
|||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user