mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-12-13 06:28:01 +01:00
Compare commits
724 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4c31e72d29 | |||
| e3b2ff7f0e | |||
| 4c5f5e2cce | |||
| 39ae9b8ba0 | |||
| 5c7eb0535d | |||
| 235718390b | |||
| 5d4b72f224 | |||
| dc76ae9d1f | |||
| e44f4bb003 | |||
| 1fc1370d41 | |||
| 80a669c989 | |||
| 801c9eba2d | |||
| f9704d2836 | |||
| 39687171e9 | |||
| 1d73691ef4 | |||
| f8678d2515 | |||
| fb108ea18d | |||
| a7229a0677 | |||
| d0dd112b98 | |||
| 1e07120eb5 | |||
| fcd1f76cff | |||
| e400d86d75 | |||
| dca3410a5b | |||
| 9b314e2953 | |||
| 5635daf66d | |||
| 7e2e1645e9 | |||
| 4990afcdbb | |||
| c11f36dfef | |||
| abddf61c88 | |||
| 37fec7e952 | |||
| 0f6a93ae8f | |||
| 25eae334b0 | |||
| 74377d01ce | |||
| 6e78ba1e7b | |||
| 39e0dedf27 | |||
| bbe2c88802 | |||
| 586b31b63e | |||
| 041abe6d7e | |||
| a69b3cd05f | |||
| b48213e79e | |||
| 5bbc14aca5 | |||
| 8ccbf502e8 | |||
| c426ca97e2 | |||
| d9eef86a8b | |||
| 3fed921748 | |||
| 02827d53a2 | |||
| 1ad5fde9ae | |||
| 909d5ed99c | |||
| b9096df218 | |||
| 1137485c55 | |||
| 61b1155a03 | |||
| 35624bcb1c | |||
| 6e262334ed | |||
| 829d69485a | |||
| 0d32c168eb | |||
| 38d6d93f65 | |||
| 9a280492c2 | |||
| d49ee79c90 | |||
| 73b83af6b1 | |||
| 064673ef23 | |||
| 81bf93e5ab | |||
| 26d5a8ce08 | |||
| c6f5c8d91f | |||
| 63a1928468 | |||
| 27c2aee8b9 | |||
| 5219d29aca | |||
| 84955352dd | |||
| 8e05c30063 | |||
| 6f98bcafec | |||
| 4afac91bce | |||
| 6e6312f6d7 | |||
| df4c4e443d | |||
| ff40474f92 | |||
| aca06ee805 | |||
| ba8e29a9f8 | |||
| 583da2bd9f | |||
| 0ea07016b4 | |||
| 616421db9a | |||
| 293ddacd19 | |||
| 13945ec937 | |||
| 4ea6f336f8 | |||
| 58296aa266 | |||
| 742df9dff3 | |||
| 011e1f5922 | |||
| 8f67d69325 | |||
| 9ac133b605 | |||
| 538b2d26cd | |||
| cc3895c423 | |||
| 79454bfc3b | |||
| 734c7572bb | |||
| 9f93fbb161 | |||
| c78c63285e | |||
| c8cbf70a28 | |||
| 2b116d6756 | |||
| da611153cf | |||
| fd9bf4468a | |||
| fa234eb9d6 | |||
| dbfebf6a32 | |||
| 7b91e31485 | |||
| e882fc8b5e | |||
| 5a54195cac | |||
| a442adf8d5 | |||
| 38466878db | |||
| 7c86e4e743 | |||
| 41cbfb8d39 | |||
| 7c394f4b20 | |||
| c1a35e1053 | |||
| cddce8596f | |||
| c75058b1da | |||
| 1a73fcdb39 | |||
| 8e0c4f5308 | |||
| 51e2791cc7 | |||
| 130159f06c | |||
| 42d1140b55 | |||
| dfd987041a | |||
| 790d1787fd | |||
| 2a6a607c7b | |||
| b3521d2a18 | |||
| dee99caa7d | |||
| cf525a3929 | |||
| 18d658f7e1 | |||
| 1c42ab77d8 | |||
| 33d5638bb0 | |||
| 8ce92df87a | |||
| 80654449af | |||
| eee1622801 | |||
| 4c54876ecf | |||
| 1cbcd5c2da | |||
| 55253e284e | |||
| e9795cd697 | |||
| be76d9a6dc | |||
| d7cdaf2870 | |||
| 48ed0e01d1 | |||
| dca31dedde | |||
| ab7356b991 | |||
| a46a673cf8 | |||
| c8d52539ca | |||
| ed9267b6ba | |||
| b7c02d1cf8 | |||
| fb66beb29f | |||
| 8c3bf6bbc3 | |||
| b943078132 | |||
| e727617bf1 | |||
| ffaea6dcbe | |||
| bf1f72a2a4 | |||
| be0df7c5b0 | |||
| 5ab769e74d | |||
| d22ddb1731 | |||
| 9fed8c022b | |||
| a315ed90af | |||
| 1ebf3c9af2 | |||
| 0e4c923c23 | |||
| 63835b9f99 | |||
| ff17f7c132 | |||
| f4631c9b38 | |||
| 35931023ae | |||
| 6d93381760 | |||
| f1bdd5f1b2 | |||
| 1c3e2fbad7 | |||
| 29a02db07d | |||
| f1db1ba708 | |||
| c1420bac88 | |||
| 8e527fbbdf | |||
| 5ec1bcfe3f | |||
| 7226461cd0 | |||
| 6d6f383c92 | |||
| e1a6328d09 | |||
| 6e4153911a | |||
| 342f74646e | |||
| fe5191d3b5 | |||
| 504cf97c6c | |||
| f8c494c9c1 | |||
| b90d7f721a | |||
| 7936af6c9a | |||
| 52d01e3dd7 | |||
| d30d70395a | |||
| 491a3ae525 | |||
| 1eae380b08 | |||
| f091b2526e | |||
| 7548e2e202 | |||
| d9b9afbf2d | |||
| 8036659003 | |||
| f9fb4668c2 | |||
| 7047924947 | |||
| 8f6be3911a | |||
| 0d95b8eb44 | |||
| 61d2d124ff | |||
| 7b218b2544 | |||
| 87ac7daf76 | |||
| 6b4817df36 | |||
| 22d99da2e1 | |||
| 47b6cf7068 | |||
| 606c9512f8 | |||
| aef9c591e9 | |||
| 71f67e9191 | |||
| 636f2b3017 | |||
| 2de5b5c6e4 | |||
| 0cbcc8c9f3 | |||
| 96146e3dc8 | |||
| 5aaae51be1 | |||
| b98625fdbc | |||
| 09a748e9dc | |||
| 87b07c6d5b | |||
| f39e668f8d | |||
| 6ea95342a0 | |||
| c594bf5757 | |||
| cd3b198c6f | |||
| b249b5f46e | |||
| bbe3b48bcc | |||
| 3bcd056197 | |||
| 6387ab41b3 | |||
| 4df16b7f15 | |||
| ed387a2873 | |||
| 9e225530a6 | |||
| 7b23686dc6 | |||
| 4de31453fd | |||
| 4c59526e39 | |||
| 9ec1764194 | |||
| 47afa32902 | |||
| 2a09487b55 | |||
| 563c856dd3 | |||
| 69ea242408 | |||
| d6e0e0726f | |||
| 73d460d40a | |||
| 1f27d96ac9 | |||
| 93e9f28d69 | |||
| ec2e26752a | |||
| fadd95f3e6 | |||
| 00acc677e6 | |||
| 1a799881e8 | |||
| f75677593a | |||
| 19e3bd19f0 | |||
| 85701b0a3c | |||
| 014cb18dcb | |||
| e71e1c853f | |||
| ee9d9196f5 | |||
| 53c8272e01 | |||
| 7f7b6b1e2a | |||
| 405777e0f5 | |||
| df2b624cb5 | |||
| 8a48d5c2f9 | |||
| c55ee71442 | |||
| 3f82745f5b | |||
| 404187a1ae | |||
| 2b7b3f586b | |||
| 04959a3493 | |||
| 97cf4932ae | |||
| b0d88a0a37 | |||
| 67a2e40622 | |||
| 3a28556c7f | |||
| 9ecc92b9a5 | |||
| ca023be98a | |||
| 11a1423f76 | |||
| 79f6df121b | |||
| 71eade7e86 | |||
| 5f81d29036 | |||
| ec1cb5dc5f | |||
| fd969e2d55 | |||
| 37e33b77ff | |||
| f7ed7703b4 | |||
| 4bb35295ca | |||
| 1e4f673f9e | |||
| 7cadb1c403 | |||
| 37148f5093 | |||
| f6bc26789f | |||
| b3f5a88525 | |||
| 1e538d2b28 | |||
| 7d7bfb7b01 | |||
| 41d86ba440 | |||
| 3df474a8a5 | |||
| a50d6e8f47 | |||
| 6081e5b9c1 | |||
| 66ccea920c | |||
| 470d63093f | |||
| eae0507831 | |||
| 92af85d3bb | |||
| 7635af5730 | |||
| a838e89695 | |||
| b22289a8b9 | |||
| 45b3ff52c6 | |||
| 4464991f4c | |||
| b0d2f77583 | |||
| b211a4405d | |||
| 8823016d2c | |||
| 859fdc7ec1 | |||
| 028d5ed01f | |||
| 5fd5a2a436 | |||
| 79a7e7470c | |||
| 9ecef78aed | |||
| 65a837a6e1 | |||
| 6e4db4acea | |||
| 26fb977d05 | |||
| b42cd1c048 | |||
| 467f7cd12f | |||
| 66699ce9df | |||
| cf7d903932 | |||
| a7ab67925c | |||
| a474ba4260 | |||
| 09e5636e86 | |||
| 2295a875be | |||
| 82a2455afc | |||
| 268de676ee | |||
| 8fe26c07f1 | |||
| da3921b1ca | |||
| 4dd2e787d1 | |||
| ce005ae6c2 | |||
| 1513f46a11 | |||
| 7543eeb0f4 | |||
| 873242120c | |||
| 98f8095a65 | |||
| 785571a550 | |||
| 0c4bd4044e | |||
| 0319543dce | |||
| 82d70b2d7f | |||
| 62d18e010a | |||
| fc77b85083 | |||
| 50a8893f4f | |||
| 9252b3040e | |||
| d5141ed020 | |||
| 7ff9e23283 | |||
| 89854d527c | |||
| 6ff0cad2a8 | |||
| 349cfbd2d5 | |||
| 40303ef74a | |||
| 6c652122c2 | |||
| 3658e3a2aa | |||
| 2b20fcfcd1 | |||
| 554d427fef | |||
| 7cf5b23306 | |||
| b26a6098eb | |||
| 7ad927bdaf | |||
| 4ed30b3619 | |||
| edfa9264d5 | |||
| f7516b593f | |||
| 83ff998f9d | |||
| 47381e0df4 | |||
| ba62d57485 | |||
| c014c4bc24 | |||
| 5d1a3fede2 | |||
| 53b584fe45 | |||
| f53d974400 | |||
| c4b4ef19cd | |||
| 3bfc360362 | |||
| 584f16d375 | |||
| b3d84c3217 | |||
| dd14ad470e | |||
| 85b90574b8 | |||
| ee5d172468 | |||
| 7ca4b94361 | |||
| 31f1546483 | |||
| d8a88a19af | |||
| 12af79de05 | |||
| 2260dd419d | |||
| 61a940cc82 | |||
| 1bbc1e0d7e | |||
| 921294eeb3 | |||
| baaa90f49d | |||
| 4e25381770 | |||
| 272877d0ed | |||
| 555b947bf7 | |||
| da29811b16 | |||
| 241f67fd4d | |||
| eb4ce18e31 | |||
| ae99fee440 | |||
| d116ac5e56 | |||
| 28db1f4253 | |||
| 034312e676 | |||
| da83d73ba6 | |||
| 02e8dc3440 | |||
| cac6d1f889 | |||
| 68fa3294d4 | |||
| 9b983de8c9 | |||
| 3a37ee719b | |||
| 61359c2faa | |||
| 7f7c5ab35b | |||
| a1b483d20a | |||
| 04cd662d78 | |||
| da597f076f | |||
| fab3efdcf5 | |||
| a55509a34d | |||
| 84fb1c5b2b | |||
| 391a90e1df | |||
| e0fe39195d | |||
| 385fead81a | |||
| 648d1b9aa9 | |||
| 3f0028913d | |||
| 45e6ec8b0f | |||
| a3fbaa0b34 | |||
| 7102cbfb3b | |||
| c3db3ce0f2 | |||
| 7a1e7637ff | |||
| 04a78a02d3 | |||
| cb61dc742f | |||
| cd53f6e757 | |||
| c64f7daa8d | |||
| e70d792654 | |||
| 9ae533f907 | |||
| cfe92f18e3 | |||
| e2a34ea28e | |||
| ec8000360e | |||
| 57b0821e19 | |||
| 09d39df15a | |||
| 1f9db3bda6 | |||
| b7104c8828 | |||
| 5da02b4092 | |||
| 802f1e3042 | |||
| 66db0df45a | |||
| 650c2e2eb7 | |||
| 6ab3754129 | |||
| 7dca0a8cab | |||
| 7cd0b4ad54 | |||
| 97acb41eee | |||
| b916b9726e | |||
| 32d3990ace | |||
| cb1fd109cc | |||
| 0e68dd6185 | |||
| fb6502bc65 | |||
| c7e7403781 | |||
| bf224408a3 | |||
| 84b7078873 | |||
| 89e5943d8f | |||
| b78c4cb8f0 | |||
| 976ba074a8 | |||
| 5205d59b96 | |||
| e8394b9c08 | |||
| 9cd00239f9 | |||
| b6b26142f8 | |||
| 4ee99376fd | |||
| b0261342ff | |||
| 87fd2a521e | |||
| 334793c6f6 | |||
| 3e70d991bb | |||
| feec96fc5c | |||
| 765984709e | |||
| c7c9931f68 | |||
| ae64573510 | |||
| d675af5aa4 | |||
| 9480d17cfc | |||
| 5ac1df2283 | |||
| 20119db883 | |||
| a4006deb8c | |||
| 25fa3cefab | |||
| bb5161eb34 | |||
| 1bfc403a98 | |||
| 720d10e543 | |||
| 30c117672e | |||
| 6d1b5c77d1 | |||
| d1cbf608e0 | |||
| 7e3014c52d | |||
| 82beb1f5a7 | |||
| 657dc81300 | |||
| 8e22192dd3 | |||
| dc0b7d58e3 | |||
| 6919e5bdb0 | |||
| 9728a62efa | |||
| 276e070759 | |||
| fadea54f8d | |||
| 523d340ade | |||
| 96fa7efb66 | |||
| 03591f8317 | |||
| 28cc60d007 | |||
| 1fa69bdb3b | |||
| 11f5f9b72e | |||
| 61f6543041 | |||
| 0c9ab32f37 | |||
| fde984d02b | |||
| f23db31306 | |||
| 8dce99b8b3 | |||
| 342ac51cda | |||
| ba31f7ae01 | |||
| 8d0fa030f8 | |||
| d030a79c81 | |||
| 6690efc4d9 | |||
| afa8098463 | |||
| c064e579d2 | |||
| 01dc4e4714 | |||
| 6fbc246b12 | |||
| 1efe2a02f7 | |||
| ab2ab06f60 | |||
| a71d889682 | |||
| 2252d85b27 | |||
| 3f09100177 | |||
| 6b79c89f42 | |||
| 5f249d4603 | |||
| fa64309909 | |||
| c46aafdab6 | |||
| 3e9c397494 | |||
| 47935165db | |||
| be77f753e7 | |||
| 2c30613279 | |||
| d83eaec987 | |||
| e6f199a224 | |||
| 6636a2aa9e | |||
| 221bdc58fe | |||
| e48a068e9d | |||
| 3371c31e63 | |||
| aa2c60f7e9 | |||
| f7dc200684 | |||
| ad306c56c7 | |||
| 86aba1eb52 | |||
| 826f1aba7a | |||
| 8abf4364c6 | |||
| 4c45d91d4e | |||
| 3176b6cb8f | |||
| 27971e09cd | |||
| bf95ae00de | |||
| 0dbfa7e101 | |||
| 85d09c4b5e | |||
| 4f9bc40476 | |||
| 757ccbf9d3 | |||
| 4cf9730130 | |||
| 1dd0d70ab9 | |||
| 340eaece0f | |||
| c151e7cd37 | |||
| ca0baae832 | |||
| 478e6ed8df | |||
| 7388eb07ca | |||
| c38d507e50 | |||
| 5aee087a57 | |||
| 0cda3702ea | |||
| ce55226d0c | |||
| 0bab0a9963 | |||
| 34955b7083 | |||
| ba6ce072ac | |||
| f39fd00697 | |||
| 58fc1be1d5 | |||
| 1fdf9bffb6 | |||
| 2ad179ef8e | |||
| d42cc5b762 | |||
| 403658f622 | |||
| 6ca35685db | |||
| bfc6822f69 | |||
| b0386937d7 | |||
| 9436540b2f | |||
| 45b0ece342 | |||
| 5c147d3648 | |||
| 8fa68c428f | |||
| e2be90191e | |||
| 339da2f1a9 | |||
| b2cc5d50bd | |||
| f38b188046 | |||
| 9e45628e87 | |||
| bf76398627 | |||
| 81d5728964 | |||
| d76027558b | |||
| 1450cc24a3 | |||
| f41523c1b2 | |||
| 4019463e68 | |||
| 5e2e239f5e | |||
| bc7856b6c0 | |||
| e2bba8d9e1 | |||
| 520db2c32e | |||
| da71f2de2b | |||
| 6dd2c6678b | |||
| fb3d9e6d6b | |||
| 36473c2df9 | |||
| 81aa30b2ec | |||
| 85d5160782 | |||
| 44bf7b870e | |||
| 44da2e6082 | |||
| d576bc3972 | |||
| dbeb4c7205 | |||
| e5223a852e | |||
| f3884315c0 | |||
| 53cd9dc9a6 | |||
| a3666a7ab2 | |||
| ca4eb17308 | |||
| b729dca2e5 | |||
| 21354e675a | |||
| 2085ddd347 | |||
| 31a475861b | |||
| 45bdd95dc8 | |||
| 569fdec380 | |||
| 3f15ff1c06 | |||
| 506cd52255 | |||
| 300c0c6195 | |||
| 7689fe97b0 | |||
| 99ed077dbc | |||
| 65aeb6656f | |||
| e4f5766ffb | |||
| 353ac7c76b | |||
| 8073fa206b | |||
| 1a1cfa2220 | |||
| 5e93d866ad | |||
| f29e03e250 | |||
| 3775b5968d | |||
| ba6242e09d | |||
| f6b0ddddb9 | |||
| 9e8d5c6768 | |||
| ef78496d5d | |||
| 41a45a14df | |||
| 5d3721ad04 | |||
| f75bcb505c | |||
| fa365794a0 | |||
| a747ab700e | |||
| b51b017005 | |||
| b9e1dd5950 | |||
| 56bf33229b | |||
| 5740dd8c8a | |||
| d3f205287c | |||
| 53518cd6e6 | |||
| 0ff3896d51 | |||
| c64e16471b | |||
| 2f2e2b82b8 | |||
| af9a503f3c | |||
| 971affa607 | |||
| 2de5d6206e | |||
| 34e0bcc56a | |||
| bb9f09c11f | |||
| 3f5cc24a10 | |||
| 109a330c54 | |||
| 3e4cd3c92f | |||
| c6aaa4fb04 | |||
| 2de9570c38 | |||
| 3d88f57f8a | |||
| 23606f6d6c | |||
| 5a1ba1b0dc | |||
| ced5a82e07 | |||
| b4fc522f37 | |||
| a7e222f2e7 | |||
| 511e5c483c | |||
| a28fddbc4d | |||
| 780908f777 | |||
| 88e5681155 | |||
| bc197e6942 | |||
| afbfea6d43 | |||
| 662ee7382c | |||
| 12144a2bda | |||
| e11f2e54b4 | |||
| 01cb4e32eb | |||
| 1ca3541b34 | |||
| e209085960 | |||
| d1a90612c2 | |||
| 0a21c61535 | |||
| 8583a55424 | |||
| 3a7a0f63de | |||
| 2e13d08018 | |||
| f13515ba16 | |||
| 6f1884451b | |||
| d9321a9acb | |||
| 19f9614c74 | |||
| 66ce355571 | |||
| 5108649ec6 | |||
| 9308478a59 | |||
| 97d778c31c | |||
| 740195146b | |||
| 6e0717bf22 | |||
| b6a683dfe1 | |||
| dc78c68f12 | |||
| 8e01d5ec84 | |||
| b531016c7b | |||
| 188369e922 | |||
| 347c5054f9 | |||
| 6729b597c0 | |||
| 7bdbfe937c | |||
| d955713335 | |||
| 8bb69ef0ee | |||
| d258583a7f | |||
| 13d0e10dcd | |||
| 5557f79fe7 | |||
| 44ccaa0d26 | |||
| 49f12abeb3 | |||
| b1859774bc | |||
| 4283403f0e | |||
| 379191751c | |||
| 9bf396f2a8 | |||
| 87af4c96c4 | |||
| dd78a7c9de | |||
| 40e534090d | |||
| 973e0c489e | |||
| 5eb64829a5 | |||
| 5648e9e806 | |||
| 2a65e20fb9 | |||
| 1162e9b655 | |||
| b8a5c2fb9b | |||
| eccd37a3eb | |||
| ee282713f8 | |||
| c5edad9c4b | |||
| 293c01b12f | |||
| 162bbc3221 | |||
| 9f27020993 | |||
| c540cf45ca | |||
| 8bf4789646 | |||
| fd97c20d37 | |||
| 7238e17b86 | |||
| 4c44da7f4a | |||
| af7657e3f8 | |||
| bea158b0d9 | |||
| 40acb49011 | |||
| cc7fc7e994 | |||
| ddec715dda | |||
| a1365a98c0 | |||
| 9a29d4ff18 | |||
| 39816eae76 | |||
| 45a38d9570 | |||
| a230258bec | |||
| 8543205b85 | |||
| 1d169005da | |||
| f5212d88f3 | |||
| 03a93ad3f3 | |||
| 3a66fa28ab | |||
| 5f79b286f1 | |||
| f6a4e39cfc | |||
| 24d8444043 | |||
| 0b8205dc41 | |||
| 98197d1e86 | |||
| 77bcca45ce | |||
| d33d65031c | |||
| 8fe4aa386d | |||
| 05cc27b2b9 | |||
| 16ef1b3a34 | |||
| fd350528a9 | |||
| 62cd076abb | |||
| b63224a218 | |||
| 3223b3e78e | |||
| 8da95496bd | |||
| 8e1d23a53e | |||
| 2e2ad4edcf | |||
| e8ecd00a57 | |||
| e19ee6f363 | |||
| 3785efce78 | |||
| 841faf9124 | |||
| f8e14cb900 | |||
| 2ecbbdd011 |
105
.gitignore
vendored
105
.gitignore
vendored
@@ -1,6 +1,12 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# TweetDuck installer builds
|
||||||
|
bld/*
|
||||||
|
!bld/*.iss
|
||||||
|
!bld/*.bat
|
||||||
|
!bld/Resources
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
@@ -17,14 +23,11 @@
|
|||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
x64/
|
x64/
|
||||||
x86/
|
x86/
|
||||||
bld/
|
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
|
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
|
||||||
#wwwroot/
|
|
||||||
|
|
||||||
# MSTest test Results
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
@@ -34,11 +37,6 @@ bld/
|
|||||||
*.VisualState.xml
|
*.VisualState.xml
|
||||||
TestResult.xml
|
TestResult.xml
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
|
||||||
[Dd]ebugPS/
|
|
||||||
[Rr]eleasePS/
|
|
||||||
dlldata.c
|
|
||||||
|
|
||||||
# DNX
|
# DNX
|
||||||
project.lock.json
|
project.lock.json
|
||||||
artifacts/
|
artifacts/
|
||||||
@@ -47,7 +45,6 @@ artifacts/
|
|||||||
*_p.c
|
*_p.c
|
||||||
*_i.h
|
*_i.h
|
||||||
*.ilk
|
*.ilk
|
||||||
*.meta
|
|
||||||
*.obj
|
*.obj
|
||||||
*.pch
|
*.pch
|
||||||
*.pdb
|
*.pdb
|
||||||
@@ -68,27 +65,12 @@ artifacts/
|
|||||||
*.svclog
|
*.svclog
|
||||||
*.scc
|
*.scc
|
||||||
|
|
||||||
# Chutzpah Test files
|
|
||||||
_Chutzpah*
|
|
||||||
|
|
||||||
# Visual C++ cache files
|
|
||||||
ipch/
|
|
||||||
*.aps
|
|
||||||
*.ncb
|
|
||||||
*.opendb
|
|
||||||
*.opensdf
|
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
|
||||||
|
|
||||||
# Visual Studio profiler
|
# Visual Studio profiler
|
||||||
*.psess
|
*.psess
|
||||||
*.vsp
|
*.vsp
|
||||||
*.vspx
|
*.vspx
|
||||||
*.sap
|
*.sap
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
|
||||||
$tf/
|
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
# Guidance Automation Toolkit
|
||||||
*.gpState
|
*.gpState
|
||||||
|
|
||||||
@@ -115,33 +97,9 @@ nCrunchTemp_*
|
|||||||
*.mm.*
|
*.mm.*
|
||||||
AutoTest.Net/
|
AutoTest.Net/
|
||||||
|
|
||||||
# Web workbench (sass)
|
|
||||||
.sass-cache/
|
|
||||||
|
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
|
||||||
DocProject/buildhelp/
|
|
||||||
DocProject/Help/*.HxT
|
|
||||||
DocProject/Help/*.HxC
|
|
||||||
DocProject/Help/*.hhc
|
|
||||||
DocProject/Help/*.hhk
|
|
||||||
DocProject/Help/*.hhp
|
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
|
||||||
|
|
||||||
# Click-Once directory
|
# Click-Once directory
|
||||||
publish/
|
publish/
|
||||||
|
|
||||||
# Publish Web Output
|
|
||||||
*.[Pp]ublish.xml
|
|
||||||
*.azurePubxml
|
|
||||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
|
||||||
|
|
||||||
# NuGet Packages
|
# NuGet Packages
|
||||||
*.nupkg
|
*.nupkg
|
||||||
# The packages folder can be ignored because of Package Restore
|
# The packages folder can be ignored because of Package Restore
|
||||||
@@ -154,17 +112,6 @@ publish/
|
|||||||
*.nuget.props
|
*.nuget.props
|
||||||
*.nuget.targets
|
*.nuget.targets
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
|
||||||
csx/
|
|
||||||
*.build.csdef
|
|
||||||
|
|
||||||
# Microsoft Azure Emulator
|
|
||||||
ecf/
|
|
||||||
rcf/
|
|
||||||
|
|
||||||
# Microsoft Azure ApplicationInsights config file
|
|
||||||
ApplicationInsights.config
|
|
||||||
|
|
||||||
# Windows Store app package directory
|
# Windows Store app package directory
|
||||||
AppPackages/
|
AppPackages/
|
||||||
BundleArtifacts/
|
BundleArtifacts/
|
||||||
@@ -186,9 +133,6 @@ ClientBin/
|
|||||||
node_modules/
|
node_modules/
|
||||||
orleans.codegen.cs
|
orleans.codegen.cs
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
# Backup & report files from converting an old project file
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
# because we have git ;-)
|
# because we have git ;-)
|
||||||
@@ -197,40 +141,3 @@ Backup*/
|
|||||||
UpgradeLog*.XML
|
UpgradeLog*.XML
|
||||||
UpgradeLog*.htm
|
UpgradeLog*.htm
|
||||||
|
|
||||||
# SQL Server files
|
|
||||||
*.mdf
|
|
||||||
*.ldf
|
|
||||||
|
|
||||||
# Business Intelligence projects
|
|
||||||
*.rdl.data
|
|
||||||
*.bim.layout
|
|
||||||
*.bim_*.settings
|
|
||||||
|
|
||||||
# Microsoft Fakes
|
|
||||||
FakesAssemblies/
|
|
||||||
|
|
||||||
# GhostDoc plugin setting file
|
|
||||||
*.GhostDoc.xml
|
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
|
||||||
.ntvs_analysis.dat
|
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
|
||||||
*.plg
|
|
||||||
|
|
||||||
# Visual Studio 6 workspace options file
|
|
||||||
*.opt
|
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/ModelManifest.xml
|
|
||||||
**/*.Server/GeneratedArtifacts
|
|
||||||
**/*.Server/ModelManifest.xml
|
|
||||||
_Pvt_Extensions
|
|
||||||
|
|
||||||
# Paket dependency manager
|
|
||||||
.paket/paket.exe
|
|
||||||
|
|
||||||
# FAKE - F# Make
|
|
||||||
.fake/
|
|
||||||
|
|||||||
34
Configuration/Arguments.cs
Normal file
34
Configuration/Arguments.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Configuration{
|
||||||
|
static class Arguments{
|
||||||
|
// public args
|
||||||
|
public const string ArgDataFolder = "-datafolder";
|
||||||
|
public const string ArgLocale = "-locale";
|
||||||
|
public const string ArgLogging = "-log";
|
||||||
|
public const string ArgDebugUpdates = "-debugupdates";
|
||||||
|
|
||||||
|
// internal args
|
||||||
|
public const string ArgRestart = "-restart";
|
||||||
|
public const string ArgImportCookies = "-importcookies";
|
||||||
|
|
||||||
|
// class data and methods
|
||||||
|
private static readonly CommandLineArgs Current = CommandLineArgs.FromStringArray('-', Environment.GetCommandLineArgs());
|
||||||
|
|
||||||
|
public static bool HasFlag(string flag){
|
||||||
|
return Current.HasFlag(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetValue(string key, string defaultValue){
|
||||||
|
return Current.GetValue(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommandLineArgs GetCurrentClean(){
|
||||||
|
CommandLineArgs args = Current.Clone();
|
||||||
|
args.RemoveFlag(ArgRestart);
|
||||||
|
args.RemoveFlag(ArgImportCookies);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,115 +1,176 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Configuration{
|
namespace TweetDck.Configuration{
|
||||||
class LockManager{
|
sealed class LockManager{
|
||||||
|
public enum Result{
|
||||||
|
Success, HasProcess, Fail
|
||||||
|
}
|
||||||
|
|
||||||
|
public Process LockingProcess { get; private set; }
|
||||||
|
|
||||||
private readonly string file;
|
private readonly string file;
|
||||||
private FileStream lockStream;
|
private FileStream lockStream;
|
||||||
private Process lockingProcess;
|
|
||||||
|
|
||||||
public LockManager(string file){
|
public LockManager(string file){
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CreateLockFile(){
|
private void CreateLockFileStream(){
|
||||||
|
lockStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||||
|
WriteIntToStream(lockStream, GetCurrentProcessId());
|
||||||
|
lockStream.Flush(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ReleaseLockFileStream(){
|
||||||
|
if (lockStream != null){
|
||||||
|
lockStream.Dispose();
|
||||||
|
lockStream = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result TryCreateLockFile(){
|
||||||
if (lockStream != null){
|
if (lockStream != null){
|
||||||
throw new InvalidOperationException("Lock file already exists.");
|
throw new InvalidOperationException("Lock file already exists.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
lockStream = new FileStream(file,FileMode.Create,FileAccess.Write,FileShare.Read);
|
CreateLockFileStream();
|
||||||
|
return Result.Success;
|
||||||
byte[] id = BitConverter.GetBytes(Process.GetCurrentProcess().Id);
|
}catch(DirectoryNotFoundException){
|
||||||
lockStream.Write(id,0,id.Length);
|
|
||||||
lockStream.Flush();
|
|
||||||
|
|
||||||
if (lockingProcess != null){
|
|
||||||
lockingProcess.Close();
|
|
||||||
lockingProcess = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}catch(Exception){
|
|
||||||
if (lockStream != null){
|
|
||||||
lockStream.Close();
|
|
||||||
lockStream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Lock(){
|
|
||||||
if (lockStream != null)return true;
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
byte[] bytes = new byte[4];
|
CreateLockFileStream();
|
||||||
|
return Result.Success;
|
||||||
|
}catch{
|
||||||
|
ReleaseLockFileStream();
|
||||||
|
return Result.Fail;
|
||||||
|
}
|
||||||
|
}catch(IOException){
|
||||||
|
return Result.HasProcess;
|
||||||
|
}catch{
|
||||||
|
ReleaseLockFileStream();
|
||||||
|
return Result.Fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result Lock(){
|
||||||
|
if (lockStream != null){
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result initialResult = TryCreateLockFile();
|
||||||
|
|
||||||
|
if (initialResult == Result.HasProcess){
|
||||||
|
try{
|
||||||
|
int pid;
|
||||||
|
|
||||||
using(FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
|
using(FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
|
||||||
fileStream.Read(bytes,0,4);
|
pid = ReadIntFromStream(fileStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pid = BitConverter.ToInt32(bytes,0);
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
Process foundProcess = Process.GetProcessById(pid);
|
Process foundProcess = Process.GetProcessById(pid);
|
||||||
|
|
||||||
using(Process currentProcess = Process.GetCurrentProcess()){
|
using(Process currentProcess = Process.GetCurrentProcess()){
|
||||||
if (foundProcess.ProcessName == currentProcess.ProcessName){
|
if (foundProcess.MainModule.FileVersionInfo.InternalName == currentProcess.MainModule.FileVersionInfo.InternalName){
|
||||||
lockingProcess = foundProcess;
|
LockingProcess = foundProcess;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
foundProcess.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch{
|
||||||
|
// GetProcessById throws ArgumentException if the process is missing
|
||||||
|
// Process.MainModule can throw exceptions in some cases
|
||||||
}
|
}
|
||||||
|
|
||||||
currentProcess.Close();
|
return LockingProcess == null ? Result.Fail : Result.HasProcess;
|
||||||
|
}catch{
|
||||||
|
return Result.Fail;
|
||||||
}
|
}
|
||||||
}catch(ArgumentException){}
|
|
||||||
|
|
||||||
return lockingProcess == null && CreateLockFile();
|
|
||||||
}catch(DirectoryNotFoundException){
|
|
||||||
string dir = Path.GetDirectoryName(file);
|
|
||||||
|
|
||||||
if (dir != null){
|
|
||||||
Directory.CreateDirectory(dir);
|
|
||||||
return CreateLockFile();
|
|
||||||
}
|
|
||||||
}catch(FileNotFoundException){
|
|
||||||
return CreateLockFile();
|
|
||||||
}catch(Exception){
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return initialResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unlock(){
|
public bool Unlock(){
|
||||||
if (lockStream != null){
|
bool result = true;
|
||||||
lockStream.Dispose();
|
|
||||||
|
if (ReleaseLockFileStream()){
|
||||||
|
try{
|
||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
|
}catch(Exception e){
|
||||||
lockStream = null;
|
Program.Reporter.Log(e.ToString());
|
||||||
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CloseLockingProcess(int timeout){
|
return result;
|
||||||
if (lockingProcess != null){
|
|
||||||
lockingProcess.CloseMainWindow();
|
|
||||||
|
|
||||||
for(int waited = 0; waited < timeout && !lockingProcess.HasExited;){
|
|
||||||
lockingProcess.Refresh();
|
|
||||||
|
|
||||||
Thread.Sleep(100);
|
|
||||||
waited += 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lockingProcess.HasExited){
|
public bool CloseLockingProcess(int closeTimeout, int killTimeout){
|
||||||
lockingProcess.Dispose();
|
if (LockingProcess != null){
|
||||||
lockingProcess = null;
|
try{
|
||||||
|
if (LockingProcess.CloseMainWindow()){
|
||||||
|
WindowsUtils.TrySleepUntil(CheckLockingProcessExited, closeTimeout, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LockingProcess.HasExited){
|
||||||
|
LockingProcess.Kill();
|
||||||
|
WindowsUtils.TrySleepUntil(CheckLockingProcessExited, killTimeout, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LockingProcess.HasExited){
|
||||||
|
LockingProcess.Dispose();
|
||||||
|
LockingProcess = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}catch(Exception ex){
|
||||||
|
if (ex is InvalidOperationException || ex is Win32Exception){
|
||||||
|
if (LockingProcess != null){
|
||||||
|
LockingProcess.Refresh();
|
||||||
|
|
||||||
|
bool hasExited = LockingProcess.HasExited;
|
||||||
|
LockingProcess.Dispose();
|
||||||
|
return hasExited;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CheckLockingProcessExited(){
|
||||||
|
LockingProcess.Refresh();
|
||||||
|
return LockingProcess.HasExited;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility functions
|
||||||
|
|
||||||
|
private static void WriteIntToStream(Stream stream, int value){
|
||||||
|
byte[] id = BitConverter.GetBytes(value);
|
||||||
|
stream.Write(id, 0, id.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ReadIntFromStream(Stream stream){
|
||||||
|
byte[] bytes = new byte[4];
|
||||||
|
stream.Read(bytes, 0, 4);
|
||||||
|
return BitConverter.ToInt32(bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetCurrentProcessId(){
|
||||||
|
using(Process process = Process.GetCurrentProcess()){
|
||||||
|
return process.Id;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,76 +4,87 @@ using System.IO;
|
|||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Runtime.Serialization.Formatters.Binary;
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
using TweetDck.Core;
|
using TweetDck.Core;
|
||||||
using TweetDck.Core.Handling;
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Notification;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
using TweetDck.Plugins;
|
||||||
|
|
||||||
namespace TweetDck.Configuration{
|
namespace TweetDck.Configuration{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
sealed class UserConfig{
|
sealed class UserConfig{
|
||||||
private static readonly IFormatter Formatter = new BinaryFormatter(){
|
private static readonly IFormatter Formatter = new BinaryFormatter();
|
||||||
Binder = new SerializationCompatibilityHandler()
|
|
||||||
};
|
|
||||||
|
|
||||||
private const int CurrentFileVersion = 1;
|
private const int CurrentFileVersion = 9;
|
||||||
|
|
||||||
// START OF CONFIGURATION
|
// START OF CONFIGURATION
|
||||||
|
|
||||||
public bool IgnoreMigration { get; set; }
|
public WindowState BrowserWindow { get; set; }
|
||||||
public bool IgnoreUninstallCheck { get; set; }
|
public bool DisplayNotificationColumn { get; set; }
|
||||||
|
|
||||||
public bool IsMaximized { get; set; }
|
|
||||||
public Point WindowLocation { get; set; }
|
|
||||||
public Size WindowSize { get; set; }
|
|
||||||
public bool DisplayNotificationTimer { get; set; }
|
public bool DisplayNotificationTimer { get; set; }
|
||||||
|
public bool NotificationTimerCountDown { get; set; }
|
||||||
|
public bool NotificationSkipOnLinkClick { get; set; }
|
||||||
|
public bool NotificationNonIntrusiveMode { get; set; }
|
||||||
|
|
||||||
public TweetNotification.Duration NotificationDuration { get; set; }
|
|
||||||
public TweetNotification.Position NotificationPosition { get; set; }
|
public TweetNotification.Position NotificationPosition { get; set; }
|
||||||
public Point CustomNotificationPosition { get; set; }
|
public Point CustomNotificationPosition { get; set; }
|
||||||
public int NotificationEdgeDistance { get; set; }
|
public int NotificationEdgeDistance { get; set; }
|
||||||
public int NotificationDisplay { get; set; }
|
public int NotificationDisplay { get; set; }
|
||||||
|
public int NotificationIdlePauseSeconds { get; set; }
|
||||||
|
public int NotificationDurationValue { get; set; }
|
||||||
|
|
||||||
|
public bool EnableSpellCheck { get; set; }
|
||||||
|
public bool ExpandLinksOnHover { get; set; }
|
||||||
|
public bool SwitchAccountSelectors { get; set; }
|
||||||
|
public bool EnableTrayHighlight { get; set; }
|
||||||
|
|
||||||
public bool EnableUpdateCheck { get; set; }
|
public bool EnableUpdateCheck { get; set; }
|
||||||
public string DismissedUpdate { get; set; }
|
public string DismissedUpdate { get; set; }
|
||||||
|
|
||||||
public bool IsCustomWindowLocationSet{
|
[Obsolete] public PluginConfig Plugins { get; set; } // TODO remove eventually
|
||||||
get{
|
public WindowState PluginsWindow { get; set; }
|
||||||
return WindowLocation.X != -32000 && WindowLocation.X != 32000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsCustomNotificationPositionSet{
|
public string CustomCefArgs { get; set; }
|
||||||
get{
|
public string CustomBrowserCSS { get; set; }
|
||||||
return CustomNotificationPosition.X != -32000 && CustomNotificationPosition.X != 32000;
|
public string CustomNotificationCSS { get; set; }
|
||||||
}
|
|
||||||
|
public bool IsCustomNotificationPositionSet => CustomNotificationPosition != ControlExtensions.InvisibleLocation;
|
||||||
|
|
||||||
|
public string NotificationSoundPath{
|
||||||
|
get => string.IsNullOrEmpty(notificationSoundPath) ? string.Empty : notificationSoundPath;
|
||||||
|
set => notificationSoundPath = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MuteNotifications{
|
public bool MuteNotifications{
|
||||||
get{
|
get => muteNotifications;
|
||||||
return muteNotifications;
|
|
||||||
}
|
|
||||||
|
|
||||||
set{
|
set{
|
||||||
if (muteNotifications == value)return;
|
if (muteNotifications != value){
|
||||||
|
|
||||||
muteNotifications = value;
|
muteNotifications = value;
|
||||||
|
MuteToggled?.Invoke(this, new EventArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (MuteToggled != null){
|
public int ZoomLevel{
|
||||||
MuteToggled(this,new EventArgs());
|
get => zoomLevel;
|
||||||
|
|
||||||
|
set{
|
||||||
|
if (zoomLevel != value){
|
||||||
|
zoomLevel = value;
|
||||||
|
ZoomLevelChanged?.Invoke(this, new EventArgs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double ZoomMultiplier => zoomLevel/100.0;
|
||||||
|
|
||||||
public TrayIcon.Behavior TrayBehavior{
|
public TrayIcon.Behavior TrayBehavior{
|
||||||
get{
|
get => trayBehavior;
|
||||||
return trayBehavior;
|
|
||||||
}
|
|
||||||
|
|
||||||
set{
|
set{
|
||||||
if (trayBehavior == value)return;
|
if (trayBehavior != value){
|
||||||
|
|
||||||
trayBehavior = value;
|
trayBehavior = value;
|
||||||
|
TrayBehaviorChanged?.Invoke(this, new EventArgs());
|
||||||
if (TrayBehaviorChanged != null){
|
|
||||||
TrayBehaviorChanged(this,new EventArgs());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,6 +94,9 @@ namespace TweetDck.Configuration{
|
|||||||
[field:NonSerialized]
|
[field:NonSerialized]
|
||||||
public event EventHandler MuteToggled;
|
public event EventHandler MuteToggled;
|
||||||
|
|
||||||
|
[field:NonSerialized]
|
||||||
|
public event EventHandler ZoomLevelChanged;
|
||||||
|
|
||||||
[field:NonSerialized]
|
[field:NonSerialized]
|
||||||
public event EventHandler TrayBehaviorChanged;
|
public event EventHandler TrayBehaviorChanged;
|
||||||
|
|
||||||
@@ -91,19 +105,26 @@ namespace TweetDck.Configuration{
|
|||||||
|
|
||||||
private int fileVersion;
|
private int fileVersion;
|
||||||
private bool muteNotifications;
|
private bool muteNotifications;
|
||||||
|
private int zoomLevel;
|
||||||
|
private string notificationSoundPath;
|
||||||
private TrayIcon.Behavior trayBehavior;
|
private TrayIcon.Behavior trayBehavior;
|
||||||
|
|
||||||
private UserConfig(string file){
|
private UserConfig(string file){
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
IsMaximized = true;
|
BrowserWindow = new WindowState();
|
||||||
|
ZoomLevel = 100;
|
||||||
DisplayNotificationTimer = true;
|
DisplayNotificationTimer = true;
|
||||||
WindowLocation = new Point(-32000,-32000);
|
NotificationNonIntrusiveMode = true;
|
||||||
NotificationDuration = TweetNotification.Duration.Medium;
|
|
||||||
NotificationPosition = TweetNotification.Position.TopRight;
|
NotificationPosition = TweetNotification.Position.TopRight;
|
||||||
CustomNotificationPosition = new Point(-32000,-32000);
|
CustomNotificationPosition = ControlExtensions.InvisibleLocation;
|
||||||
NotificationEdgeDistance = 8;
|
NotificationEdgeDistance = 8;
|
||||||
|
NotificationDurationValue = 25;
|
||||||
EnableUpdateCheck = true;
|
EnableUpdateCheck = true;
|
||||||
|
ExpandLinksOnHover = true;
|
||||||
|
SwitchAccountSelectors = true;
|
||||||
|
EnableTrayHighlight = true;
|
||||||
|
PluginsWindow = new WindowState();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpgradeFile(){
|
private void UpgradeFile(){
|
||||||
@@ -118,6 +139,46 @@ namespace TweetDck.Configuration{
|
|||||||
++fileVersion;
|
++fileVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 1){
|
||||||
|
ExpandLinksOnHover = true;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 2){
|
||||||
|
BrowserWindow = new WindowState();
|
||||||
|
PluginsWindow = new WindowState();
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 3){
|
||||||
|
EnableTrayHighlight = true;
|
||||||
|
NotificationDurationValue = 25;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 4){
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 5){
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 6){
|
||||||
|
NotificationNonIntrusiveMode = true;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 7){
|
||||||
|
ZoomLevel = 100;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 8){
|
||||||
|
SwitchAccountSelectors = true;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
// update the version
|
// update the version
|
||||||
fileVersion = CurrentFileVersion;
|
fileVersion = CurrentFileVersion;
|
||||||
Save();
|
Save();
|
||||||
@@ -142,13 +203,14 @@ namespace TweetDck.Configuration{
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
Program.HandleException("Could not save the configuration file.",e);
|
Program.Reporter.HandleException("Configuration Error", "Could not save the configuration file.", true, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UserConfig Load(string file){
|
public static UserConfig Load(string file){
|
||||||
UserConfig config = null;
|
UserConfig config = null;
|
||||||
|
Exception firstException = null;
|
||||||
|
|
||||||
for(int attempt = 0; attempt < 2; attempt++){
|
for(int attempt = 0; attempt < 2; attempt++){
|
||||||
try{
|
try{
|
||||||
@@ -158,35 +220,31 @@ namespace TweetDck.Configuration{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config != null){
|
config?.UpgradeFile();
|
||||||
config.UpgradeFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}catch(FileNotFoundException){
|
}catch(FileNotFoundException){
|
||||||
|
}catch(DirectoryNotFoundException){
|
||||||
|
break;
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
Program.HandleException("Could not open the configuration file.",e);
|
if (attempt == 0){
|
||||||
|
firstException = e;
|
||||||
|
Program.Reporter.Log(e.ToString());
|
||||||
}
|
}
|
||||||
|
else if (firstException != null){
|
||||||
|
Program.Reporter.HandleException("Configuration Error", "Could not open the backup configuration file. If you continue, you may lose your settings and list of enabled plugins.", true, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstException != null && config == null){
|
||||||
|
Program.Reporter.HandleException("Configuration Error", "Could not open the configuration file.", true, firstException);
|
||||||
}
|
}
|
||||||
|
|
||||||
return config ?? new UserConfig(file);
|
return config ?? new UserConfig(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetBackupFile(string file){
|
public static string GetBackupFile(string file){
|
||||||
return file+".bak";
|
return file+".bak";
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SerializationCompatibilityHandler : SerializationBinder{
|
|
||||||
public override Type BindToType(string assemblyName, string typeName){
|
|
||||||
#if DUCK
|
|
||||||
assemblyName = assemblyName.Replace("TweetDick","TweetDuck");
|
|
||||||
#else
|
|
||||||
assemblyName = assemblyName.Replace("TweetDuck","TweetDick");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typeName = typeName.Replace("TweetDick","TweetDck");
|
|
||||||
return Type.GetType(string.Format("{0}, {1}",typeName,assemblyName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup></configuration>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<packages xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
|
||||||
<package id="cef.redist.x64" version="3.2623.1396" targetFramework="net40-Client" />
|
|
||||||
<package id="cef.redist.x86" version="3.2623.1396" targetFramework="net40-Client" />
|
|
||||||
<package id="CefSharp.Common" version="49.0.0-pre02" targetFramework="net40-Client" />
|
|
||||||
<package id="CefSharp.WinForms" version="49.0.0-pre02" targetFramework="net40-Client" />
|
|
||||||
<package id="Microsoft.VC120.CRT.JetBrains" version="12.0.21005.2" targetFramework="net40-Client" />
|
|
||||||
</packages>
|
|
||||||
19
Core/Bridge/CallbackBridge.cs
Normal file
19
Core/Bridge/CallbackBridge.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Bridge{
|
||||||
|
sealed class CallbackBridge{
|
||||||
|
private readonly Control owner;
|
||||||
|
private readonly Action safeCallback;
|
||||||
|
|
||||||
|
public CallbackBridge(Control owner, Action safeCallback){
|
||||||
|
this.owner = owner;
|
||||||
|
this.safeCallback = safeCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trigger(){
|
||||||
|
owner.InvokeSafe(safeCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
Core/Bridge/PropertyBridge.cs
Normal file
45
Core/Bridge/PropertyBridge.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Bridge{
|
||||||
|
static class PropertyBridge{
|
||||||
|
[Flags]
|
||||||
|
public enum Properties{
|
||||||
|
ExpandLinksOnHover = 1,
|
||||||
|
MuteNotifications = 2,
|
||||||
|
HasCustomNotificationSound = 4,
|
||||||
|
SkipOnLinkClick = 8,
|
||||||
|
SwitchAccountSelectors = 16,
|
||||||
|
AllBrowser = ExpandLinksOnHover | SwitchAccountSelectors | MuteNotifications | HasCustomNotificationSound,
|
||||||
|
AllNotification = ExpandLinksOnHover | SkipOnLinkClick
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateScript(Properties properties){
|
||||||
|
StringBuilder build = new StringBuilder();
|
||||||
|
build.Append("(function(c){");
|
||||||
|
|
||||||
|
if (properties.HasFlag(Properties.ExpandLinksOnHover)){
|
||||||
|
build.Append("c.expandLinksOnHover=").Append(Program.UserConfig.ExpandLinksOnHover ? "true;" : "false;");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.HasFlag(Properties.SwitchAccountSelectors)){
|
||||||
|
build.Append("c.switchAccountSelectors=").Append(Program.UserConfig.SwitchAccountSelectors ? "true;" : "false;");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.HasFlag(Properties.MuteNotifications)){
|
||||||
|
build.Append("c.muteNotifications=").Append(Program.UserConfig.MuteNotifications ? "true;" : "false;");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.HasFlag(Properties.HasCustomNotificationSound)){
|
||||||
|
build.Append("c.hasCustomNotificationSound=").Append(Program.UserConfig.NotificationSoundPath.Length > 0 ? "true;" : "false;");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.HasFlag(Properties.SkipOnLinkClick)){
|
||||||
|
build.Append("c.skipOnLinkClick=").Append(Program.UserConfig.NotificationSkipOnLinkClick ? "true;" : "false;");
|
||||||
|
}
|
||||||
|
|
||||||
|
build.Append("})(window.$TDX=window.$TDX||{})");
|
||||||
|
return build.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
111
Core/Bridge/TweetDeckBridge.cs
Normal file
111
Core/Bridge/TweetDeckBridge.cs
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Notification;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Bridge{
|
||||||
|
sealed class TweetDeckBridge{
|
||||||
|
public static string LastRightClickedLink = string.Empty;
|
||||||
|
public static string LastHighlightedTweet = string.Empty;
|
||||||
|
public static string LastHighlightedQuotedTweet = string.Empty;
|
||||||
|
|
||||||
|
public static void ResetStaticProperties(){
|
||||||
|
LastRightClickedLink = LastHighlightedTweet = LastHighlightedQuotedTweet = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly FormBrowser form;
|
||||||
|
private readonly FormNotificationMain notification;
|
||||||
|
|
||||||
|
public TweetDeckBridge(FormBrowser form, FormNotificationMain notification){
|
||||||
|
this.form = form;
|
||||||
|
this.notification = notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadFontSizeClass(string fsClass){
|
||||||
|
form.InvokeAsyncSafe(() => {
|
||||||
|
TweetNotification.SetFontSizeClass(fsClass);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadNotificationHeadContents(string headContents){
|
||||||
|
form.InvokeAsyncSafe(() => {
|
||||||
|
TweetNotification.SetHeadTag(headContents);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLastRightClickedLink(string link){
|
||||||
|
form.InvokeAsyncSafe(() => LastRightClickedLink = link);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLastHighlightedTweet(string link, string quotedLink){
|
||||||
|
form.InvokeAsyncSafe(() => {
|
||||||
|
LastHighlightedTweet = link;
|
||||||
|
LastHighlightedQuotedTweet = quotedLink;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenContextMenu(){
|
||||||
|
form.InvokeAsyncSafe(form.OpenContextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnTweetPopup(string columnName, string tweetHtml, int tweetCharacters, string tweetUrl, string quoteUrl){
|
||||||
|
notification.InvokeAsyncSafe(() => {
|
||||||
|
form.OnTweetNotification();
|
||||||
|
notification.ShowNotification(new TweetNotification(columnName, tweetHtml, tweetCharacters, tweetUrl, quoteUrl));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnTweetSound(){
|
||||||
|
form.InvokeAsyncSafe(() => {
|
||||||
|
form.OnTweetNotification();
|
||||||
|
form.PlayNotificationSound();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisplayTooltip(string text, bool showInNotification){
|
||||||
|
if (showInNotification){
|
||||||
|
notification.InvokeAsyncSafe(() => notification.DisplayTooltip(text));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
form.InvokeAsyncSafe(() => form.DisplayTooltip(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadNextNotification(){
|
||||||
|
notification.InvokeAsyncSafe(notification.FinishCurrentNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScreenshotTweet(string html, int width, int height){
|
||||||
|
form.InvokeAsyncSafe(() => form.OnTweetScreenshotReady(html, width, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FixClipboard(){
|
||||||
|
form.InvokeAsyncSafe(WindowsUtils.ClipboardStripHtmlStyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetIdleSeconds(){
|
||||||
|
return NativeMethods.GetIdleSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenBrowser(string url){
|
||||||
|
BrowserUtils.OpenExternalBrowser(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Alert(string type, string contents){
|
||||||
|
MessageBoxIcon icon;
|
||||||
|
|
||||||
|
switch(type){
|
||||||
|
case "error": icon = MessageBoxIcon.Error; break;
|
||||||
|
case "warning": icon = MessageBoxIcon.Warning; break;
|
||||||
|
case "info": icon = MessageBoxIcon.Information; break;
|
||||||
|
default: icon = MessageBoxIcon.None; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBox.Show(contents, Program.BrandName+" Browser Message", MessageBoxButtons.OK, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(string data){
|
||||||
|
System.Diagnostics.Debug.WriteLine(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,30 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Controls{
|
namespace TweetDck.Core.Controls{
|
||||||
static class ControlExtensions{
|
static class ControlExtensions{
|
||||||
public static void InvokeSafe(this Form form, Action func){
|
public static readonly Point InvisibleLocation = new Point(-32000, -32000);
|
||||||
if (form.InvokeRequired){
|
|
||||||
form.Invoke(func);
|
public static void InvokeSafe(this Control control, Action func){
|
||||||
|
if (control.InvokeRequired){
|
||||||
|
control.Invoke(func);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void InvokeAsyncSafe(this Control control, Action func){
|
||||||
|
control.BeginInvoke(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsFullyOutsideView(this Form form){
|
||||||
|
return !Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(form.Bounds));
|
||||||
|
}
|
||||||
|
|
||||||
public static void MoveToCenter(this Form targetForm, Form parentForm){
|
public static void MoveToCenter(this Form targetForm, Form parentForm){
|
||||||
targetForm.Location = new Point(parentForm.Location.X+parentForm.Width/2-targetForm.Width/2, parentForm.Location.Y+parentForm.Height/2-targetForm.Height/2);
|
targetForm.Location = new Point(parentForm.Location.X+parentForm.Width/2-targetForm.Width/2, parentForm.Location.Y+parentForm.Height/2-targetForm.Height/2);
|
||||||
}
|
}
|
||||||
@@ -28,5 +40,27 @@ namespace TweetDck.Core.Controls{
|
|||||||
bar.Value = value;
|
bar.Value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetValueSafe(this TrackBar trackBar, int value){
|
||||||
|
if (value >= trackBar.Minimum && value <= trackBar.Maximum){
|
||||||
|
trackBar.Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetElevated(this Button button){
|
||||||
|
button.Text = " "+button.Text;
|
||||||
|
button.FlatStyle = FlatStyle.System;
|
||||||
|
NativeMethods.SendMessage(button.Handle, NativeMethods.BCM_SETSHIELD, 0, new IntPtr(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnableMultilineShortcuts(this TextBox textBox){
|
||||||
|
textBox.KeyDown += (sender, args) => {
|
||||||
|
if (args.Control && args.KeyCode == Keys.A){
|
||||||
|
((TextBox)sender).SelectAll();
|
||||||
|
args.SuppressKeyPress = true;
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
Core/Controls/FlatButton.cs
Normal file
16
Core/Controls/FlatButton.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Controls{
|
||||||
|
class FlatButton : Button{
|
||||||
|
protected override bool ShowFocusCues => false;
|
||||||
|
|
||||||
|
public FlatButton(){
|
||||||
|
GotFocus += FlatButton_GotFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FlatButton_GotFocus(object sender, EventArgs e){ // removes extra border when focused
|
||||||
|
NotifyDefault(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
Core/Controls/FlatProgressBar.Designer.cs
generated
33
Core/Controls/FlatProgressBar.Designer.cs
generated
@@ -1,33 +0,0 @@
|
|||||||
namespace TweetDck.Core.Controls {
|
|
||||||
partial class FlatProgressBar {
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing) {
|
|
||||||
if (brush != null)brush.Dispose();
|
|
||||||
|
|
||||||
if (disposing && (components != null)) {
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Component Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent() {
|
|
||||||
components = new System.ComponentModel.Container();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,10 +2,12 @@
|
|||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDck.Core.Controls{
|
namespace TweetDck.Core.Controls{
|
||||||
public partial class FlatProgressBar : ProgressBar{
|
sealed class FlatProgressBar : ProgressBar{
|
||||||
private SolidBrush brush;
|
private readonly SolidBrush brush;
|
||||||
|
|
||||||
public FlatProgressBar(){
|
public FlatProgressBar(){
|
||||||
|
brush = new SolidBrush(Color.White);
|
||||||
|
|
||||||
SetStyle(ControlStyles.UserPaint, true);
|
SetStyle(ControlStyles.UserPaint, true);
|
||||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||||
}
|
}
|
||||||
@@ -15,13 +17,21 @@ namespace TweetDck.Core.Controls{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPaint(PaintEventArgs e){
|
protected override void OnPaint(PaintEventArgs e){
|
||||||
if (brush == null || brush.Color != ForeColor){
|
if (brush.Color != ForeColor){
|
||||||
brush = new SolidBrush(ForeColor);
|
brush.Color = ForeColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle rect = e.ClipRectangle;
|
Rectangle rect = e.ClipRectangle;
|
||||||
rect.Width = (int)(rect.Width*((double)Value/Maximum));
|
rect.Width = (int)(rect.Width*((double)Value/Maximum));
|
||||||
e.Graphics.FillRectangle(brush,rect);
|
e.Graphics.FillRectangle(brush,rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing){
|
||||||
|
base.Dispose(disposing);
|
||||||
|
|
||||||
|
if (disposing){
|
||||||
|
brush.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
Core/Controls/RichTextLabel.Designer.cs
generated
41
Core/Controls/RichTextLabel.Designer.cs
generated
@@ -1,41 +0,0 @@
|
|||||||
namespace TweetDck.Core.Controls {
|
|
||||||
partial class RichTextLabel {
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing) {
|
|
||||||
if (disposing && (components != null)) {
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Component Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent() {
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// RichTextLabel
|
|
||||||
//
|
|
||||||
this.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
|
||||||
this.ReadOnly = true;
|
|
||||||
this.TabStop = false;
|
|
||||||
this.MouseEnter += new System.EventHandler(this.RichTextLabel_MouseEnter);
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Controls{
|
|
||||||
public partial class RichTextLabel : RichTextBox{
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps the body of a RTF formatted string with default tags and formatting.
|
|
||||||
/// </summary>
|
|
||||||
public static string Wrap(string str){
|
|
||||||
string rtf = @"{\rtf1\ansi\ansicpg1250\deff0\deflang1029{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}";
|
|
||||||
rtf += @"{\*\generator Msftedit 4.20.69.1337;}\viewkind4\uc1\pard\sa200\sl276\slmult1\lang1036\f0\fs16 ";
|
|
||||||
rtf += str;
|
|
||||||
return rtf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps URL tags around a link.
|
|
||||||
/// </summary>
|
|
||||||
public static string AddLink(string url){
|
|
||||||
return @"{\field{\*\fldinst{HYPERLINK """+url+@"""}}{\fldrslt{\ul\cf1 "+url+@"}}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uses v5 of RichTextBox, which fixes URLs and other crap.
|
|
||||||
/// </summary>
|
|
||||||
protected override CreateParams CreateParams{
|
|
||||||
get{
|
|
||||||
CreateParams createParams = base.CreateParams;
|
|
||||||
|
|
||||||
if (Program.LoadLibrary("msftedit.dll") != IntPtr.Zero){
|
|
||||||
createParams.ClassName = "RICHEDIT50W";
|
|
||||||
}
|
|
||||||
|
|
||||||
return createParams;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RichTextLabel(){
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
SetStyle(ControlStyles.Selectable,false);
|
|
||||||
SetStyle(ControlStyles.UserMouse,true);
|
|
||||||
SetStyle(ControlStyles.SupportsTransparentBackColor,true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RichTextLabel_MouseEnter(object sender, EventArgs e){
|
|
||||||
Cursor = Cursors.Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void WndProc(ref Message m){
|
|
||||||
if (m.Msg == 0x204 || m.Msg == 0x205){ // WM_RBUTTONDOWN, WM_RBUTTONUP
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.WndProc(ref m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
25
Core/Controls/TabButton.cs
Normal file
25
Core/Controls/TabButton.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Controls{
|
||||||
|
sealed class TabButton : FlatButton{
|
||||||
|
public Action Callback { get; private set; }
|
||||||
|
|
||||||
|
public void SetupButton(int locationX, int sizeWidth, string title, Action callback){
|
||||||
|
Callback = callback;
|
||||||
|
|
||||||
|
SuspendLayout();
|
||||||
|
FlatAppearance.BorderColor = Color.DimGray;
|
||||||
|
FlatAppearance.MouseDownBackColor = Color.White;
|
||||||
|
FlatAppearance.MouseOverBackColor = Color.White;
|
||||||
|
FlatStyle = FlatStyle.Flat;
|
||||||
|
Location = new Point(locationX, 0);
|
||||||
|
Margin = new Padding(0);
|
||||||
|
Size = new Size(sizeWidth, 30);
|
||||||
|
Text = title;
|
||||||
|
UseVisualStyleBackColor = true;
|
||||||
|
ResumeLayout(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
68
Core/Controls/TabPanel.Designer.cs
generated
Normal file
68
Core/Controls/TabPanel.Designer.cs
generated
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
namespace TweetDck.Core.Controls {
|
||||||
|
partial class TabPanel {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.panelButtons = new System.Windows.Forms.Panel();
|
||||||
|
this.panelContent = new System.Windows.Forms.Panel();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// panelButtons
|
||||||
|
//
|
||||||
|
this.panelButtons.Dock = System.Windows.Forms.DockStyle.Top;
|
||||||
|
this.panelButtons.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.panelButtons.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.panelButtons.Name = "panelButtons";
|
||||||
|
this.panelButtons.Size = new System.Drawing.Size(640, 30);
|
||||||
|
this.panelButtons.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// panelContent
|
||||||
|
//
|
||||||
|
this.panelContent.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelContent.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||||
|
this.panelContent.Location = new System.Drawing.Point(0, 29);
|
||||||
|
this.panelContent.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.panelContent.Name = "panelContent";
|
||||||
|
this.panelContent.Size = new System.Drawing.Size(640, 451);
|
||||||
|
this.panelContent.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// TabPanel
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.panelContent);
|
||||||
|
this.Controls.Add(this.panelButtons);
|
||||||
|
this.Name = "TabPanel";
|
||||||
|
this.Size = new System.Drawing.Size(640, 480);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Panel panelButtons;
|
||||||
|
private System.Windows.Forms.Panel panelContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Core/Controls/TabPanel.cs
Normal file
52
Core/Controls/TabPanel.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Controls{
|
||||||
|
sealed partial class TabPanel : UserControl{
|
||||||
|
public Panel Content => panelContent;
|
||||||
|
public IEnumerable<TabButton> Buttons => panelButtons.Controls.Cast<TabButton>();
|
||||||
|
|
||||||
|
public TabButton ActiveButton { get; private set; }
|
||||||
|
|
||||||
|
private int btnWidth;
|
||||||
|
|
||||||
|
public TabPanel(){
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetupTabPanel(int buttonWidth){
|
||||||
|
this.btnWidth = buttonWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TabButton AddButton(string title, Action callback){
|
||||||
|
TabButton button = new TabButton();
|
||||||
|
button.SetupButton((btnWidth-1)*panelButtons.Controls.Count, btnWidth, title, callback);
|
||||||
|
button.Click += (sender, args) => SelectTab((TabButton)sender);
|
||||||
|
|
||||||
|
panelButtons.Controls.Add(button);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectTab(TabButton button){
|
||||||
|
if (ActiveButton != null){
|
||||||
|
ActiveButton.BackColor = SystemColors.Control;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.BackColor = Color.White;
|
||||||
|
button.Callback();
|
||||||
|
|
||||||
|
ActiveButton = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReplaceContent(Control newControl){
|
||||||
|
newControl.Dock = DockStyle.Fill;
|
||||||
|
Content.SuspendLayout();
|
||||||
|
Content.Controls.Clear();
|
||||||
|
Content.Controls.Add(newControl);
|
||||||
|
Content.ResumeLayout(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Core/FormBrowser.Designer.cs
generated
18
Core/FormBrowser.Designer.cs
generated
@@ -23,22 +23,23 @@
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.trayIcon = new TweetDck.Core.TrayIcon();
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.trayIcon = new TweetDck.Core.TrayIcon(this.components);
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// trayIcon
|
|
||||||
//
|
|
||||||
this.trayIcon.Visible = false;
|
|
||||||
//
|
|
||||||
// FormBrowser
|
// FormBrowser
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(284, 262);
|
this.BackColor = TweetDck.Core.Utils.BrowserUtils.BackgroundColor;
|
||||||
this.Icon = ((System.Drawing.Icon)(TweetDck.Properties.Resources.ResourceManager.GetObject("icon")));
|
this.ClientSize = new System.Drawing.Size(324, 386);
|
||||||
this.Location = new System.Drawing.Point(-32000, -32000);
|
this.Icon = Properties.Resources.icon;
|
||||||
|
this.Location = TweetDck.Core.Controls.ControlExtensions.InvisibleLocation;
|
||||||
|
this.MinimumSize = new System.Drawing.Size(340, 424);
|
||||||
this.Name = "FormBrowser";
|
this.Name = "FormBrowser";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
|
this.Activated += new System.EventHandler(this.FormBrowser_Activated);
|
||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing);
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing);
|
||||||
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
|
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
|
||||||
this.Resize += new System.EventHandler(this.FormBrowser_Resize);
|
this.Resize += new System.EventHandler(this.FormBrowser_Resize);
|
||||||
@@ -49,6 +50,7 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private TrayIcon trayIcon;
|
private TrayIcon trayIcon;
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,107 +1,217 @@
|
|||||||
using System;
|
using CefSharp;
|
||||||
|
using CefSharp.WinForms;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using CefSharp;
|
|
||||||
using CefSharp.WinForms;
|
|
||||||
using TweetDck.Configuration;
|
using TweetDck.Configuration;
|
||||||
using TweetDck.Core.Handling;
|
using TweetDck.Core.Bridge;
|
||||||
using TweetDck.Core.Other;
|
|
||||||
using TweetDck.Resources;
|
|
||||||
using TweetDck.Core.Utils;
|
|
||||||
using TweetDck.Core.Controls;
|
using TweetDck.Core.Controls;
|
||||||
using System.ComponentModel;
|
using TweetDck.Core.Handling;
|
||||||
|
using TweetDck.Core.Notification;
|
||||||
|
using TweetDck.Core.Notification.Screenshot;
|
||||||
|
using TweetDck.Core.Notification.Sound;
|
||||||
|
using TweetDck.Core.Other;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
using TweetDck.Plugins;
|
||||||
|
using TweetDck.Plugins.Enums;
|
||||||
|
using TweetDck.Plugins.Events;
|
||||||
|
using TweetDck.Resources;
|
||||||
|
using TweetDck.Updates;
|
||||||
|
using TweetDck.Updates.Events;
|
||||||
|
|
||||||
namespace TweetDck.Core{
|
namespace TweetDck.Core{
|
||||||
sealed partial class FormBrowser : Form{
|
sealed partial class FormBrowser : Form{
|
||||||
private static UserConfig Config{
|
private static UserConfig Config => Program.UserConfig;
|
||||||
get{
|
|
||||||
return Program.UserConfig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string UpdateInstallerPath { get; private set; }
|
public string UpdateInstallerPath { get; private set; }
|
||||||
|
|
||||||
private readonly ChromiumWebBrowser browser;
|
private readonly ChromiumWebBrowser browser;
|
||||||
private readonly TweetDeckBridge bridge;
|
private readonly PluginManager plugins;
|
||||||
private readonly FormNotification notification;
|
private readonly UpdateHandler updates;
|
||||||
|
private readonly FormNotificationTweet notification;
|
||||||
|
private readonly ContextMenu contextMenu;
|
||||||
|
|
||||||
private FormSettings currentFormSettings;
|
|
||||||
private FormAbout currentFormAbout;
|
|
||||||
private bool isLoaded;
|
private bool isLoaded;
|
||||||
|
private bool isBrowserReady;
|
||||||
private FormWindowState prevState;
|
private FormWindowState prevState;
|
||||||
|
|
||||||
public FormBrowser(){
|
private TweetScreenshotManager notificationScreenshotManager;
|
||||||
|
private ISoundNotificationPlayer soundNotification;
|
||||||
|
|
||||||
|
public FormBrowser(PluginManager pluginManager, UpdaterSettings updaterSettings){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Text = Program.BrandName;
|
Text = Program.BrandName;
|
||||||
|
|
||||||
bridge = new TweetDeckBridge(this);
|
this.plugins = pluginManager;
|
||||||
|
this.plugins.Reloaded += plugins_Reloaded;
|
||||||
|
this.plugins.PluginChangedState += plugins_PluginChangedState;
|
||||||
|
|
||||||
browser = new ChromiumWebBrowser("https://tweetdeck.twitter.com/"){ MenuHandler = new ContextMenuBrowser(this) };
|
this.contextMenu = ContextMenuBrowser.CreateMenu(this);
|
||||||
browser.LoadingStateChanged += Browser_LoadingStateChanged;
|
|
||||||
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
|
||||||
browser.RegisterJsObject("$TD",bridge);
|
|
||||||
|
|
||||||
|
this.notification = new FormNotificationTweet(this, plugins){
|
||||||
|
#if DEBUG
|
||||||
|
CanMoveWindow = () => (ModifierKeys & Keys.Alt) == Keys.Alt
|
||||||
|
#else
|
||||||
|
CanMoveWindow = () => false
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
this.notification.Show();
|
||||||
|
|
||||||
|
this.browser = new ChromiumWebBrowser("https://tweetdeck.twitter.com/"){
|
||||||
|
MenuHandler = new ContextMenuBrowser(this),
|
||||||
|
JsDialogHandler = new JavaScriptDialogHandler(),
|
||||||
|
LifeSpanHandler = new LifeSpanHandler()
|
||||||
|
};
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
this.browser.ConsoleMessage += BrowserUtils.HandleConsoleMessage;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
this.browser.LoadingStateChanged += browser_LoadingStateChanged;
|
||||||
|
this.browser.FrameLoadStart += browser_FrameLoadStart;
|
||||||
|
this.browser.FrameLoadEnd += browser_FrameLoadEnd;
|
||||||
|
this.browser.LoadError += browser_LoadError;
|
||||||
|
this.browser.RegisterAsyncJsObject("$TD", new TweetDeckBridge(this, notification));
|
||||||
|
this.browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
|
||||||
|
|
||||||
|
browser.BrowserSettings.BackgroundColor = (uint)BrowserUtils.BackgroundColor.ToArgb();
|
||||||
|
browser.Dock = DockStyle.None;
|
||||||
|
browser.Location = ControlExtensions.InvisibleLocation;
|
||||||
Controls.Add(browser);
|
Controls.Add(browser);
|
||||||
|
|
||||||
Disposed += (sender, args) => browser.Dispose();
|
Controls.Add(new MenuStrip{ Visible = false }); // fixes Alt freezing the program in Win 10 Anniversary Update
|
||||||
|
|
||||||
trayIcon.ClickRestore += trayIcon_ClickRestore;
|
Disposed += (sender, args) => {
|
||||||
trayIcon.ClickClose += trayIcon_ClickClose;
|
browser.Dispose();
|
||||||
|
contextMenu.Dispose();
|
||||||
|
|
||||||
|
notificationScreenshotManager?.Dispose();
|
||||||
|
soundNotification?.Dispose();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.trayIcon.ClickRestore += trayIcon_ClickRestore;
|
||||||
|
this.trayIcon.ClickClose += trayIcon_ClickClose;
|
||||||
Config.TrayBehaviorChanged += Config_TrayBehaviorChanged;
|
Config.TrayBehaviorChanged += Config_TrayBehaviorChanged;
|
||||||
|
|
||||||
UpdateTrayIcon();
|
UpdateTrayIcon();
|
||||||
|
|
||||||
notification = new FormNotification(this,bridge,true){ CanMoveWindow = () => false };
|
Config.MuteToggled += Config_MuteToggled;
|
||||||
notification.Show();
|
Config.ZoomLevelChanged += Config_ZoomLevelChanged;
|
||||||
|
|
||||||
|
this.updates = new UpdateHandler(browser, this, updaterSettings);
|
||||||
|
this.updates.UpdateAccepted += updates_UpdateAccepted;
|
||||||
|
this.updates.UpdateDismissed += updates_UpdateDismissed;
|
||||||
|
|
||||||
|
RestoreWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryBringToFront<T>() where T : Form{
|
||||||
|
T form = Application.OpenForms.OfType<T>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (form != null){
|
||||||
|
form.BringToFront();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowChildForm(Form form){
|
private void ShowChildForm(Form form){
|
||||||
|
form.VisibleChanged += (sender, args) => form.MoveToCenter(this);
|
||||||
form.Show(this);
|
form.Show(this);
|
||||||
form.MoveToCenter(this);
|
}
|
||||||
|
|
||||||
|
public void ForceClose(){
|
||||||
|
trayIcon.Visible = false; // checked in FormClosing event
|
||||||
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// window setup
|
// window setup
|
||||||
|
|
||||||
private void SetupWindow(){
|
private void RestoreWindow(){
|
||||||
if (Config.IsCustomWindowLocationSet){
|
Config.BrowserWindow.Restore(this, true);
|
||||||
Location = Config.WindowLocation;
|
|
||||||
Size = Config.WindowSize;
|
|
||||||
WindowState = Config.IsMaximized ? FormWindowState.Maximized : FormWindowState.Normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Config.IsCustomWindowLocationSet || !Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(Bounds))){
|
|
||||||
Location = Screen.PrimaryScreen.WorkingArea.Location;
|
|
||||||
Size = Screen.PrimaryScreen.WorkingArea.Size;
|
|
||||||
WindowState = FormWindowState.Maximized;
|
|
||||||
}
|
|
||||||
|
|
||||||
prevState = WindowState;
|
prevState = WindowState;
|
||||||
isLoaded = true;
|
isLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnBrowserReady(){
|
||||||
|
if (!isBrowserReady){
|
||||||
|
browser.Location = Point.Empty;
|
||||||
|
browser.Dock = DockStyle.Fill;
|
||||||
|
isBrowserReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateTrayIcon(){
|
private void UpdateTrayIcon(){
|
||||||
trayIcon.Visible = Config.TrayBehavior != TrayIcon.Behavior.Disabled;
|
trayIcon.Visible = Config.TrayBehavior.ShouldDisplayIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
// active event handlers
|
// active event handlers
|
||||||
|
|
||||||
private void Browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e){
|
private void browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e){
|
||||||
if (!e.IsLoading){
|
if (!e.IsLoading){
|
||||||
Invoke(new Action(SetupWindow));
|
foreach(string word in BrowserUtils.DictionaryWords){
|
||||||
browser.LoadingStateChanged -= Browser_LoadingStateChanged;
|
browser.AddWordToDictionary(word);
|
||||||
|
}
|
||||||
|
|
||||||
|
BeginInvoke(new Action(OnBrowserReady));
|
||||||
|
browser.LoadingStateChanged -= browser_LoadingStateChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
private void browser_FrameLoadStart(object sender, FrameLoadStartEventArgs e){
|
||||||
if (e.Frame.IsMain){
|
if (e.Frame.IsMain){
|
||||||
foreach(string js in ScriptLoader.LoadResources("code.js","update.js").Where(js => js != null)){
|
if (Config.ZoomLevel != 100){
|
||||||
browser.ExecuteScriptAsync(js);
|
BrowserUtils.SetZoomLevel(browser.GetBrowser(), Config.ZoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BrowserUtils.IsTwitterWebsite(e.Frame)){
|
||||||
|
ScriptLoader.ExecuteFile(e.Frame, "twitter.js");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
||||||
|
if (e.Frame.IsMain && BrowserUtils.IsTweetDeckWebsite(e.Frame)){
|
||||||
|
e.Frame.ExecuteJavaScriptAsync(BrowserUtils.BackgroundColorFix);
|
||||||
|
|
||||||
|
UpdateProperties(PropertyBridge.Properties.AllBrowser);
|
||||||
|
ScriptLoader.ExecuteFile(e.Frame, "code.js");
|
||||||
|
ReinjectCustomCSS(Config.CustomBrowserCSS);
|
||||||
|
|
||||||
|
if (plugins.HasAnyPlugin(PluginEnvironment.Browser)){
|
||||||
|
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginBrowserScriptFile);
|
||||||
|
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginGlobalScriptFile);
|
||||||
|
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Browser, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TweetDeckBridge.ResetStaticProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void browser_LoadError(object sender, LoadErrorEventArgs e){
|
||||||
|
if (e.ErrorCode == CefErrorCode.Aborted){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e.FailedUrl.StartsWith("http://td/")){
|
||||||
|
string errorPage = ScriptLoader.LoadResource("pages/error.html", true);
|
||||||
|
|
||||||
|
if (errorPage != null){
|
||||||
|
browser.LoadHtml(errorPage.Replace("{err}", BrowserUtils.GetErrorName(e.ErrorCode)), "http://td/error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FormBrowser_Activated(object sender, EventArgs e){
|
||||||
|
if (!isLoaded)return;
|
||||||
|
|
||||||
|
trayIcon.HasNotifications = false;
|
||||||
|
}
|
||||||
|
|
||||||
private void FormBrowser_Resize(object sender, EventArgs e){
|
private void FormBrowser_Resize(object sender, EventArgs e){
|
||||||
if (!isLoaded)return;
|
if (!isLoaded)return;
|
||||||
|
|
||||||
@@ -109,7 +219,7 @@ namespace TweetDck.Core{
|
|||||||
prevState = WindowState;
|
prevState = WindowState;
|
||||||
|
|
||||||
if (WindowState == FormWindowState.Minimized){
|
if (WindowState == FormWindowState.Minimized){
|
||||||
if (Config.TrayBehavior == TrayIcon.Behavior.MinimizeToTray){
|
if (Config.TrayBehavior.ShouldHideOnMinimize()){
|
||||||
Hide(); // hides taskbar too?! welp that works I guess
|
Hide(); // hides taskbar too?! welp that works I guess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,14 +232,8 @@ namespace TweetDck.Core{
|
|||||||
private void FormBrowser_ResizeEnd(object sender, EventArgs e){ // also triggers when the window moves
|
private void FormBrowser_ResizeEnd(object sender, EventArgs e){ // also triggers when the window moves
|
||||||
if (!isLoaded)return;
|
if (!isLoaded)return;
|
||||||
|
|
||||||
if (Location.X != -32000){
|
if (Location != ControlExtensions.InvisibleLocation){
|
||||||
Config.IsMaximized = WindowState == FormWindowState.Maximized;
|
Config.BrowserWindow.Save(this);
|
||||||
|
|
||||||
if (WindowState == FormWindowState.Normal){
|
|
||||||
Config.WindowLocation = Location;
|
|
||||||
Config.WindowSize = Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
Config.Save();
|
Config.Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,101 +241,223 @@ namespace TweetDck.Core{
|
|||||||
private void FormBrowser_FormClosing(object sender, FormClosingEventArgs e){
|
private void FormBrowser_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
if (!isLoaded)return;
|
if (!isLoaded)return;
|
||||||
|
|
||||||
if (Config.TrayBehavior == TrayIcon.Behavior.CloseToTray && trayIcon.Visible && e.CloseReason == CloseReason.UserClosing){
|
if (Config.TrayBehavior.ShouldHideOnClose() && trayIcon.Visible && e.CloseReason == CloseReason.UserClosing){
|
||||||
Hide(); // hides taskbar too?! welp that works I guess
|
Hide(); // hides taskbar too?! welp that works I guess
|
||||||
e.Cancel = true;
|
e.Cancel = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Config_TrayBehaviorChanged(object sender, EventArgs e){
|
private void Config_MuteToggled(object sender, EventArgs e){
|
||||||
if (!isLoaded)return;
|
UpdateProperties(PropertyBridge.Properties.MuteNotifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Config_ZoomLevelChanged(object sender, EventArgs e){
|
||||||
|
BrowserUtils.SetZoomLevel(browser.GetBrowser(), Config.ZoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Config_TrayBehaviorChanged(object sender, EventArgs e){
|
||||||
UpdateTrayIcon();
|
UpdateTrayIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trayIcon_ClickRestore(object sender, EventArgs e){
|
private void trayIcon_ClickRestore(object sender, EventArgs e){
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
isLoaded = false;
|
|
||||||
Show();
|
Show();
|
||||||
SetupWindow();
|
RestoreWindow();
|
||||||
Activate();
|
Activate();
|
||||||
UpdateTrayIcon();
|
UpdateTrayIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trayIcon_ClickClose(object sender, EventArgs e){
|
private void trayIcon_ClickClose(object sender, EventArgs e){
|
||||||
if (!isLoaded)return;
|
ForceClose();
|
||||||
|
|
||||||
trayIcon.Visible = false; // checked in FormClosing event
|
|
||||||
Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// callback handlers
|
private void plugins_Reloaded(object sender, PluginErrorEventArgs e){
|
||||||
|
browser.GetBrowser().Reload();
|
||||||
public void InvokeSafe(Action func){
|
|
||||||
ControlExtensions.InvokeSafe(this,func);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenSettings(){
|
private void plugins_PluginChangedState(object sender, PluginChangedStateEventArgs e){
|
||||||
if (currentFormSettings != null){
|
browser.ExecuteScriptAsync("window.TDPF_setPluginState", e.Plugin, e.IsEnabled);
|
||||||
currentFormSettings.BringToFront();
|
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
bool prevEnableUpdateCheck = Config.EnableUpdateCheck;
|
|
||||||
|
|
||||||
currentFormSettings = new FormSettings(this);
|
private void updates_UpdateAccepted(object sender, UpdateAcceptedEventArgs e){
|
||||||
|
foreach(Form form in Application.OpenForms.Cast<Form>().Reverse()){
|
||||||
currentFormSettings.FormClosed += (sender, args) => {
|
if (form is FormSettings || form is FormPlugins || form is FormAbout){
|
||||||
currentFormSettings = null;
|
form.Close();
|
||||||
|
|
||||||
if (!prevEnableUpdateCheck && Config.EnableUpdateCheck){
|
|
||||||
Config.DismissedUpdate = string.Empty;
|
|
||||||
Config.Save();
|
|
||||||
|
|
||||||
browser.ExecuteScriptAsync("TDGF_runUpdateCheck",new object[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ShowChildForm(currentFormSettings);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenAbout(){
|
|
||||||
if (currentFormAbout != null){
|
|
||||||
currentFormAbout.BringToFront();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
currentFormAbout = new FormAbout();
|
|
||||||
currentFormAbout.FormClosed += (sender, args) => currentFormAbout = null;
|
|
||||||
ShowChildForm(currentFormAbout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnTweetPopup(TweetNotification tweet){
|
|
||||||
notification.ShowNotification(tweet);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnTweetSound(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BeginUpdateProcess(string versionTag, string downloadUrl){
|
|
||||||
Hide();
|
Hide();
|
||||||
|
|
||||||
FormUpdateDownload downloadForm = new FormUpdateDownload(new UpdateInfo(versionTag,downloadUrl));
|
FormUpdateDownload downloadForm = new FormUpdateDownload(e.UpdateInfo);
|
||||||
downloadForm.MoveToCenter(this);
|
downloadForm.MoveToCenter(this);
|
||||||
downloadForm.ShowDialog();
|
downloadForm.ShowDialog();
|
||||||
|
downloadForm.Dispose();
|
||||||
|
|
||||||
if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Succeeded){
|
if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Succeeded){
|
||||||
UpdateInstallerPath = downloadForm.InstallerPath;
|
UpdateInstallerPath = downloadForm.InstallerPath;
|
||||||
Close();
|
ForceClose();
|
||||||
}
|
}
|
||||||
else if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Manual){
|
else if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Manual){
|
||||||
Close();
|
ForceClose();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
Show();
|
Show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updates_UpdateDismissed(object sender, UpdateDismissedEventArgs e){
|
||||||
|
Config.DismissedUpdate = e.VersionTag;
|
||||||
|
Config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void soundNotification_PlaybackError(object sender, PlaybackErrorEventArgs e){
|
||||||
|
e.Ignore = true;
|
||||||
|
|
||||||
|
using(FormMessage form = new FormMessage("Notification Sound Error", "Could not play custom notification sound."+Environment.NewLine+e.Message, MessageBoxIcon.Error)){
|
||||||
|
form.CancelButton = form.AddButton("Ignore");
|
||||||
|
|
||||||
|
Button btnOpenSettings = form.AddButton("Open Settings");
|
||||||
|
btnOpenSettings.Width += 16;
|
||||||
|
btnOpenSettings.Location = new Point(btnOpenSettings.Location.X-16, btnOpenSettings.Location.Y);
|
||||||
|
|
||||||
|
if (form.ShowDialog() == DialogResult.OK && form.ClickedButton == btnOpenSettings){
|
||||||
|
OpenSettings(FormSettings.TabIndexNotification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void WndProc(ref Message m){
|
||||||
|
if (isLoaded && m.Msg == Program.WindowRestoreMessage){
|
||||||
|
using(Process process = Process.GetCurrentProcess()){
|
||||||
|
if (process.Id == m.WParam.ToInt32()){
|
||||||
|
trayIcon_ClickRestore(trayIcon, new EventArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBrowserReady && m.Msg == NativeMethods.WM_PARENTNOTIFY && (m.WParam.ToInt32() & 0xFFFF) == NativeMethods.WM_XBUTTONDOWN){
|
||||||
|
browser.ExecuteScriptAsync("TDGF_onMouseClickExtra", (m.WParam.ToInt32() >> 16) & 0xFFFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.WndProc(ref m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// notification helpers
|
||||||
|
|
||||||
|
public FormNotificationMain CreateNotificationForm(bool enableContextMenu){
|
||||||
|
return new FormNotificationMain(this, plugins, enableContextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PauseNotification(){
|
||||||
|
notification.PauseNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResumeNotification(){
|
||||||
|
notification.ResumeNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
// javascript calls
|
||||||
|
|
||||||
|
public void ReinjectCustomCSS(string css){
|
||||||
|
browser.ExecuteScriptAsync("TDGF_reinjectCustomCSS", css?.Replace(Environment.NewLine, " ") ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateProperties(PropertyBridge.Properties properties){
|
||||||
|
browser.ExecuteScriptAsync(PropertyBridge.GenerateScript(properties));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReloadToTweetDeck(){
|
||||||
|
browser.ExecuteScriptAsync("window.location.href = 'https://tweetdeck.twitter.com'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback handlers
|
||||||
|
|
||||||
|
public void OpenContextMenu(){
|
||||||
|
contextMenu.Show(this, PointToClient(Cursor.Position));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenSettings(){
|
||||||
|
OpenSettings(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenSettings(int tabIndex){
|
||||||
|
if (!TryBringToFront<FormSettings>()){
|
||||||
|
bool prevEnableUpdateCheck = Config.EnableUpdateCheck;
|
||||||
|
|
||||||
|
FormSettings form = new FormSettings(this, plugins, updates, tabIndex);
|
||||||
|
|
||||||
|
form.FormClosed += (sender, args) => {
|
||||||
|
if (!prevEnableUpdateCheck && Config.EnableUpdateCheck){
|
||||||
|
updates.DismissUpdate(string.Empty);
|
||||||
|
updates.Check(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Config.EnableTrayHighlight){
|
||||||
|
trayIcon.HasNotifications = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateProperties(PropertyBridge.Properties.ExpandLinksOnHover | PropertyBridge.Properties.SwitchAccountSelectors | PropertyBridge.Properties.HasCustomNotificationSound);
|
||||||
|
form.Dispose();
|
||||||
|
};
|
||||||
|
|
||||||
|
ShowChildForm(form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenAbout(){
|
||||||
|
if (!TryBringToFront<FormAbout>()){
|
||||||
|
ShowChildForm(new FormAbout());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenPlugins(){
|
||||||
|
if (!TryBringToFront<FormPlugins>()){
|
||||||
|
ShowChildForm(new FormPlugins(plugins));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnTweetNotification(){ // may be called multiple times, once for each type of notification
|
||||||
|
if (Config.EnableTrayHighlight && !ContainsFocus){
|
||||||
|
trayIcon.HasNotifications = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayNotificationSound(){
|
||||||
|
if (Config.NotificationSoundPath.Length == 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soundNotification == null){
|
||||||
|
soundNotification = SoundNotification.New();
|
||||||
|
soundNotification.PlaybackError += soundNotification_PlaybackError;
|
||||||
|
}
|
||||||
|
|
||||||
|
soundNotification.Play(Config.NotificationSoundPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnTweetScreenshotReady(string html, int width, int height){
|
||||||
|
if (notificationScreenshotManager == null){
|
||||||
|
notificationScreenshotManager = new TweetScreenshotManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationScreenshotManager.Trigger(html, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisplayTooltip(string text){
|
||||||
|
if (string.IsNullOrEmpty(text)){
|
||||||
|
toolTip.Hide(this);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Point position = PointToClient(Cursor.Position);
|
||||||
|
position.Offset(20, 10);
|
||||||
|
toolTip.Show(text, this, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerTweetScreenshot(){
|
||||||
|
browser.ExecuteScriptAsync("TDGF_triggerScreenshot()");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
127
Core/FormBrowser.resx
Normal file
127
Core/FormBrowser.resx
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
|
<data name="trayIcon.TrayLocation" type="System.Drawing.Point, System.Drawing">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</data>
|
||||||
|
<data name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing">
|
||||||
|
<value>112, 17</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using CefSharp;
|
|
||||||
using CefSharp.WinForms;
|
|
||||||
using TweetDck.Configuration;
|
|
||||||
using TweetDck.Core.Handling;
|
|
||||||
using TweetDck.Resources;
|
|
||||||
|
|
||||||
namespace TweetDck.Core{
|
|
||||||
sealed partial class FormNotification : Form{
|
|
||||||
public Func<bool> CanMoveWindow = () => true;
|
|
||||||
|
|
||||||
private readonly Form owner;
|
|
||||||
private readonly ChromiumWebBrowser browser;
|
|
||||||
|
|
||||||
private readonly Queue<TweetNotification> tweetQueue = new Queue<TweetNotification>(4);
|
|
||||||
private readonly bool autoHide;
|
|
||||||
private int timeLeft, totalTime;
|
|
||||||
|
|
||||||
private readonly string notificationJS;
|
|
||||||
|
|
||||||
protected override bool ShowWithoutActivation{
|
|
||||||
get{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormNotification(Form owner, TweetDeckBridge bridge, bool autoHide){
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
Text = Program.BrandName;
|
|
||||||
|
|
||||||
this.owner = owner;
|
|
||||||
this.autoHide = autoHide;
|
|
||||||
|
|
||||||
owner.FormClosed += (sender, args) => Close();
|
|
||||||
|
|
||||||
notificationJS = ScriptLoader.LoadResource("notification.js");
|
|
||||||
|
|
||||||
browser = new ChromiumWebBrowser("about:blank"){ MenuHandler = new ContextMenuNotification() };
|
|
||||||
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
|
||||||
|
|
||||||
if (bridge != null){
|
|
||||||
browser.RegisterJsObject("$TD",bridge);
|
|
||||||
}
|
|
||||||
|
|
||||||
panelBrowser.Controls.Add(browser);
|
|
||||||
|
|
||||||
if (autoHide){
|
|
||||||
Program.UserConfig.MuteToggled += Config_MuteToggled;
|
|
||||||
Disposed += (sender, args) => Program.UserConfig.MuteToggled -= Config_MuteToggled;
|
|
||||||
}
|
|
||||||
|
|
||||||
Disposed += (sender, args) => browser.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormNotification(Form owner, bool autoHide) : this(owner,null,autoHide){}
|
|
||||||
|
|
||||||
protected override void WndProc(ref Message m){
|
|
||||||
if (m.Msg == 0x0112 && (m.WParam.ToInt32() & 0xFFF0) == 0xF010 && !CanMoveWindow()){ // WM_SYSCOMMAND, SC_MOVE
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.WndProc(ref m);
|
|
||||||
}
|
|
||||||
|
|
||||||
// event handlers
|
|
||||||
|
|
||||||
private void timerHideProgress_Tick(object sender, EventArgs e){
|
|
||||||
if (Bounds.Contains(Cursor.Position))return;
|
|
||||||
|
|
||||||
timeLeft -= timerProgress.Interval;
|
|
||||||
progressBarTimer.SetValueInstant((int)Math.Min(1000,Math.Round(1050.0*(totalTime-timeLeft)/totalTime)));
|
|
||||||
|
|
||||||
if (timeLeft <= 0){
|
|
||||||
if (tweetQueue.Count > 0){
|
|
||||||
LoadNextNotification();
|
|
||||||
}
|
|
||||||
else if (autoHide){
|
|
||||||
HideNotification();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Config_MuteToggled(object sender, EventArgs e){
|
|
||||||
if (Program.UserConfig.MuteNotifications){
|
|
||||||
HideNotification();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (tweetQueue.Count > 0){
|
|
||||||
MoveToVisibleLocation();
|
|
||||||
LoadNextNotification();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
|
||||||
if (e.Frame.IsMain && notificationJS != null && browser.Address != "about:blank"){
|
|
||||||
browser.ExecuteScriptAsync(notificationJS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FormNotification_FormClosing(object sender, FormClosingEventArgs e){
|
|
||||||
if (e.CloseReason == CloseReason.UserClosing){
|
|
||||||
HideNotification();
|
|
||||||
tweetQueue.Clear();
|
|
||||||
e.Cancel = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// notification methods
|
|
||||||
|
|
||||||
public void ShowNotification(TweetNotification notification){
|
|
||||||
if (Program.UserConfig.MuteNotifications){
|
|
||||||
tweetQueue.Enqueue(notification);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
MoveToVisibleLocation();
|
|
||||||
|
|
||||||
tweetQueue.Enqueue(notification);
|
|
||||||
UpdateTitle();
|
|
||||||
|
|
||||||
if (!timerProgress.Enabled){
|
|
||||||
LoadNextNotification();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowNotificationForSettings(bool reset){
|
|
||||||
if (browser.Address == "about:blank"){
|
|
||||||
browser.Load("about:blank"); // required, otherwise shit breaks
|
|
||||||
reset = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reset){
|
|
||||||
browser.LoadHtml(TweetNotification.ExampleTweet.GenerateHtml(),"http://tweetdeck.twitter.com/");
|
|
||||||
|
|
||||||
totalTime = timeLeft = TweetNotification.ExampleTweet.GetDisplayDuration(Program.UserConfig.NotificationDuration);
|
|
||||||
timerProgress.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
MoveToVisibleLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HideNotification(){
|
|
||||||
browser.LoadHtml("","about:blank");
|
|
||||||
Location = new Point(-32000,-32000);
|
|
||||||
timerProgress.Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadNextNotification(){
|
|
||||||
TweetNotification tweet = tweetQueue.Dequeue();
|
|
||||||
|
|
||||||
if (browser.Address == "about:blank"){
|
|
||||||
browser.Load("about:blank"); // required, otherwise shit breaks
|
|
||||||
}
|
|
||||||
|
|
||||||
browser.LoadHtml(tweet.GenerateHtml(),"http://tweetdeck.twitter.com/");
|
|
||||||
|
|
||||||
totalTime = timeLeft = tweet.GetDisplayDuration(Program.UserConfig.NotificationDuration);
|
|
||||||
timerProgress.Stop();
|
|
||||||
timerProgress.Start();
|
|
||||||
|
|
||||||
UpdateTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MoveToVisibleLocation(){
|
|
||||||
bool needsReactivating = Location.X == -32000;
|
|
||||||
|
|
||||||
UserConfig config = Program.UserConfig;
|
|
||||||
Screen screen = Screen.FromControl(owner);
|
|
||||||
|
|
||||||
if (config.DisplayNotificationTimer){
|
|
||||||
ClientSize = new Size(ClientSize.Width,122);
|
|
||||||
progressBarTimer.Visible = true;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
ClientSize = new Size(ClientSize.Width,118);
|
|
||||||
progressBarTimer.Visible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.NotificationDisplay > 0 && config.NotificationDisplay <= Screen.AllScreens.Length){
|
|
||||||
screen = Screen.AllScreens[config.NotificationDisplay-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
int edgeDist = config.NotificationEdgeDistance;
|
|
||||||
|
|
||||||
switch(config.NotificationPosition){
|
|
||||||
case TweetNotification.Position.TopLeft:
|
|
||||||
Location = new Point(screen.WorkingArea.X+edgeDist,screen.WorkingArea.Y+edgeDist);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TweetNotification.Position.TopRight:
|
|
||||||
Location = new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width,screen.WorkingArea.Y+edgeDist);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TweetNotification.Position.BottomLeft:
|
|
||||||
Location = new Point(screen.WorkingArea.X+edgeDist,screen.WorkingArea.Y+screen.WorkingArea.Height-edgeDist-Height);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TweetNotification.Position.BottomRight:
|
|
||||||
Location = new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width,screen.WorkingArea.Y+screen.WorkingArea.Height-edgeDist-Height);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TweetNotification.Position.Custom:
|
|
||||||
if (!config.IsCustomNotificationPositionSet){
|
|
||||||
config.CustomNotificationPosition = new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width,screen.WorkingArea.Y+edgeDist);
|
|
||||||
config.Save();
|
|
||||||
}
|
|
||||||
|
|
||||||
Location = config.CustomNotificationPosition;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsReactivating){
|
|
||||||
Program.SetWindowPos(Handle.ToInt32(),-1,Left,Top,Width,Height,0x0010); // HWND_TOPMOST, SWP_NOACTIVATE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateTitle(){
|
|
||||||
Text = tweetQueue.Count > 0 ? Program.BrandName+" ("+tweetQueue.Count+" more left)" : Program.BrandName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
15
Core/Handling/BrowserProcessHandler.cs
Normal file
15
Core/Handling/BrowserProcessHandler.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Handling{
|
||||||
|
class BrowserProcessHandler : IBrowserProcessHandler{
|
||||||
|
void IBrowserProcessHandler.OnContextInitialized(){
|
||||||
|
using(IRequestContext ctx = Cef.GetGlobalRequestContext()){
|
||||||
|
ctx.SetPreference("browser.enable_spellchecking", Program.UserConfig.EnableSpellCheck, out string _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IBrowserProcessHandler.OnScheduleMessagePumpWork(long delay){}
|
||||||
|
void IDisposable.Dispose(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,44 +1,71 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Bridge;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
using TweetDck.Core.Utils;
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
namespace TweetDck.Core.Handling{
|
||||||
abstract class ContextMenuBase : IContextMenuHandler{
|
abstract class ContextMenuBase : IContextMenuHandler{
|
||||||
private const int MenuOpenUrlInBrowser = 26500;
|
private static readonly Regex RegexTwitterAccount = new Regex(@"^https?://twitter\.com/([^/]+)/?$", RegexOptions.Compiled);
|
||||||
private const int MenuCopyUrl = 26501;
|
|
||||||
private const int MenuOpenImageInBrowser = 26502;
|
private const int MenuOpenLinkUrl = 26500;
|
||||||
private const int MenuSaveImage = 26503;
|
private const int MenuCopyLinkUrl = 26501;
|
||||||
private const int MenuCopyImageUrl = 26504;
|
private const int MenuCopyUsername = 26502;
|
||||||
|
private const int MenuOpenImage = 26503;
|
||||||
|
private const int MenuSaveImage = 26504;
|
||||||
|
private const int MenuCopyImageUrl = 26505;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
private const int MenuOpenDevTools = 26599;
|
||||||
|
|
||||||
|
protected void AddDebugMenuItems(IMenuModel model){
|
||||||
|
model.AddItem((CefMenuCommand)MenuOpenDevTools, "Open dev tools");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private readonly Form form;
|
||||||
|
|
||||||
|
protected ContextMenuBase(Form form){
|
||||||
|
this.form = form;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
||||||
RemoveSeparatorIfLast(model);
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal)){
|
||||||
|
if (RegexTwitterAccount.IsMatch(parameters.UnfilteredLinkUrl)){
|
||||||
|
model.AddItem((CefMenuCommand)MenuOpenLinkUrl, "Open account in browser");
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyLinkUrl, "Copy account address");
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyUsername, "Copy account username");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
model.AddItem((CefMenuCommand)MenuOpenLinkUrl, "Open link in browser");
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyLinkUrl, "Copy link address");
|
||||||
|
}
|
||||||
|
|
||||||
if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#")){
|
|
||||||
model.AddItem((CefMenuCommand)MenuOpenUrlInBrowser,"Open in browser");
|
|
||||||
model.AddItem((CefMenuCommand)MenuCopyUrl,"Copy link address");
|
|
||||||
model.AddSeparator();
|
model.AddSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents){
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents){
|
||||||
model.AddItem((CefMenuCommand)MenuOpenImageInBrowser,"Open image in browser");
|
model.AddItem((CefMenuCommand)MenuOpenImage, "Open image in browser");
|
||||||
model.AddItem((CefMenuCommand)MenuSaveImage, "Save image as...");
|
model.AddItem((CefMenuCommand)MenuSaveImage, "Save image as...");
|
||||||
model.AddItem((CefMenuCommand)MenuCopyImageUrl,"Copy image URL");
|
model.AddItem((CefMenuCommand)MenuCopyImageUrl, "Copy image address");
|
||||||
model.AddSeparator();
|
model.AddSeparator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
||||||
switch((int)commandId){
|
switch((int)commandId){
|
||||||
case MenuOpenUrlInBrowser:
|
case MenuOpenLinkUrl:
|
||||||
BrowserUtils.OpenExternalBrowser(parameters.LinkUrl);
|
BrowserUtils.OpenExternalBrowser(parameters.LinkUrl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuCopyUrl:
|
case MenuCopyLinkUrl:
|
||||||
Clipboard.SetText(string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedLink) ? parameters.UnfilteredLinkUrl : TweetDeckBridge.LastRightClickedLink,TextDataFormat.UnicodeText);
|
SetClipboardText(string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedLink) ? parameters.UnfilteredLinkUrl : TweetDeckBridge.LastRightClickedLink);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuOpenImageInBrowser:
|
case MenuOpenImage:
|
||||||
BrowserUtils.OpenExternalBrowser(parameters.SourceUrl);
|
BrowserUtils.OpenExternalBrowser(parameters.SourceUrl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -66,8 +93,19 @@ namespace TweetDck.Core.Handling{
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuCopyImageUrl:
|
case MenuCopyImageUrl:
|
||||||
Clipboard.SetText(parameters.SourceUrl,TextDataFormat.UnicodeText);
|
SetClipboardText(parameters.SourceUrl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MenuCopyUsername:
|
||||||
|
Match match = RegexTwitterAccount.Match(parameters.UnfilteredLinkUrl);
|
||||||
|
SetClipboardText(match.Success ? match.Groups[1].Value : parameters.UnfilteredLinkUrl);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
case MenuOpenDevTools:
|
||||||
|
browserControl.ShowDevTools();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -79,15 +117,19 @@ namespace TweetDck.Core.Handling{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void RemoveSeparatorIfFirst(IMenuModel model){
|
protected void SetClipboardText(string text){
|
||||||
|
form.InvokeAsyncSafe(() => WindowsUtils.SetClipboard(text, TextDataFormat.UnicodeText));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void RemoveSeparatorIfLast(IMenuModel model){
|
||||||
if (model.Count > 0 && model.GetTypeAt(model.Count-1) == MenuItemType.Separator){
|
if (model.Count > 0 && model.GetTypeAt(model.Count-1) == MenuItemType.Separator){
|
||||||
model.RemoveAt(model.Count-1);
|
model.RemoveAt(model.Count-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void RemoveSeparatorIfLast(IMenuModel model){
|
protected static void AddSeparator(IMenuModel model){
|
||||||
if (model.Count > 0 && model.GetTypeAt(model.Count-1) == MenuItemType.Separator){
|
if (model.Count > 0 && model.GetTypeAt(model.Count-1) != MenuItemType.Separator){ // do not add separators if there is nothing to separate
|
||||||
model.RemoveAt(model.Count-1);
|
model.AddSeparator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,35 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Bridge;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
namespace TweetDck.Core.Handling{
|
||||||
class ContextMenuBrowser : ContextMenuBase{
|
class ContextMenuBrowser : ContextMenuBase{
|
||||||
private const int MenuSettings = 26600;
|
private const int MenuGlobal = 26600;
|
||||||
private const int MenuAbout = 26601;
|
private const int MenuMute = 26601;
|
||||||
private const int MenuMute = 26602;
|
private const int MenuSettings = 26602;
|
||||||
|
private const int MenuPlugins = 26003;
|
||||||
|
private const int MenuAbout = 26604;
|
||||||
|
|
||||||
|
private const int MenuOpenTweetUrl = 26610;
|
||||||
|
private const int MenuCopyTweetUrl = 26611;
|
||||||
|
private const int MenuOpenQuotedTweetUrl = 26612;
|
||||||
|
private const int MenuCopyQuotedTweetUrl = 26613;
|
||||||
|
private const int MenuScreenshotTweet = 26614;
|
||||||
|
|
||||||
|
private const string TitleReloadBrowser = "Reload browser";
|
||||||
|
private const string TitleMuteNotifications = "Mute notifications";
|
||||||
|
private const string TitleSettings = "Settings";
|
||||||
|
private const string TitlePlugins = "Plugins";
|
||||||
|
private const string TitleAboutProgram = "About "+Program.BrandName;
|
||||||
|
|
||||||
private readonly FormBrowser form;
|
private readonly FormBrowser form;
|
||||||
|
|
||||||
public ContextMenuBrowser(FormBrowser form){
|
private string lastHighlightedTweet;
|
||||||
|
private string lastHighlightedQuotedTweet;
|
||||||
|
|
||||||
|
public ContextMenuBrowser(FormBrowser form) : base(form){
|
||||||
this.form = form;
|
this.form = form;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,21 +38,57 @@ namespace TweetDck.Core.Handling{
|
|||||||
model.Remove(CefMenuCommand.Forward);
|
model.Remove(CefMenuCommand.Forward);
|
||||||
model.Remove(CefMenuCommand.Print);
|
model.Remove(CefMenuCommand.Print);
|
||||||
model.Remove(CefMenuCommand.ViewSource);
|
model.Remove(CefMenuCommand.ViewSource);
|
||||||
|
RemoveSeparatorIfLast(model);
|
||||||
|
|
||||||
RemoveSeparatorIfFirst(model);
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Selection)){
|
||||||
|
model.AddSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
||||||
|
|
||||||
model.AddItem(CefMenuCommand.Reload,"Reload");
|
lastHighlightedTweet = TweetDeckBridge.LastHighlightedTweet;
|
||||||
model.AddCheckItem((CefMenuCommand)MenuMute,"Mute Notifications");
|
lastHighlightedQuotedTweet = TweetDeckBridge.LastHighlightedQuotedTweet;
|
||||||
model.SetChecked((CefMenuCommand)MenuMute,Program.UserConfig.MuteNotifications);
|
|
||||||
model.AddSeparator();
|
|
||||||
|
|
||||||
if (TweetNotification.IsReady){
|
if (!BrowserUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){
|
||||||
model.AddItem((CefMenuCommand)MenuSettings,"Settings");
|
lastHighlightedTweet = string.Empty;
|
||||||
|
lastHighlightedQuotedTweet = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
model.AddItem((CefMenuCommand)MenuAbout,"About "+Program.BrandName);
|
if (!string.IsNullOrEmpty(lastHighlightedTweet) && (parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
|
||||||
|
model.AddItem((CefMenuCommand)MenuOpenTweetUrl, "Open tweet in browser");
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
|
||||||
|
model.AddItem((CefMenuCommand)MenuScreenshotTweet, "Screenshot tweet to clipboard");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(lastHighlightedQuotedTweet)){
|
||||||
|
model.AddSeparator();
|
||||||
|
model.AddItem((CefMenuCommand)MenuOpenQuotedTweetUrl, "Open quoted tweet in browser");
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyQuotedTweetUrl, "Copy quoted tweet address");
|
||||||
|
}
|
||||||
|
|
||||||
|
model.AddSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
|
||||||
|
AddSeparator(model);
|
||||||
|
|
||||||
|
IMenuModel globalMenu = model.Count == 0 ? model : model.AddSubMenu((CefMenuCommand)MenuGlobal, Program.BrandName);
|
||||||
|
|
||||||
|
globalMenu.AddItem(CefMenuCommand.Reload, TitleReloadBrowser);
|
||||||
|
globalMenu.AddCheckItem((CefMenuCommand)MenuMute, TitleMuteNotifications);
|
||||||
|
globalMenu.SetChecked((CefMenuCommand)MenuMute, Program.UserConfig.MuteNotifications);
|
||||||
|
globalMenu.AddSeparator();
|
||||||
|
|
||||||
|
globalMenu.AddItem((CefMenuCommand)MenuSettings, TitleSettings);
|
||||||
|
globalMenu.AddItem((CefMenuCommand)MenuPlugins, TitlePlugins);
|
||||||
|
globalMenu.AddItem((CefMenuCommand)MenuAbout, TitleAboutProgram);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
globalMenu.AddSeparator();
|
||||||
|
AddDebugMenuItems(globalMenu);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveSeparatorIfLast(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
||||||
@@ -40,30 +97,70 @@ namespace TweetDck.Core.Handling{
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch((int)commandId){
|
switch((int)commandId){
|
||||||
case MenuSettings:
|
case (int)CefMenuCommand.Reload:
|
||||||
form.InvokeSafe(() => {
|
form.InvokeAsyncSafe(form.ReloadToTweetDeck);
|
||||||
form.OpenSettings();
|
return true;
|
||||||
});
|
|
||||||
|
|
||||||
|
case MenuSettings:
|
||||||
|
form.InvokeAsyncSafe(form.OpenSettings);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuAbout:
|
case MenuAbout:
|
||||||
form.InvokeSafe(() => {
|
form.InvokeAsyncSafe(form.OpenAbout);
|
||||||
form.OpenAbout();
|
return true;
|
||||||
});
|
|
||||||
|
|
||||||
|
case MenuPlugins:
|
||||||
|
form.InvokeAsyncSafe(form.OpenPlugins);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuMute:
|
case MenuMute:
|
||||||
form.InvokeSafe(() => {
|
form.InvokeAsyncSafe(ToggleMuteNotifications);
|
||||||
Program.UserConfig.MuteNotifications = !Program.UserConfig.MuteNotifications;
|
return true;
|
||||||
Program.UserConfig.Save();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
case MenuOpenTweetUrl:
|
||||||
|
BrowserUtils.OpenExternalBrowser(lastHighlightedTweet);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MenuCopyTweetUrl:
|
||||||
|
SetClipboardText(lastHighlightedTweet);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MenuScreenshotTweet:
|
||||||
|
form.InvokeAsyncSafe(form.TriggerTweetScreenshot);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MenuOpenQuotedTweetUrl:
|
||||||
|
BrowserUtils.OpenExternalBrowser(lastHighlightedQuotedTweet);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MenuCopyQuotedTweetUrl:
|
||||||
|
SetClipboardText(lastHighlightedQuotedTweet);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ContextMenu CreateMenu(FormBrowser form){
|
||||||
|
ContextMenu menu = new ContextMenu();
|
||||||
|
|
||||||
|
menu.MenuItems.Add(TitleReloadBrowser, (sender, args) => form.ReloadToTweetDeck());
|
||||||
|
menu.MenuItems.Add(TitleMuteNotifications, (sender, args) => ToggleMuteNotifications());
|
||||||
|
menu.MenuItems.Add("-");
|
||||||
|
menu.MenuItems.Add(TitleSettings, (sender, args) => form.OpenSettings());
|
||||||
|
menu.MenuItems.Add(TitlePlugins, (sender, args) => form.OpenPlugins());
|
||||||
|
menu.MenuItems.Add(TitleAboutProgram, (sender, args) => form.OpenAbout());
|
||||||
|
|
||||||
|
menu.Popup += (sender, args) => {
|
||||||
|
menu.MenuItems[1].Checked = Program.UserConfig.MuteNotifications;
|
||||||
|
};
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ToggleMuteNotifications(){
|
||||||
|
Program.UserConfig.MuteNotifications = !Program.UserConfig.MuteNotifications;
|
||||||
|
Program.UserConfig.Save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,87 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Notification;
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
namespace TweetDck.Core.Handling{
|
||||||
class ContextMenuNotification : ContextMenuBase{
|
class ContextMenuNotification : ContextMenuBase{
|
||||||
|
private const int MenuSkipTweet = 26600;
|
||||||
|
private const int MenuFreeze = 26601;
|
||||||
|
private const int MenuCopyTweetUrl = 26602;
|
||||||
|
private const int MenuCopyQuotedTweetUrl = 26603;
|
||||||
|
|
||||||
|
private readonly FormNotificationBase form;
|
||||||
|
private readonly bool enableCustomMenu;
|
||||||
|
|
||||||
|
public ContextMenuNotification(FormNotificationBase form, bool enableCustomMenu) : base(form){
|
||||||
|
this.form = form;
|
||||||
|
this.enableCustomMenu = enableCustomMenu;
|
||||||
|
}
|
||||||
|
|
||||||
public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
||||||
model.Clear();
|
model.Clear();
|
||||||
|
|
||||||
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Selection)){
|
||||||
|
model.AddItem(CefMenuCommand.Copy, "Copy");
|
||||||
|
model.AddSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
||||||
|
|
||||||
|
if (enableCustomMenu){
|
||||||
|
model.AddItem((CefMenuCommand)MenuSkipTweet, "Skip tweet");
|
||||||
|
model.AddCheckItem((CefMenuCommand)MenuFreeze, "Freeze");
|
||||||
|
model.SetChecked((CefMenuCommand)MenuFreeze, form.FreezeTimer);
|
||||||
|
model.AddSeparator();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(form.CurrentTweetUrl)){
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(form.CurrentQuoteUrl)){
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyQuotedTweetUrl, "Copy quoted tweet address");
|
||||||
|
}
|
||||||
|
|
||||||
|
model.AddSeparator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
AddDebugMenuItems(model);
|
||||||
|
#endif
|
||||||
|
|
||||||
RemoveSeparatorIfLast(model);
|
RemoveSeparatorIfLast(model);
|
||||||
|
|
||||||
|
form.InvokeAsyncSafe(() => form.ContextMenuOpen = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
||||||
|
if (base.OnContextMenuCommand(browserControl, browser, frame, parameters, commandId, eventFlags)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch((int)commandId){
|
||||||
|
case MenuSkipTweet:
|
||||||
|
form.InvokeAsyncSafe(form.FinishCurrentNotification);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MenuFreeze:
|
||||||
|
form.InvokeAsyncSafe(() => form.FreezeTimer = !form.FreezeTimer);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MenuCopyTweetUrl:
|
||||||
|
SetClipboardText(form.CurrentTweetUrl);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MenuCopyQuotedTweetUrl:
|
||||||
|
SetClipboardText(form.CurrentQuoteUrl);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){
|
||||||
|
base.OnContextMenuDismissed(browserControl, browser, frame);
|
||||||
|
form.InvokeAsyncSafe(() => form.ContextMenuOpen = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
60
Core/Handling/JavaScriptDialogHandler.cs
Normal file
60
Core/Handling/JavaScriptDialogHandler.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using CefSharp.WinForms;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Other;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Handling {
|
||||||
|
class JavaScriptDialogHandler : IJsDialogHandler{
|
||||||
|
bool IJsDialogHandler.OnJSDialog(IWebBrowser browserControl, IBrowser browser, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, IJsDialogCallback callback, ref bool suppressMessage){
|
||||||
|
((ChromiumWebBrowser)browserControl).InvokeSafe(() => {
|
||||||
|
FormMessage form = new FormMessage(Program.BrandName, messageText, MessageBoxIcon.None);
|
||||||
|
TextBox input = null;
|
||||||
|
|
||||||
|
if (dialogType == CefJsDialogType.Alert){
|
||||||
|
form.AcceptButton = form.AddButton("OK");
|
||||||
|
}
|
||||||
|
else if (dialogType == CefJsDialogType.Confirm){
|
||||||
|
form.CancelButton = form.AddButton("No", DialogResult.No);
|
||||||
|
form.AcceptButton = form.AddButton("Yes");
|
||||||
|
}
|
||||||
|
else if (dialogType == CefJsDialogType.Prompt){
|
||||||
|
form.CancelButton = form.AddButton("Cancel", DialogResult.Cancel);
|
||||||
|
form.AcceptButton = form.AddButton("OK");
|
||||||
|
|
||||||
|
input = new TextBox{
|
||||||
|
Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom,
|
||||||
|
Location = new Point(27, form.ActionPanelY-46),
|
||||||
|
Size = new Size(form.ClientSize.Width-54, 20)
|
||||||
|
};
|
||||||
|
|
||||||
|
form.Controls.Add(input);
|
||||||
|
form.ActiveControl = input;
|
||||||
|
form.Height += input.Size.Height+input.Margin.Vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = form.ShowDialog() == DialogResult.OK;
|
||||||
|
|
||||||
|
if (input == null){
|
||||||
|
callback.Continue(success);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
callback.Continue(success, input.Text);
|
||||||
|
input.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
form.Dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IJsDialogHandler.OnJSBeforeUnload(IWebBrowser browserControl, IBrowser browser, string message, bool isReload, IJsDialogCallback callback){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IJsDialogHandler.OnResetDialogState(IWebBrowser browserControl, IBrowser browser){}
|
||||||
|
void IJsDialogHandler.OnDialogClosed(IWebBrowser browserControl, IBrowser browser){}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Core/Handling/LifeSpanHandler.cs
Normal file
30
Core/Handling/LifeSpanHandler.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Handling{
|
||||||
|
class LifeSpanHandler : ILifeSpanHandler{
|
||||||
|
public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser){
|
||||||
|
newBrowser = null;
|
||||||
|
|
||||||
|
switch(targetDisposition){
|
||||||
|
case WindowOpenDisposition.NewBackgroundTab:
|
||||||
|
case WindowOpenDisposition.NewForegroundTab:
|
||||||
|
case WindowOpenDisposition.NewPopup:
|
||||||
|
case WindowOpenDisposition.NewWindow:
|
||||||
|
BrowserUtils.OpenExternalBrowser(targetUrl);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnAfterCreated(IWebBrowser browserControl, IBrowser browser){}
|
||||||
|
|
||||||
|
public bool DoClose(IWebBrowser browserControl, IBrowser browser){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnBeforeClose(IWebBrowser browserControl, IBrowser browser){}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
Core/Handling/ResourceHandlerNotification.cs
Normal file
63
Core/Handling/ResourceHandlerNotification.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Handling{
|
||||||
|
class ResourceHandlerNotification : IResourceHandler{
|
||||||
|
private readonly NameValueCollection headers = new NameValueCollection(0);
|
||||||
|
private MemoryStream dataIn;
|
||||||
|
|
||||||
|
public void SetHTML(string html){
|
||||||
|
dataIn?.Dispose();
|
||||||
|
dataIn = ResourceHandler.GetMemoryStream(html, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose(){
|
||||||
|
if (dataIn != null){
|
||||||
|
dataIn.Dispose();
|
||||||
|
dataIn = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IResourceHandler.ProcessRequest(IRequest request, ICallback callback){
|
||||||
|
callback.Continue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResourceHandler.GetResponseHeaders(IResponse response, out long responseLength, out string redirectUrl){
|
||||||
|
redirectUrl = null;
|
||||||
|
|
||||||
|
response.MimeType = "text/html";
|
||||||
|
response.StatusCode = 200;
|
||||||
|
response.StatusText = "OK";
|
||||||
|
response.ResponseHeaders = headers;
|
||||||
|
responseLength = dataIn?.Length ?? -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IResourceHandler.ReadResponse(Stream dataOut, out int bytesRead, ICallback callback){
|
||||||
|
callback.Dispose();
|
||||||
|
|
||||||
|
try{
|
||||||
|
int length = (int)dataIn.Length;
|
||||||
|
|
||||||
|
dataIn.CopyTo(dataOut, length);
|
||||||
|
bytesRead = length;
|
||||||
|
return true;
|
||||||
|
}catch{ // catch IOException, possibly NullReferenceException if dataIn is null
|
||||||
|
bytesRead = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IResourceHandler.CanGetCookie(Cookie cookie){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IResourceHandler.CanSetCookie(Cookie cookie){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResourceHandler.Cancel(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
using TweetDck.Core.Utils;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
|
||||||
class TweetDeckBridge{
|
|
||||||
public static string LastRightClickedLink = string.Empty;
|
|
||||||
|
|
||||||
private readonly FormBrowser form;
|
|
||||||
|
|
||||||
public string BrandName{
|
|
||||||
get{
|
|
||||||
return Program.BrandName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string VersionTag{
|
|
||||||
get{
|
|
||||||
return Program.VersionTag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool MuteNotifications{
|
|
||||||
get{
|
|
||||||
return Program.UserConfig.MuteNotifications;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool UpdateCheckEnabled{
|
|
||||||
get{
|
|
||||||
return Program.UserConfig.EnableUpdateCheck;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string DismissedVersionTag{
|
|
||||||
get{
|
|
||||||
return Program.UserConfig.DismissedUpdate ?? string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TweetDeckBridge(FormBrowser form){
|
|
||||||
this.form = form;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadFontSizeClass(string fsClass){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
TweetNotification.SetFontSizeClass(fsClass);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadNotificationHeadContents(string headContents){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
TweetNotification.SetHeadTag(headContents);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetLastRightClickedLink(string link){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
LastRightClickedLink = link;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenSettingsMenu(){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
form.OpenSettings();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnTweetPopup(string tweetHtml, int tweetCharacters){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
form.OnTweetPopup(new TweetNotification(tweetHtml,tweetCharacters));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnTweetSound(){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
form.OnTweetSound();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnUpdateAccepted(string versionTag, string downloadUrl){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
form.BeginUpdateProcess(versionTag,downloadUrl);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnUpdateDismissed(string versionTag){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
Program.UserConfig.DismissedUpdate = versionTag;
|
|
||||||
Program.UserConfig.Save();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenBrowser(string url){
|
|
||||||
BrowserUtils.OpenExternalBrowser(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log(string data){
|
|
||||||
System.Diagnostics.Debug.WriteLine(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
|
||||||
sealed class TweetNotification{
|
|
||||||
private static string FontSizeClass { get; set; }
|
|
||||||
private static string HeadTag { get; set; }
|
|
||||||
|
|
||||||
public static bool IsReady{
|
|
||||||
get{
|
|
||||||
return FontSizeClass != null && HeadTag != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TweetNotification ExampleTweet{
|
|
||||||
get{
|
|
||||||
StringBuilder build = new StringBuilder();
|
|
||||||
build.Append(@"<article><div class='js-stream-item-content item-box js-show-detail'><div class='js-tweet tweet'>");
|
|
||||||
build.Append(@"<header class='tweet-header'>");
|
|
||||||
build.Append(@"<time class='tweet-timestamp js-timestamp pull-right txt-mute'><a target='_blank' rel='url' href='https://twitter.com/chylexmc' class='txt-small'>0s</a></time>");
|
|
||||||
build.Append(@"<a target='_blank' rel='user' href='https://twitter.com/chylexmc' class='account-link link-complex block'>");
|
|
||||||
build.Append(@"<div class='obj-left item-img tweet-img'><img width='48' height='48' alt='chylexmc's avatar' src='https://pbs.twimg.com/profile_images/645532929930608642/J56NBJVY_normal.png' class='tweet-avatar avatar pull-right'></div>");
|
|
||||||
build.Append(@"<div class='nbfc'><span class='account-inline txt-ellipsis'><b class='fullname link-complex-target'>chylex</b> <span class='username txt-mute'>@chylexmc</span></span></div>");
|
|
||||||
build.Append(@"</a>");
|
|
||||||
build.Append(@"</header>");
|
|
||||||
build.Append(@"<div class='tweet-body'><p class='js-tweet-text tweet-text with-linebreaks'>This is an example tweet, which lets you test the location and duration of popup notifications.</p></div>");
|
|
||||||
build.Append(@"</div></div></article>");
|
|
||||||
|
|
||||||
return new TweetNotification(build.ToString(),95);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetFontSizeClass(string newFSClass){
|
|
||||||
FontSizeClass = newFSClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetHeadTag(string headContents){
|
|
||||||
HeadTag = headContents;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Position{
|
|
||||||
TopLeft, TopRight, BottomLeft, BottomRight, Custom
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Duration{
|
|
||||||
Short, Medium, Long, VeryLong
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly string html;
|
|
||||||
private readonly int characters;
|
|
||||||
|
|
||||||
public TweetNotification(string html, int characters){
|
|
||||||
this.html = html;
|
|
||||||
this.characters = characters;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetDisplayDuration(Duration modifier){
|
|
||||||
int multiplier;
|
|
||||||
|
|
||||||
switch(modifier){
|
|
||||||
case Duration.Short: multiplier = 15; break;
|
|
||||||
case Duration.Long: multiplier = 35; break;
|
|
||||||
case Duration.VeryLong: multiplier = 45; break;
|
|
||||||
default: multiplier = 25; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 2000+Math.Max(1000,multiplier*characters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GenerateHtml(){
|
|
||||||
StringBuilder build = new StringBuilder();
|
|
||||||
build.Append("<!DOCTYPE html>");
|
|
||||||
build.Append("<html class='os-windows txt-base-").Append(FontSizeClass).Append("'>");
|
|
||||||
build.Append("<head>").Append(HeadTag).Append("</head>");
|
|
||||||
build.Append("<body class='hearty'><div class='app-columns-container'><div class='column' style='width:100%'>");
|
|
||||||
build.Append(html);
|
|
||||||
build.Append("</div></div></body>");
|
|
||||||
build.Append("</html>");
|
|
||||||
return build.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
52
Core/Notification/FormNotificationBase.Designer.cs
generated
Normal file
52
Core/Notification/FormNotificationBase.Designer.cs
generated
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
namespace TweetDck.Core.Notification {
|
||||||
|
partial class FormNotificationBase {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// FormNotification
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.BackColor = System.Drawing.SystemColors.Control;
|
||||||
|
this.ClientSize = new System.Drawing.Size(284, 122);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||||
|
this.Location = TweetDck.Core.Controls.ControlExtensions.InvisibleLocation;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "FormNotification";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.ShowInTaskbar = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
}
|
||||||
|
}
|
||||||
211
Core/Notification/FormNotificationBase.cs
Normal file
211
Core/Notification/FormNotificationBase.cs
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using CefSharp.WinForms;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Configuration;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Handling;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification{
|
||||||
|
partial class FormNotificationBase : Form{
|
||||||
|
protected Point PrimaryLocation{
|
||||||
|
get{
|
||||||
|
UserConfig config = Program.UserConfig;
|
||||||
|
Screen screen;
|
||||||
|
|
||||||
|
if (config.NotificationDisplay > 0 && config.NotificationDisplay <= Screen.AllScreens.Length){
|
||||||
|
screen = Screen.AllScreens[config.NotificationDisplay-1];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
screen = Screen.FromControl(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
int edgeDist = config.NotificationEdgeDistance;
|
||||||
|
|
||||||
|
switch(config.NotificationPosition){
|
||||||
|
case TweetNotification.Position.TopLeft:
|
||||||
|
return new Point(screen.WorkingArea.X+edgeDist, screen.WorkingArea.Y+edgeDist);
|
||||||
|
|
||||||
|
case TweetNotification.Position.TopRight:
|
||||||
|
return new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width, screen.WorkingArea.Y+edgeDist);
|
||||||
|
|
||||||
|
case TweetNotification.Position.BottomLeft:
|
||||||
|
return new Point(screen.WorkingArea.X+edgeDist, screen.WorkingArea.Y+screen.WorkingArea.Height-edgeDist-Height);
|
||||||
|
|
||||||
|
case TweetNotification.Position.BottomRight:
|
||||||
|
return new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width, screen.WorkingArea.Y+screen.WorkingArea.Height-edgeDist-Height);
|
||||||
|
|
||||||
|
case TweetNotification.Position.Custom:
|
||||||
|
if (!config.IsCustomNotificationPositionSet){
|
||||||
|
config.CustomNotificationPosition = new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width, screen.WorkingArea.Y+edgeDist);
|
||||||
|
config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.CustomNotificationPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsNotificationVisible => Location != ControlExtensions.InvisibleLocation;
|
||||||
|
|
||||||
|
public new Point Location{
|
||||||
|
get => base.Location;
|
||||||
|
|
||||||
|
set{
|
||||||
|
Visible = (base.Location = value) != ControlExtensions.InvisibleLocation;
|
||||||
|
|
||||||
|
if (WindowsUtils.ShouldAvoidToolWindow){
|
||||||
|
FormBorderStyle = Visible ? FormBorderStyle.FixedSingle : FormBorderStyle.FixedToolWindow; // workaround for alt+tab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Func<bool> CanMoveWindow = () => true;
|
||||||
|
protected override bool ShowWithoutActivation => true;
|
||||||
|
|
||||||
|
protected readonly Form owner;
|
||||||
|
protected readonly ChromiumWebBrowser browser;
|
||||||
|
|
||||||
|
private readonly ResourceHandlerNotification resourceHandler = new ResourceHandlerNotification();
|
||||||
|
|
||||||
|
private string currentColumn;
|
||||||
|
private int pauseCounter;
|
||||||
|
|
||||||
|
public bool IsPaused => pauseCounter > 0;
|
||||||
|
|
||||||
|
public bool FreezeTimer { get; set; }
|
||||||
|
public bool ContextMenuOpen { get; set; }
|
||||||
|
public string CurrentTweetUrl { get; private set; }
|
||||||
|
public string CurrentQuoteUrl { get; private set; }
|
||||||
|
|
||||||
|
public event EventHandler Initialized;
|
||||||
|
|
||||||
|
public FormNotificationBase(Form owner, bool enableContextMenu){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.owner = owner;
|
||||||
|
this.owner.FormClosed += owner_FormClosed;
|
||||||
|
|
||||||
|
this.browser = new ChromiumWebBrowser("about:blank"){
|
||||||
|
MenuHandler = new ContextMenuNotification(this, enableContextMenu),
|
||||||
|
LifeSpanHandler = new LifeSpanHandler()
|
||||||
|
};
|
||||||
|
|
||||||
|
this.browser.Dock = DockStyle.None;
|
||||||
|
this.browser.ClientSize = ClientSize;
|
||||||
|
this.browser.IsBrowserInitializedChanged += Browser_IsBrowserInitializedChanged;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
this.browser.ConsoleMessage += BrowserUtils.HandleConsoleMessage;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DefaultResourceHandlerFactory handlerFactory = (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory;
|
||||||
|
handlerFactory.RegisterHandler("https://tweetdeck.twitter.com", this.resourceHandler);
|
||||||
|
|
||||||
|
Controls.Add(browser);
|
||||||
|
|
||||||
|
Disposed += (sender, args) => {
|
||||||
|
this.browser.Dispose();
|
||||||
|
this.owner.FormClosed -= owner_FormClosed;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ReSharper disable once VirtualMemberCallInContructor
|
||||||
|
UpdateTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void WndProc(ref Message m){
|
||||||
|
if (m.Msg == 0x0112 && (m.WParam.ToInt32() & 0xFFF0) == 0xF010 && !CanMoveWindow()){ // WM_SYSCOMMAND, SC_MOVE
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.WndProc(ref m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// event handlers
|
||||||
|
|
||||||
|
private void owner_FormClosed(object sender, FormClosedEventArgs e){
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Browser_IsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs e){
|
||||||
|
if (e.IsBrowserInitialized){
|
||||||
|
Initialized?.Invoke(this, new EventArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// notification methods
|
||||||
|
|
||||||
|
public virtual void HideNotification(bool loadBlank){
|
||||||
|
if (loadBlank){
|
||||||
|
browser.Load("about:blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
Location = ControlExtensions.InvisibleLocation;
|
||||||
|
currentColumn = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void FinishCurrentNotification(){}
|
||||||
|
|
||||||
|
public virtual void PauseNotification(){
|
||||||
|
if (pauseCounter++ == 0 && IsNotificationVisible){
|
||||||
|
Location = ControlExtensions.InvisibleLocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ResumeNotification(){
|
||||||
|
if (pauseCounter > 0){
|
||||||
|
--pauseCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual string GetTweetHTML(TweetNotification tweet){
|
||||||
|
string bodyClasses = browser.Bounds.Contains(PointToClient(Cursor.Position)) ? "td-hover" : string.Empty;
|
||||||
|
return tweet.GenerateHtml(bodyClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void LoadTweet(TweetNotification tweet){
|
||||||
|
CurrentTweetUrl = tweet.TweetUrl;
|
||||||
|
CurrentQuoteUrl = tweet.QuoteUrl;
|
||||||
|
currentColumn = tweet.Column;
|
||||||
|
|
||||||
|
resourceHandler.SetHTML(GetTweetHTML(tweet));
|
||||||
|
browser.Load("https://tweetdeck.twitter.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void SetNotificationSize(int width, int height){
|
||||||
|
browser.ClientSize = ClientSize = new Size((int)Math.Round(width*Program.UserConfig.ZoomMultiplier), (int)Math.Round(height*Program.UserConfig.ZoomMultiplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnNotificationReady(){
|
||||||
|
MoveToVisibleLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateTitle(){
|
||||||
|
Text = string.IsNullOrEmpty(currentColumn) || !Program.UserConfig.DisplayNotificationColumn ? Program.BrandName : Program.BrandName+" - "+currentColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveToVisibleLocation(){
|
||||||
|
bool needsReactivating = Location == ControlExtensions.InvisibleLocation;
|
||||||
|
Location = PrimaryLocation;
|
||||||
|
|
||||||
|
if (needsReactivating){
|
||||||
|
NativeMethods.SetFormPos(this, NativeMethods.HWND_TOPMOST, NativeMethods.SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisplayTooltip(string text){
|
||||||
|
if (string.IsNullOrEmpty(text)){
|
||||||
|
toolTip.Hide(this);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Point position = PointToClient(Cursor.Position);
|
||||||
|
position.Offset(20, 5);
|
||||||
|
toolTip.Show(text, this, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
using TweetDck.Core.Controls;
|
namespace TweetDck.Core.Notification {
|
||||||
|
partial class FormNotificationMain {
|
||||||
namespace TweetDck.Core {
|
|
||||||
sealed partial class FormNotification {
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -26,21 +24,15 @@ namespace TweetDck.Core {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
this.panelBrowser = new System.Windows.Forms.Panel();
|
this.timerDisplayDelay = new System.Windows.Forms.Timer(this.components);
|
||||||
this.timerProgress = new System.Windows.Forms.Timer(this.components);
|
this.timerProgress = new System.Windows.Forms.Timer(this.components);
|
||||||
this.progressBarTimer = new TweetDck.Core.Controls.FlatProgressBar();
|
this.progressBarTimer = new TweetDck.Core.Controls.FlatProgressBar();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// panelBrowser
|
// timerDisplayDelay
|
||||||
//
|
//
|
||||||
this.panelBrowser.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
this.timerDisplayDelay.Interval = 17;
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
this.timerDisplayDelay.Tick += new System.EventHandler(this.timerDisplayDelay_Tick);
|
||||||
this.panelBrowser.BackColor = System.Drawing.Color.White;
|
|
||||||
this.panelBrowser.Location = new System.Drawing.Point(0, 0);
|
|
||||||
this.panelBrowser.Margin = new System.Windows.Forms.Padding(0);
|
|
||||||
this.panelBrowser.Name = "panelBrowser";
|
|
||||||
this.panelBrowser.Size = new System.Drawing.Size(284, 118);
|
|
||||||
this.panelBrowser.TabIndex = 0;
|
|
||||||
//
|
//
|
||||||
// timerProgress
|
// timerProgress
|
||||||
//
|
//
|
||||||
@@ -49,6 +41,8 @@ namespace TweetDck.Core {
|
|||||||
//
|
//
|
||||||
// progressBarTimer
|
// progressBarTimer
|
||||||
//
|
//
|
||||||
|
this.progressBarTimer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.progressBarTimer.BackColor = System.Drawing.SystemColors.Control;
|
this.progressBarTimer.BackColor = System.Drawing.SystemColors.Control;
|
||||||
this.progressBarTimer.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(28)))), ((int)(((byte)(99)))), ((int)(((byte)(153)))));
|
this.progressBarTimer.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(28)))), ((int)(((byte)(99)))), ((int)(((byte)(153)))));
|
||||||
this.progressBarTimer.Location = new System.Drawing.Point(0, 118);
|
this.progressBarTimer.Location = new System.Drawing.Point(0, 118);
|
||||||
@@ -65,14 +59,6 @@ namespace TweetDck.Core {
|
|||||||
this.BackColor = System.Drawing.SystemColors.Control;
|
this.BackColor = System.Drawing.SystemColors.Control;
|
||||||
this.ClientSize = new System.Drawing.Size(284, 122);
|
this.ClientSize = new System.Drawing.Size(284, 122);
|
||||||
this.Controls.Add(this.progressBarTimer);
|
this.Controls.Add(this.progressBarTimer);
|
||||||
this.Controls.Add(this.panelBrowser);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
|
||||||
this.Location = new System.Drawing.Point(-32000, -32000);
|
|
||||||
this.MaximizeBox = false;
|
|
||||||
this.MinimizeBox = false;
|
|
||||||
this.Name = "FormNotification";
|
|
||||||
this.ShowInTaskbar = false;
|
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
|
||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormNotification_FormClosing);
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormNotification_FormClosing);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
@@ -80,8 +66,8 @@ namespace TweetDck.Core {
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.Panel panelBrowser;
|
private System.Windows.Forms.Timer timerDisplayDelay;
|
||||||
|
protected System.Windows.Forms.Timer timerProgress;
|
||||||
private Controls.FlatProgressBar progressBarTimer;
|
private Controls.FlatProgressBar progressBarTimer;
|
||||||
private System.Windows.Forms.Timer timerProgress;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
282
Core/Notification/FormNotificationMain.cs
Normal file
282
Core/Notification/FormNotificationMain.cs
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Bridge;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
using TweetDck.Plugins;
|
||||||
|
using TweetDck.Plugins.Enums;
|
||||||
|
using TweetDck.Resources;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification{
|
||||||
|
partial class FormNotificationMain : FormNotificationBase{
|
||||||
|
private const string NotificationScriptFile = "notification.js";
|
||||||
|
|
||||||
|
private static readonly string NotificationScriptIdentifier = ScriptLoader.GetRootIdentifier(NotificationScriptFile);
|
||||||
|
private static readonly string PluginScriptIdentifier = ScriptLoader.GetRootIdentifier(PluginManager.PluginNotificationScriptFile);
|
||||||
|
|
||||||
|
private static readonly string NotificationJS, PluginJS;
|
||||||
|
|
||||||
|
static FormNotificationMain(){
|
||||||
|
NotificationJS = ScriptLoader.LoadResource(NotificationScriptFile);
|
||||||
|
PluginJS = ScriptLoader.LoadResource(PluginManager.PluginNotificationScriptFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int BaseClientWidth{
|
||||||
|
get{
|
||||||
|
int level = TweetNotification.FontSizeLevel;
|
||||||
|
int width = level == 0 ? 284 : (int)Math.Round(284.0*(1.0+0.05*level));
|
||||||
|
return (int)Math.Round(width*Program.UserConfig.ZoomMultiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int BaseClientHeight{
|
||||||
|
get{
|
||||||
|
int level = TweetNotification.FontSizeLevel;
|
||||||
|
int height = level == 0 ? 118 : (int)Math.Round(118.0*(1.0+0.075*level));
|
||||||
|
return (int)Math.Round(height*Program.UserConfig.ZoomMultiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly PluginManager plugins;
|
||||||
|
|
||||||
|
protected int timeLeft, totalTime;
|
||||||
|
protected bool pausedDuringNotification;
|
||||||
|
|
||||||
|
private readonly NativeMethods.HookProc mouseHookDelegate;
|
||||||
|
private IntPtr mouseHook;
|
||||||
|
private bool blockXButtonUp;
|
||||||
|
|
||||||
|
private bool? prevDisplayTimer;
|
||||||
|
private int? prevFontSize;
|
||||||
|
|
||||||
|
private bool RequiresResize{
|
||||||
|
get{
|
||||||
|
return !prevDisplayTimer.HasValue || !prevFontSize.HasValue || prevDisplayTimer != Program.UserConfig.DisplayNotificationTimer || prevFontSize != TweetNotification.FontSizeLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
set{
|
||||||
|
if (value){
|
||||||
|
prevDisplayTimer = null;
|
||||||
|
prevFontSize = null;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
prevDisplayTimer = Program.UserConfig.DisplayNotificationTimer;
|
||||||
|
prevFontSize = TweetNotification.FontSizeLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FormNotificationMain(FormBrowser owner, PluginManager pluginManager, bool enableContextMenu) : base(owner, enableContextMenu){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.plugins = pluginManager;
|
||||||
|
|
||||||
|
browser.RegisterAsyncJsObject("$TD", new TweetDeckBridge(owner, this));
|
||||||
|
browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
|
||||||
|
|
||||||
|
browser.LoadingStateChanged += Browser_LoadingStateChanged;
|
||||||
|
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
||||||
|
|
||||||
|
mouseHookDelegate = MouseHookProc;
|
||||||
|
Disposed += (sender, args) => StopMouseHook(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mouse wheel hook
|
||||||
|
|
||||||
|
private void StartMouseHook(){
|
||||||
|
if (mouseHook == IntPtr.Zero){
|
||||||
|
mouseHook = NativeMethods.SetWindowsHookEx(NativeMethods.WM_MOUSE_LL, mouseHookDelegate, IntPtr.Zero, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopMouseHook(bool force){
|
||||||
|
if (mouseHook != IntPtr.Zero && (force || !blockXButtonUp)){
|
||||||
|
NativeMethods.UnhookWindowsHookEx(mouseHook);
|
||||||
|
mouseHook = IntPtr.Zero;
|
||||||
|
blockXButtonUp = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam){
|
||||||
|
if (nCode == 0){
|
||||||
|
int eventType = wParam.ToInt32();
|
||||||
|
|
||||||
|
if (eventType == NativeMethods.WM_MOUSEWHEEL && browser.Bounds.Contains(PointToClient(Cursor.Position)) && !ContainsFocus && !owner.ContainsFocus){
|
||||||
|
browser.SendMouseWheelEvent(0, 0, 0, NativeMethods.GetMouseHookData(lParam), CefEventFlags.None);
|
||||||
|
return NativeMethods.HOOK_HANDLED;
|
||||||
|
}
|
||||||
|
else if (eventType == NativeMethods.WM_XBUTTONDOWN && DesktopBounds.Contains(Cursor.Position)){
|
||||||
|
int extraButton = NativeMethods.GetMouseHookData(lParam);
|
||||||
|
|
||||||
|
if (extraButton == 2){ // forward button
|
||||||
|
this.InvokeAsyncSafe(FinishCurrentNotification);
|
||||||
|
}
|
||||||
|
else if (extraButton == 1){ // back button
|
||||||
|
this.InvokeAsyncSafe(Close);
|
||||||
|
}
|
||||||
|
|
||||||
|
blockXButtonUp = true;
|
||||||
|
return NativeMethods.HOOK_HANDLED;
|
||||||
|
}
|
||||||
|
else if (eventType == NativeMethods.WM_XBUTTONUP && blockXButtonUp){
|
||||||
|
blockXButtonUp = false;
|
||||||
|
|
||||||
|
if (!Visible){
|
||||||
|
StopMouseHook(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NativeMethods.HOOK_HANDLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NativeMethods.CallNextHookEx(mouseHook, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
// event handlers
|
||||||
|
|
||||||
|
private void FormNotification_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
|
if (e.CloseReason == CloseReason.UserClosing){
|
||||||
|
HideNotification(true);
|
||||||
|
e.Cancel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e){
|
||||||
|
if (!e.IsLoading && browser.Address != "about:blank"){
|
||||||
|
this.InvokeSafe(() => {
|
||||||
|
Visible = true; // ensures repaint before moving the window to a visible location
|
||||||
|
timerDisplayDelay.Start();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
||||||
|
if (e.Frame.IsMain && NotificationJS != null && browser.Address != "about:blank"){
|
||||||
|
e.Frame.ExecuteJavaScriptAsync(PropertyBridge.GenerateScript(PropertyBridge.Properties.AllNotification));
|
||||||
|
ScriptLoader.ExecuteScript(e.Frame, NotificationJS, NotificationScriptIdentifier);
|
||||||
|
|
||||||
|
if (plugins.HasAnyPlugin(PluginEnvironment.Notification)){
|
||||||
|
ScriptLoader.ExecuteScript(e.Frame, PluginJS, PluginScriptIdentifier);
|
||||||
|
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginGlobalScriptFile);
|
||||||
|
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Notification, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerDisplayDelay_Tick(object sender, EventArgs e){
|
||||||
|
OnNotificationReady();
|
||||||
|
timerDisplayDelay.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerHideProgress_Tick(object sender, EventArgs e){
|
||||||
|
if (Bounds.Contains(Cursor.Position) || FreezeTimer || ContextMenuOpen)return;
|
||||||
|
|
||||||
|
timeLeft -= timerProgress.Interval;
|
||||||
|
|
||||||
|
int value = (int)Math.Round(1025.0*(totalTime-timeLeft)/totalTime);
|
||||||
|
progressBarTimer.SetValueInstant(Math.Min(1000, Math.Max(0, Program.UserConfig.NotificationTimerCountDown ? 1000-value : value)));
|
||||||
|
|
||||||
|
if (timeLeft <= 0){
|
||||||
|
FinishCurrentNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// notification methods
|
||||||
|
|
||||||
|
public virtual void ShowNotification(TweetNotification notification){
|
||||||
|
LoadTweet(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowNotificationForSettings(bool reset){
|
||||||
|
if (reset){
|
||||||
|
LoadTweet(TweetNotification.ExampleTweet);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
PrepareAndDisplayWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HideNotification(bool loadBlank){
|
||||||
|
base.HideNotification(loadBlank);
|
||||||
|
|
||||||
|
progressBarTimer.Value = Program.UserConfig.NotificationTimerCountDown ? 1000 : 0;
|
||||||
|
timerProgress.Stop();
|
||||||
|
totalTime = 0;
|
||||||
|
|
||||||
|
StopMouseHook(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void FinishCurrentNotification(){
|
||||||
|
timerProgress.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PauseNotification(){
|
||||||
|
if (!IsPaused){
|
||||||
|
pausedDuringNotification = IsNotificationVisible;
|
||||||
|
timerProgress.Stop();
|
||||||
|
StopMouseHook(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.PauseNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ResumeNotification(){
|
||||||
|
bool wasPaused = IsPaused;
|
||||||
|
base.ResumeNotification();
|
||||||
|
|
||||||
|
if (wasPaused && !IsPaused && pausedDuringNotification){
|
||||||
|
OnNotificationReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetTweetHTML(TweetNotification tweet){
|
||||||
|
string html = base.GetTweetHTML(tweet);
|
||||||
|
|
||||||
|
foreach(InjectedHTML injection in plugins.Bridge.NotificationInjections){
|
||||||
|
html = injection.Inject(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadTweet(TweetNotification tweet){
|
||||||
|
timerProgress.Stop();
|
||||||
|
totalTime = timeLeft = tweet.GetDisplayDuration(Program.UserConfig.NotificationDurationValue);
|
||||||
|
progressBarTimer.Value = Program.UserConfig.NotificationTimerCountDown ? 1000 : 0;
|
||||||
|
|
||||||
|
base.LoadTweet(tweet);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetNotificationSize(int width, int height){
|
||||||
|
if (Program.UserConfig.DisplayNotificationTimer){
|
||||||
|
ClientSize = new Size(width, height+4);
|
||||||
|
progressBarTimer.Visible = true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ClientSize = new Size(width, height);
|
||||||
|
progressBarTimer.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.ClientSize = new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrepareAndDisplayWindow(){
|
||||||
|
if (RequiresResize){
|
||||||
|
RequiresResize = false;
|
||||||
|
SetNotificationSize(BaseClientWidth, BaseClientHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveToVisibleLocation();
|
||||||
|
StartMouseHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNotificationReady(){
|
||||||
|
PrepareAndDisplayWindow();
|
||||||
|
timerProgress.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
Core/Notification/FormNotificationTweet.Designer.cs
generated
Normal file
53
Core/Notification/FormNotificationTweet.Designer.cs
generated
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
namespace TweetDck.Core.Notification {
|
||||||
|
partial class FormNotificationTweet {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.timerCursorCheck = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.timerIdlePauseCheck = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// timerCursorCheck
|
||||||
|
//
|
||||||
|
this.timerCursorCheck.Interval = 200;
|
||||||
|
this.timerCursorCheck.Tick += new System.EventHandler(this.timerCursorCheck_Tick);
|
||||||
|
//
|
||||||
|
// timerIdlePauseCheck
|
||||||
|
//
|
||||||
|
this.timerIdlePauseCheck.Interval = 750;
|
||||||
|
this.timerIdlePauseCheck.Tick += new System.EventHandler(this.timerIdlePauseCheck_Tick);
|
||||||
|
//
|
||||||
|
// FormNotificationTweet
|
||||||
|
//
|
||||||
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormNotificationTweet_FormClosing);
|
||||||
|
this.ResumeLayout(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Timer timerCursorCheck;
|
||||||
|
private System.Windows.Forms.Timer timerIdlePauseCheck;
|
||||||
|
}
|
||||||
|
}
|
||||||
141
Core/Notification/FormNotificationTweet.cs
Normal file
141
Core/Notification/FormNotificationTweet.cs
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using TweetDck.Plugins;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification{
|
||||||
|
sealed partial class FormNotificationTweet : FormNotificationMain{
|
||||||
|
private const int NonIntrusiveIdleLimit = 30;
|
||||||
|
private const int TrimMinimum = 32;
|
||||||
|
|
||||||
|
private bool IsCursorOverNotificationArea => new Rectangle(PrimaryLocation, Size).Contains(Cursor.Position);
|
||||||
|
|
||||||
|
private readonly Queue<TweetNotification> tweetQueue = new Queue<TweetNotification>(4);
|
||||||
|
private bool needsTrim;
|
||||||
|
|
||||||
|
public FormNotificationTweet(FormBrowser owner, PluginManager pluginManager) : base(owner, pluginManager, true){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Program.UserConfig.MuteToggled += Config_MuteToggled;
|
||||||
|
Disposed += (sender, args) => Program.UserConfig.MuteToggled -= Config_MuteToggled;
|
||||||
|
|
||||||
|
if (Program.UserConfig.MuteNotifications){
|
||||||
|
PauseNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FormNotificationTweet_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
|
if (e.CloseReason == CloseReason.UserClosing){
|
||||||
|
tweetQueue.Clear(); // already canceled
|
||||||
|
TrimQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TrimQueue(){
|
||||||
|
if (needsTrim){
|
||||||
|
tweetQueue.TrimExcess();
|
||||||
|
needsTrim = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// event handlers
|
||||||
|
|
||||||
|
private void Config_MuteToggled(object sender, EventArgs e){
|
||||||
|
if (Program.UserConfig.MuteNotifications){
|
||||||
|
PauseNotification();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ResumeNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerCursorCheck_Tick(object sender, EventArgs e){
|
||||||
|
if (!IsCursorOverNotificationArea){
|
||||||
|
ResumeNotification();
|
||||||
|
timerCursorCheck.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerIdlePauseCheck_Tick(object sender, EventArgs e){
|
||||||
|
if (NativeMethods.GetIdleSeconds() < Program.UserConfig.NotificationIdlePauseSeconds){
|
||||||
|
ResumeNotification();
|
||||||
|
timerIdlePauseCheck.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// notification methods
|
||||||
|
|
||||||
|
public override void ShowNotification(TweetNotification notification){
|
||||||
|
if (IsPaused){
|
||||||
|
tweetQueue.Enqueue(notification);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
tweetQueue.Enqueue(notification);
|
||||||
|
UpdateTitle();
|
||||||
|
|
||||||
|
if (totalTime == 0){
|
||||||
|
LoadNextNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
needsTrim |= tweetQueue.Count >= TrimMinimum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void FinishCurrentNotification(){
|
||||||
|
if (tweetQueue.Count > 0){
|
||||||
|
LoadNextNotification();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
HideNotification(true);
|
||||||
|
TrimQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ResumeNotification(){
|
||||||
|
bool wasPaused = IsPaused;
|
||||||
|
base.ResumeNotification();
|
||||||
|
|
||||||
|
if (wasPaused && !IsPaused && !pausedDuringNotification && tweetQueue.Count > 0){
|
||||||
|
LoadNextNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadNextNotification(){
|
||||||
|
if (!IsNotificationVisible){
|
||||||
|
if (Program.UserConfig.NotificationNonIntrusiveMode && IsCursorOverNotificationArea && NativeMethods.GetIdleSeconds() < NonIntrusiveIdleLimit){
|
||||||
|
if (!timerCursorCheck.Enabled){
|
||||||
|
PauseNotification();
|
||||||
|
timerCursorCheck.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (Program.UserConfig.NotificationIdlePauseSeconds > 0 && NativeMethods.GetIdleSeconds() >= Program.UserConfig.NotificationIdlePauseSeconds){
|
||||||
|
if (!timerIdlePauseCheck.Enabled){
|
||||||
|
PauseNotification();
|
||||||
|
timerIdlePauseCheck.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadTweet(tweetQueue.Dequeue());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateTitle(){
|
||||||
|
base.UpdateTitle();
|
||||||
|
|
||||||
|
if (tweetQueue.Count > 0){
|
||||||
|
Text = Text+" ("+tweetQueue.Count+" more left)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNotificationReady(){
|
||||||
|
UpdateTitle();
|
||||||
|
base.OnNotificationReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Bridge;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
using TweetDck.Resources;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification.Screenshot{
|
||||||
|
sealed class FormNotificationScreenshotable : FormNotificationBase{
|
||||||
|
public FormNotificationScreenshotable(Action callback, Form owner) : base(owner, false){
|
||||||
|
browser.RegisterAsyncJsObject("$TD_NotificationScreenshot", new CallbackBridge(this, callback));
|
||||||
|
|
||||||
|
browser.FrameLoadEnd += (sender, args) => {
|
||||||
|
if (args.Frame.IsMain && browser.Address != "about:blank"){
|
||||||
|
ScriptLoader.ExecuteScript(args.Frame, "window.setTimeout($TD_NotificationScreenshot.trigger, 67)", "gen:screenshot");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetTweetHTML(TweetNotification tweet){
|
||||||
|
return tweet.GenerateHtml(enableCustomCSS: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadNotificationForScreenshot(TweetNotification tweet, int width, int height){
|
||||||
|
LoadTweet(tweet);
|
||||||
|
SetNotificationSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TakeScreenshot(){
|
||||||
|
IntPtr context = NativeMethods.GetDC(this.Handle);
|
||||||
|
|
||||||
|
if (context == IntPtr.Zero){
|
||||||
|
MessageBox.Show("Could not retrieve a graphics context handle for the notification window to take the screenshot.", "Screenshot Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
using(Bitmap bmp = new Bitmap(ClientSize.Width, ClientSize.Height, PixelFormat.Format32bppRgb)){
|
||||||
|
try{
|
||||||
|
NativeMethods.RenderSourceIntoBitmap(context, bmp);
|
||||||
|
}finally{
|
||||||
|
NativeMethods.ReleaseDC(this.Handle, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
Clipboard.SetImage(bmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
Core/Notification/Screenshot/TweetScreenshotManager.cs
Normal file
75
Core/Notification/Screenshot/TweetScreenshotManager.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Uncomment to keep screenshot windows visible for debugging
|
||||||
|
// #define NO_HIDE_SCREENSHOTS
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification.Screenshot{
|
||||||
|
sealed class TweetScreenshotManager : IDisposable{
|
||||||
|
private readonly Form owner;
|
||||||
|
private readonly Timer timeout;
|
||||||
|
private readonly Timer disposer;
|
||||||
|
|
||||||
|
private FormNotificationScreenshotable screenshot;
|
||||||
|
|
||||||
|
public TweetScreenshotManager(Form owner){
|
||||||
|
this.owner = owner;
|
||||||
|
|
||||||
|
this.timeout = new Timer{ Interval = 8000 };
|
||||||
|
this.timeout.Tick += timeout_Tick;
|
||||||
|
|
||||||
|
this.disposer = new Timer{ Interval = 1 };
|
||||||
|
this.disposer.Tick += disposer_Tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timeout_Tick(object sender, EventArgs e){
|
||||||
|
timeout.Stop();
|
||||||
|
screenshot.Location = ControlExtensions.InvisibleLocation;
|
||||||
|
disposer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disposer_Tick(object sender, EventArgs e){
|
||||||
|
disposer.Stop();
|
||||||
|
screenshot.Dispose();
|
||||||
|
screenshot = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trigger(string html, int width, int height){
|
||||||
|
if (screenshot != null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
screenshot = new FormNotificationScreenshotable(Callback, owner){
|
||||||
|
CanMoveWindow = () => false
|
||||||
|
};
|
||||||
|
|
||||||
|
screenshot.LoadNotificationForScreenshot(new TweetNotification(string.Empty, html, 0, string.Empty, string.Empty), width, height);
|
||||||
|
screenshot.Show();
|
||||||
|
timeout.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Callback(){
|
||||||
|
if (!timeout.Enabled){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout.Stop();
|
||||||
|
screenshot.TakeScreenshot();
|
||||||
|
|
||||||
|
#if !(DEBUG && NO_HIDE_SCREENSHOTS)
|
||||||
|
screenshot.Location = ControlExtensions.InvisibleLocation;
|
||||||
|
disposer.Start();
|
||||||
|
#else
|
||||||
|
screenshot.MoveToVisibleLocation();
|
||||||
|
screenshot.FormClosed += (sender, args) => disposer.Start();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose(){
|
||||||
|
timeout.Dispose();
|
||||||
|
disposer.Dispose();
|
||||||
|
screenshot?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Core/Notification/Sound/ISoundNotificationPlayer.cs
Normal file
12
Core/Notification/Sound/ISoundNotificationPlayer.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification.Sound{
|
||||||
|
interface ISoundNotificationPlayer : IDisposable{
|
||||||
|
string SupportedFormats { get; }
|
||||||
|
|
||||||
|
event EventHandler<PlaybackErrorEventArgs> PlaybackError;
|
||||||
|
|
||||||
|
void Play(string file);
|
||||||
|
void Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Core/Notification/Sound/PlaybackErrorEventArgs.cs
Normal file
13
Core/Notification/Sound/PlaybackErrorEventArgs.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification.Sound{
|
||||||
|
sealed class PlaybackErrorEventArgs : EventArgs{
|
||||||
|
public string Message { get; }
|
||||||
|
public bool Ignore { get; set; }
|
||||||
|
|
||||||
|
public PlaybackErrorEventArgs(string message){
|
||||||
|
this.Message = message;
|
||||||
|
this.Ignore = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
Core/Notification/Sound/SoundPlayerImplFallback.cs
Normal file
53
Core/Notification/Sound/SoundPlayerImplFallback.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Media;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification.Sound{
|
||||||
|
sealed class SoundPlayerImplFallback : ISoundNotificationPlayer{
|
||||||
|
string ISoundNotificationPlayer.SupportedFormats => "*.wav";
|
||||||
|
|
||||||
|
public event EventHandler<PlaybackErrorEventArgs> PlaybackError;
|
||||||
|
|
||||||
|
private readonly SoundPlayer player;
|
||||||
|
private bool ignorePlaybackError;
|
||||||
|
|
||||||
|
public SoundPlayerImplFallback(){
|
||||||
|
player = new SoundPlayer{
|
||||||
|
LoadTimeout = 5000
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISoundNotificationPlayer.Play(string file){
|
||||||
|
if (player.SoundLocation != file){
|
||||||
|
player.SoundLocation = file;
|
||||||
|
ignorePlaybackError = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
player.Play();
|
||||||
|
}catch(FileNotFoundException e){
|
||||||
|
OnNotificationSoundError("File not found: "+e.FileName);
|
||||||
|
}catch(InvalidOperationException){
|
||||||
|
OnNotificationSoundError("File format was not recognized.");
|
||||||
|
}catch(TimeoutException){
|
||||||
|
OnNotificationSoundError("File took too long to load.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISoundNotificationPlayer.Stop(){
|
||||||
|
player.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisposable.Dispose(){
|
||||||
|
player.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNotificationSoundError(string message){
|
||||||
|
if (!ignorePlaybackError && PlaybackError != null){
|
||||||
|
PlaybackErrorEventArgs args = new PlaybackErrorEventArgs(message);
|
||||||
|
PlaybackError(this, args);
|
||||||
|
ignorePlaybackError = args.Ignore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
113
Core/Notification/Sound/SoundPlayerImplWMP.cs
Normal file
113
Core/Notification/Sound/SoundPlayerImplWMP.cs
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
using WMPLib;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification.Sound{
|
||||||
|
sealed class SoundPlayerImplWMP : ISoundNotificationPlayer{
|
||||||
|
string ISoundNotificationPlayer.SupportedFormats => "*.wav;*.mp3;*.mp2;*.m4a;*.mid;*.midi;*.rmi;*.wma;*.aif;*.aifc;*.aiff;*.snd;*.au";
|
||||||
|
|
||||||
|
public event EventHandler<PlaybackErrorEventArgs> PlaybackError;
|
||||||
|
|
||||||
|
private readonly WindowsMediaPlayer player;
|
||||||
|
private bool wasTryingToPlay;
|
||||||
|
private bool ignorePlaybackError;
|
||||||
|
|
||||||
|
// changing the player volume also affects the value in the Windows mixer
|
||||||
|
// however, the initial value is always 50 or some other stupid shit
|
||||||
|
// so we have to tell the player to set its volume to whatever the mixer is set to
|
||||||
|
// using the most code required for the least functionality with a sorry excuse for an API
|
||||||
|
// thanks, Microsoft
|
||||||
|
|
||||||
|
public SoundPlayerImplWMP(){
|
||||||
|
player = new WindowsMediaPlayer();
|
||||||
|
player.settings.autoStart = false;
|
||||||
|
player.settings.enableErrorDialogs = false;
|
||||||
|
player.settings.invokeURLs = false;
|
||||||
|
player.settings.volume = (int)Math.Floor(100.0*NativeCoreAudio.GetMixerVolumeForCurrentProcess());
|
||||||
|
player.MediaChange += player_MediaChange;
|
||||||
|
player.MediaError += player_MediaError;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISoundNotificationPlayer.Play(string file){
|
||||||
|
wasTryingToPlay = true;
|
||||||
|
|
||||||
|
try{
|
||||||
|
if (player.URL != file){
|
||||||
|
player.close();
|
||||||
|
player.URL = file;
|
||||||
|
ignorePlaybackError = false;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
player.controls.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
player.controls.play();
|
||||||
|
}catch(Exception e){
|
||||||
|
OnNotificationSoundError("An error occurred in Windows Media Player: "+e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISoundNotificationPlayer.Stop(){
|
||||||
|
try{
|
||||||
|
player.controls.stop();
|
||||||
|
}catch{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisposable.Dispose(){
|
||||||
|
player.close();
|
||||||
|
Marshal.ReleaseComObject(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void player_MediaChange(object item){
|
||||||
|
IWMPMedia2 media = item as IWMPMedia2;
|
||||||
|
|
||||||
|
if (media == null){
|
||||||
|
OnNotificationSoundError("Unknown error.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||||
|
else if (media.Error == null && media.duration == 0.0){
|
||||||
|
OnNotificationSoundError("File does not contain an audio track.");
|
||||||
|
}
|
||||||
|
else if (media.Error != null){
|
||||||
|
OnNotificationSoundError(media.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Marshal.ReleaseComObject(media);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void player_MediaError(object pMediaObject){
|
||||||
|
IWMPMedia2 media = pMediaObject as IWMPMedia2;
|
||||||
|
|
||||||
|
if (media == null){
|
||||||
|
OnNotificationSoundError("Unknown error.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (media.Error != null){
|
||||||
|
OnNotificationSoundError(media.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Marshal.ReleaseComObject(media);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNotificationSoundError(IWMPErrorItem error){
|
||||||
|
OnNotificationSoundError(error.errorCode == -1072885353 ? "Invalid media file." : error.errorDescription);
|
||||||
|
Marshal.ReleaseComObject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNotificationSoundError(string message){
|
||||||
|
if (wasTryingToPlay){
|
||||||
|
wasTryingToPlay = false;
|
||||||
|
|
||||||
|
if (!ignorePlaybackError && PlaybackError != null){
|
||||||
|
PlaybackErrorEventArgs args = new PlaybackErrorEventArgs(message);
|
||||||
|
PlaybackError(this, args);
|
||||||
|
ignorePlaybackError = args.Ignore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
Core/Notification/SoundNotification.cs
Normal file
28
Core/Notification/SoundNotification.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using TweetDck.Core.Notification.Sound;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification{
|
||||||
|
static class SoundNotification{
|
||||||
|
private static bool? IsWMPAvailable;
|
||||||
|
|
||||||
|
public static ISoundNotificationPlayer New(){
|
||||||
|
if (IsWMPAvailable.HasValue){
|
||||||
|
if (IsWMPAvailable.Value){
|
||||||
|
return new SoundPlayerImplWMP();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return new SoundPlayerImplFallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
SoundPlayerImplWMP implWMP = new SoundPlayerImplWMP();
|
||||||
|
IsWMPAvailable = true;
|
||||||
|
return implWMP;
|
||||||
|
}catch(COMException){
|
||||||
|
IsWMPAvailable = false;
|
||||||
|
return new SoundPlayerImplFallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
108
Core/Notification/TweetNotification.cs
Normal file
108
Core/Notification/TweetNotification.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using TweetDck.Resources;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Notification{
|
||||||
|
sealed class TweetNotification{
|
||||||
|
private static string FontSizeClass { get; set; }
|
||||||
|
private static string HeadTag { get; set; }
|
||||||
|
|
||||||
|
private const string DefaultFontSizeClass = "medium";
|
||||||
|
private const string DefaultHeadTag = @"<meta charset='utf-8'><meta http-equiv='X-UA-Compatible' content='chrome=1'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/font.5ef884f9f9.css'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/app-dark.5631e0dd42.css'><style type='text/css'>body{background:#222426}</style>";
|
||||||
|
private const string CustomCSS = @"body:before{content:none}body{overflow-y:auto}.scroll-styled-v::-webkit-scrollbar{width:7px}.scroll-styled-v::-webkit-scrollbar-thumb{border-radius:0}.scroll-styled-v::-webkit-scrollbar-track{border-left:0}#td-skip{opacity:0;cursor:pointer;transition:opacity 0.15s ease}.td-hover #td-skip{opacity:0.75}#td-skip:hover{opacity:1}";
|
||||||
|
|
||||||
|
public static int FontSizeLevel{
|
||||||
|
get{
|
||||||
|
switch(FontSizeClass){
|
||||||
|
case "largest": return 4;
|
||||||
|
case "large": return 3;
|
||||||
|
case "medium": return 2;
|
||||||
|
case "small": return 1;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExampleTweetHTML;
|
||||||
|
|
||||||
|
public static TweetNotification ExampleTweet{
|
||||||
|
get{
|
||||||
|
if (ExampleTweetHTML == null){
|
||||||
|
ExampleTweetHTML = ScriptLoader.LoadResource("pages/example.html", true);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
ExampleTweetHTML = ExampleTweetHTML.Replace("</p>", @"</p><div style='margin-top:64px'>Scrollbar test padding...</div>");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TweetNotification("Home", ExampleTweetHTML, 95, string.Empty, string.Empty, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetFontSizeClass(string newFSClass){
|
||||||
|
FontSizeClass = newFSClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetHeadTag(string headContents){
|
||||||
|
HeadTag = headContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Position{
|
||||||
|
TopLeft, TopRight, BottomLeft, BottomRight, Custom
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Column => column;
|
||||||
|
public string TweetUrl => tweetUrl;
|
||||||
|
public string QuoteUrl => quoteUrl;
|
||||||
|
|
||||||
|
private readonly string column;
|
||||||
|
private readonly string html;
|
||||||
|
private readonly int characters;
|
||||||
|
private readonly string tweetUrl;
|
||||||
|
private readonly string quoteUrl;
|
||||||
|
private readonly bool isExample;
|
||||||
|
|
||||||
|
public TweetNotification(string column, string html, int characters, string tweetUrl, string quoteUrl) : this(column, html, characters, tweetUrl, quoteUrl, false){}
|
||||||
|
|
||||||
|
private TweetNotification(string column, string html, int characters, string tweetUrl, string quoteUrl, bool isExample){
|
||||||
|
this.column = column;
|
||||||
|
this.html = html;
|
||||||
|
this.tweetUrl = tweetUrl;
|
||||||
|
this.quoteUrl = quoteUrl;
|
||||||
|
this.characters = characters;
|
||||||
|
this.isExample = isExample;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetDisplayDuration(int value){
|
||||||
|
return 2000+Math.Max(1000, value*characters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GenerateHtml(string bodyClasses = null, bool enableCustomCSS = true){
|
||||||
|
StringBuilder build = new StringBuilder();
|
||||||
|
build.Append("<!DOCTYPE html>");
|
||||||
|
build.Append("<html class='os-windows txt-base-").Append(FontSizeClass ?? DefaultFontSizeClass).Append("'>");
|
||||||
|
build.Append("<head>").Append(HeadTag ?? DefaultHeadTag);
|
||||||
|
|
||||||
|
if (enableCustomCSS){
|
||||||
|
build.Append("<style type='text/css'>").Append(CustomCSS).Append("</style>");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Program.UserConfig.CustomNotificationCSS)){
|
||||||
|
build.Append("<style type='text/css'>").Append(Program.UserConfig.CustomNotificationCSS).Append("</style>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build.Append("</head>");
|
||||||
|
build.Append("<body class='scroll-styled-v");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(bodyClasses)){
|
||||||
|
build.Append(' ').Append(bodyClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
build.Append('\'').Append(isExample ? " td-example-notification" : "").Append("><div class='column' style='width:100%;height:auto;overflow:initial;'>");
|
||||||
|
build.Append(html);
|
||||||
|
build.Append("</div></body>");
|
||||||
|
build.Append("</html>");
|
||||||
|
return build.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
126
Core/Other/FormAbout.Designer.cs
generated
126
Core/Other/FormAbout.Designer.cs
generated
@@ -1,5 +1,3 @@
|
|||||||
using TweetDck.Core.Controls;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Other {
|
namespace TweetDck.Core.Other {
|
||||||
sealed partial class FormAbout {
|
sealed partial class FormAbout {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,44 +23,134 @@ namespace TweetDck.Core.Other {
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.labelAbout = new TweetDck.Core.Controls.RichTextLabel();
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormAbout));
|
||||||
|
this.pictureLogo = new System.Windows.Forms.PictureBox();
|
||||||
|
this.labelDescription = new System.Windows.Forms.Label();
|
||||||
|
this.labelTips = new System.Windows.Forms.LinkLabel();
|
||||||
|
this.labelWebsite = new System.Windows.Forms.LinkLabel();
|
||||||
|
this.tablePanelLinks = new System.Windows.Forms.TableLayoutPanel();
|
||||||
|
this.labelIssues = new System.Windows.Forms.LinkLabel();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.pictureLogo)).BeginInit();
|
||||||
|
this.tablePanelLinks.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// labelAbout
|
// pictureLogo
|
||||||
//
|
//
|
||||||
this.labelAbout.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.pictureLogo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
|
||||||
|
this.pictureLogo.ErrorImage = null;
|
||||||
|
this.pictureLogo.Image = ((System.Drawing.Image)(resources.GetObject("pictureLogo.Image")));
|
||||||
|
this.pictureLogo.InitialImage = null;
|
||||||
|
this.pictureLogo.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.pictureLogo.Name = "pictureLogo";
|
||||||
|
this.pictureLogo.Size = new System.Drawing.Size(96, 96);
|
||||||
|
this.pictureLogo.TabIndex = 0;
|
||||||
|
this.pictureLogo.TabStop = false;
|
||||||
|
//
|
||||||
|
// labelDescription
|
||||||
|
//
|
||||||
|
this.labelDescription.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.labelAbout.BackColor = System.Drawing.Color.White;
|
this.labelDescription.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
this.labelAbout.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
this.labelDescription.Location = new System.Drawing.Point(114, 12);
|
||||||
this.labelAbout.Location = new System.Drawing.Point(12, 12);
|
this.labelDescription.Name = "labelDescription";
|
||||||
this.labelAbout.Name = "labelAbout";
|
this.labelDescription.Size = new System.Drawing.Size(232, 109);
|
||||||
this.labelAbout.ReadOnly = true;
|
this.labelDescription.TabIndex = 0;
|
||||||
this.labelAbout.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
|
//
|
||||||
this.labelAbout.Size = new System.Drawing.Size(360, 126);
|
// labelTips
|
||||||
this.labelAbout.TabIndex = 0;
|
//
|
||||||
this.labelAbout.TabStop = false;
|
this.labelTips.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.labelAbout.Text = "";
|
this.labelTips.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
this.labelAbout.Click += new System.EventHandler(this.labelAbout_Click);
|
this.labelTips.LinkArea = new System.Windows.Forms.LinkArea(0, 0);
|
||||||
|
this.labelTips.Location = new System.Drawing.Point(117, 0);
|
||||||
|
this.labelTips.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.labelTips.Name = "labelTips";
|
||||||
|
this.labelTips.Size = new System.Drawing.Size(99, 16);
|
||||||
|
this.labelTips.TabIndex = 1;
|
||||||
|
this.labelTips.TabStop = true;
|
||||||
|
this.labelTips.Text = "Tips && Tricks";
|
||||||
|
this.labelTips.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.labelTips.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
|
||||||
|
//
|
||||||
|
// labelWebsite
|
||||||
|
//
|
||||||
|
this.labelWebsite.AutoSize = true;
|
||||||
|
this.labelWebsite.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.labelWebsite.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelWebsite.LinkArea = new System.Windows.Forms.LinkArea(0, 0);
|
||||||
|
this.labelWebsite.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.labelWebsite.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.labelWebsite.Name = "labelWebsite";
|
||||||
|
this.labelWebsite.Size = new System.Drawing.Size(117, 16);
|
||||||
|
this.labelWebsite.TabIndex = 0;
|
||||||
|
this.labelWebsite.TabStop = true;
|
||||||
|
this.labelWebsite.Text = "Official Website";
|
||||||
|
this.labelWebsite.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
|
this.labelWebsite.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
|
||||||
|
//
|
||||||
|
// tablePanelLinks
|
||||||
|
//
|
||||||
|
this.tablePanelLinks.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.tablePanelLinks.ColumnCount = 3;
|
||||||
|
this.tablePanelLinks.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 35.16F));
|
||||||
|
this.tablePanelLinks.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 29.7F));
|
||||||
|
this.tablePanelLinks.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 35.14F));
|
||||||
|
this.tablePanelLinks.Controls.Add(this.labelIssues, 2, 0);
|
||||||
|
this.tablePanelLinks.Controls.Add(this.labelWebsite, 0, 0);
|
||||||
|
this.tablePanelLinks.Controls.Add(this.labelTips, 1, 0);
|
||||||
|
this.tablePanelLinks.Location = new System.Drawing.Point(12, 124);
|
||||||
|
this.tablePanelLinks.Name = "tablePanelLinks";
|
||||||
|
this.tablePanelLinks.RowCount = 1;
|
||||||
|
this.tablePanelLinks.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
|
this.tablePanelLinks.Size = new System.Drawing.Size(334, 16);
|
||||||
|
this.tablePanelLinks.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// labelIssues
|
||||||
|
//
|
||||||
|
this.labelIssues.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.labelIssues.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelIssues.LinkArea = new System.Windows.Forms.LinkArea(0, 0);
|
||||||
|
this.labelIssues.Location = new System.Drawing.Point(216, 0);
|
||||||
|
this.labelIssues.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.labelIssues.Name = "labelIssues";
|
||||||
|
this.labelIssues.Size = new System.Drawing.Size(118, 16);
|
||||||
|
this.labelIssues.TabIndex = 2;
|
||||||
|
this.labelIssues.TabStop = true;
|
||||||
|
this.labelIssues.Text = "Report an Issue";
|
||||||
|
this.labelIssues.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
|
this.labelIssues.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
|
||||||
//
|
//
|
||||||
// FormAbout
|
// FormAbout
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.BackColor = System.Drawing.Color.White;
|
this.BackColor = System.Drawing.Color.White;
|
||||||
this.ClientSize = new System.Drawing.Size(384, 150);
|
this.ClientSize = new System.Drawing.Size(358, 152);
|
||||||
this.Controls.Add(this.labelAbout);
|
this.Controls.Add(this.tablePanelLinks);
|
||||||
|
this.Controls.Add(this.labelDescription);
|
||||||
|
this.Controls.Add(this.pictureLogo);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||||
this.MaximizeBox = false;
|
this.MaximizeBox = false;
|
||||||
this.MinimizeBox = false;
|
this.MinimizeBox = false;
|
||||||
this.Name = "FormAbout";
|
this.Name = "FormAbout";
|
||||||
|
this.ShowIcon = false;
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.pictureLogo)).EndInit();
|
||||||
|
this.tablePanelLinks.ResumeLayout(false);
|
||||||
|
this.tablePanelLinks.PerformLayout();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private Controls.RichTextLabel labelAbout;
|
private System.Windows.Forms.PictureBox pictureLogo;
|
||||||
|
private System.Windows.Forms.Label labelDescription;
|
||||||
|
private System.Windows.Forms.LinkLabel labelTips;
|
||||||
|
private System.Windows.Forms.LinkLabel labelWebsite;
|
||||||
|
private System.Windows.Forms.TableLayoutPanel tablePanelLinks;
|
||||||
|
private System.Windows.Forms.LinkLabel labelIssues;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,43 +1,25 @@
|
|||||||
using System;
|
using System.Windows.Forms;
|
||||||
using System.Text;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using TweetDck.Core.Controls;
|
|
||||||
using TweetDck.Core.Utils;
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other{
|
namespace TweetDck.Core.Other{
|
||||||
sealed partial class FormAbout : Form{
|
sealed partial class FormAbout : Form{
|
||||||
private const string GitHubLink = "https://github.com/chylex/TweetDuck";
|
private const string TipsLink = "https://github.com/chylex/TweetDuck/wiki";
|
||||||
|
private const string IssuesLink = "https://github.com/chylex/TweetDuck/issues";
|
||||||
|
|
||||||
public FormAbout(){
|
public FormAbout(){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Text = "About "+Program.BrandName+" "+Program.VersionTag;
|
Text = "About "+Program.BrandName+" "+Program.VersionTag;
|
||||||
|
|
||||||
StringBuilder build = new StringBuilder();
|
labelDescription.Text = Program.BrandName+" was created by chylex as a replacement to the discontinued official TweetDeck client for Windows.\n\nThe program is available for free under the open source MIT license.";
|
||||||
build.Append(@"\fs22").Append(Program.BrandName).Append(@" was created by chylex as a replacement to the discontinued TweetDeck client for Windows, and is released under the MIT license.\par ");
|
|
||||||
build.Append(@"Official Website: ").Append(RichTextLabel.AddLink(Program.Website)).Append(@"\line ");
|
|
||||||
build.Append(@"Source Code: ").Append(RichTextLabel.AddLink(GitHubLink));
|
|
||||||
|
|
||||||
labelAbout.Rtf = RichTextLabel.Wrap(build.ToString());
|
labelWebsite.Links.Add(new LinkLabel.Link(0, labelWebsite.Text.Length, Program.Website));
|
||||||
|
labelTips.Links.Add(new LinkLabel.Link(0, labelTips.Text.Length, TipsLink));
|
||||||
|
labelIssues.Links.Add(new LinkLabel.Link(0, labelIssues.Text.Length, IssuesLink));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void labelAbout_Click(object sender, EventArgs e){ // LinkClicked isn't working so fuck that
|
private void OnLinkClicked(object sender, LinkLabelLinkClickedEventArgs e){
|
||||||
if (Cursor.Current != Cursors.Hand)return;
|
BrowserUtils.OpenExternalBrowserUnsafe(e.Link.LinkData as string);
|
||||||
|
|
||||||
// I don't even give a fuck, someone else PR a proper fix please
|
|
||||||
int index = labelAbout.GetCharIndexFromPosition(((MouseEventArgs)e).Location);
|
|
||||||
|
|
||||||
if (IsClickingOn(index,Program.Website)){
|
|
||||||
BrowserUtils.OpenExternalBrowser(Program.Website);
|
|
||||||
}
|
|
||||||
else if (IsClickingOn(index,GitHubLink)){
|
|
||||||
BrowserUtils.OpenExternalBrowser(GitHubLink);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsClickingOn(int index, string substringSearch){
|
|
||||||
int substringIndex = labelAbout.Text.IndexOf(substringSearch,StringComparison.Ordinal);
|
|
||||||
return index >= substringIndex && index <= substringIndex+substringSearch.Length;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
246
Core/Other/FormAbout.resx
Normal file
246
Core/Other/FormAbout.resx
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
|
<data name="pictureLogo.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACH
|
||||||
|
DwAAjA8AAP1SAACBQAAAfXkAAOmLAAA85QAAGcxzPIV3AAAKOWlDQ1BQaG90b3Nob3AgSUNDIHByb2Zp
|
||||||
|
bGUAAEjHnZZ3VFTXFofPvXd6oc0wAlKG3rvAANJ7k15FYZgZYCgDDjM0sSGiAhFFRJoiSFDEgNFQJFZE
|
||||||
|
sRAUVLAHJAgoMRhFVCxvRtaLrqy89/Ly++Osb+2z97n77L3PWhcAkqcvl5cGSwGQyhPwgzyc6RGRUXTs
|
||||||
|
AIABHmCAKQBMVka6X7B7CBDJy82FniFyAl8EAfB6WLwCcNPQM4BOB/+fpFnpfIHomAARm7M5GSwRF4g4
|
||||||
|
JUuQLrbPipgalyxmGCVmvihBEcuJOWGRDT77LLKjmNmpPLaIxTmns1PZYu4V8bZMIUfEiK+ICzO5nCwR
|
||||||
|
3xKxRoowlSviN+LYVA4zAwAUSWwXcFiJIjYRMYkfEuQi4uUA4EgJX3HcVyzgZAvEl3JJS8/hcxMSBXQd
|
||||||
|
li7d1NqaQffkZKVwBALDACYrmcln013SUtOZvBwAFu/8WTLi2tJFRbY0tba0NDQzMv2qUP91829K3NtF
|
||||||
|
ehn4uWcQrf+L7a/80hoAYMyJarPziy2uCoDOLQDI3fti0zgAgKSobx3Xv7oPTTwviQJBuo2xcVZWlhGX
|
||||||
|
wzISF/QP/U+Hv6GvvmckPu6P8tBdOfFMYYqALq4bKy0lTcinZ6QzWRy64Z+H+B8H/nUeBkGceA6fwxNF
|
||||||
|
hImmjMtLELWbx+YKuGk8Opf3n5r4D8P+pMW5FonS+BFQY4yA1HUqQH7tBygKESDR+8Vd/6NvvvgwIH55
|
||||||
|
4SqTi3P/7zf9Z8Gl4iWDm/A5ziUohM4S8jMX98TPEqABAUgCKpAHykAd6ABDYAasgC1wBG7AG/iDEBAJ
|
||||||
|
VgMWSASpgA+yQB7YBApBMdgJ9oBqUAcaQTNoBcdBJzgFzoNL4Bq4AW6D+2AUTIBnYBa8BgsQBGEhMkSB
|
||||||
|
5CEVSBPSh8wgBmQPuUG+UBAUCcVCCRAPEkJ50GaoGCqDqqF6qBn6HjoJnYeuQIPQXWgMmoZ+h97BCEyC
|
||||||
|
qbASrAUbwwzYCfaBQ+BVcAK8Bs6FC+AdcCXcAB+FO+Dz8DX4NjwKP4PnEIAQERqiihgiDMQF8UeikHiE
|
||||||
|
j6xHipAKpAFpRbqRPuQmMorMIG9RGBQFRUcZomxRnqhQFAu1BrUeVYKqRh1GdaB6UTdRY6hZ1Ec0Ga2I
|
||||||
|
1kfboL3QEegEdBa6EF2BbkK3oy+ib6Mn0K8xGAwNo42xwnhiIjFJmLWYEsw+TBvmHGYQM46Zw2Kx8lh9
|
||||||
|
rB3WH8vECrCF2CrsUexZ7BB2AvsGR8Sp4Mxw7rgoHA+Xj6vAHcGdwQ3hJnELeCm8Jt4G749n43PwpfhG
|
||||||
|
fDf+On4Cv0CQJmgT7AghhCTCJkIloZVwkfCA8JJIJKoRrYmBRC5xI7GSeIx4mThGfEuSIemRXEjRJCFp
|
||||||
|
B+kQ6RzpLuklmUzWIjuSo8gC8g5yM/kC+RH5jQRFwkjCS4ItsUGiRqJDYkjiuSReUlPSSXK1ZK5kheQJ
|
||||||
|
yeuSM1J4KS0pFymm1HqpGqmTUiNSc9IUaVNpf+lU6RLpI9JXpKdksDJaMm4ybJkCmYMyF2TGKQhFneJC
|
||||||
|
YVE2UxopFykTVAxVm+pFTaIWU7+jDlBnZWVkl8mGyWbL1sielh2lITQtmhcthVZKO04bpr1borTEaQln
|
||||||
|
yfYlrUuGlszLLZVzlOPIFcm1yd2WeydPl3eTT5bfJd8p/1ABpaCnEKiQpbBf4aLCzFLqUtulrKVFS48v
|
||||||
|
vacIK+opBimuVTyo2K84p6Ss5KGUrlSldEFpRpmm7KicpFyufEZ5WoWiYq/CVSlXOavylC5Ld6Kn0Cvp
|
||||||
|
vfRZVUVVT1Whar3qgOqCmrZaqFq+WpvaQ3WCOkM9Xr1cvUd9VkNFw08jT6NF454mXpOhmai5V7NPc15L
|
||||||
|
Wytca6tWp9aUtpy2l3audov2Ax2yjoPOGp0GnVu6GF2GbrLuPt0berCehV6iXo3edX1Y31Kfq79Pf9AA
|
||||||
|
bWBtwDNoMBgxJBk6GWYathiOGdGMfI3yjTqNnhtrGEcZ7zLuM/5oYmGSYtJoct9UxtTbNN+02/R3Mz0z
|
||||||
|
llmN2S1zsrm7+QbzLvMXy/SXcZbtX3bHgmLhZ7HVosfig6WVJd+y1XLaSsMq1qrWaoRBZQQwShiXrdHW
|
||||||
|
ztYbrE9Zv7WxtBHYHLf5zdbQNtn2iO3Ucu3lnOWNy8ft1OyYdvV2o/Z0+1j7A/ajDqoOTIcGh8eO6o5s
|
||||||
|
xybHSSddpySno07PnU2c+c7tzvMuNi7rXM65Iq4erkWuA24ybqFu1W6P3NXcE9xb3Gc9LDzWepzzRHv6
|
||||||
|
eO7yHPFS8mJ5NXvNelt5r/Pu9SH5BPtU+zz21fPl+3b7wX7efrv9HqzQXMFb0ekP/L38d/s/DNAOWBPw
|
||||||
|
YyAmMCCwJvBJkGlQXlBfMCU4JvhI8OsQ55DSkPuhOqHC0J4wybDosOaw+XDX8LLw0QjjiHUR1yIVIrmR
|
||||||
|
XVHYqLCopqi5lW4r96yciLaILoweXqW9KnvVldUKq1NWn46RjGHGnIhFx4bHHol9z/RnNjDn4rziauNm
|
||||||
|
WS6svaxnbEd2OXuaY8cp40zG28WXxU8l2CXsTphOdEisSJzhunCruS+SPJPqkuaT/ZMPJX9KCU9pS8Wl
|
||||||
|
xqae5Mnwknm9acpp2WmD6frphemja2zW7Fkzy/fhN2VAGasyugRU0c9Uv1BHuEU4lmmfWZP5Jiss60S2
|
||||||
|
dDYvuz9HL2d7zmSue+63a1FrWWt78lTzNuWNrXNaV78eWh+3vmeD+oaCDRMbPTYe3kTYlLzpp3yT/LL8
|
||||||
|
V5vDN3cXKBVsLBjf4rGlpVCikF84stV2a9021DbutoHt5turtn8sYhddLTYprih+X8IqufqN6TeV33za
|
||||||
|
Eb9joNSydP9OzE7ezuFdDrsOl0mX5ZaN7/bb3VFOLy8qf7UnZs+VimUVdXsJe4V7Ryt9K7uqNKp2Vr2v
|
||||||
|
Tqy+XeNc01arWLu9dn4fe9/Qfsf9rXVKdcV17w5wD9yp96jvaNBqqDiIOZh58EljWGPft4xvm5sUmoqb
|
||||||
|
PhziHRo9HHS4t9mqufmI4pHSFrhF2DJ9NProje9cv+tqNWytb6O1FR8Dx4THnn4f+/3wcZ/jPScYJ1p/
|
||||||
|
0Pyhtp3SXtQBdeR0zHYmdo52RXYNnvQ+2dNt293+o9GPh06pnqo5LXu69AzhTMGZT2dzz86dSz83cz7h
|
||||||
|
/HhPTM/9CxEXbvUG9g5c9Ll4+ZL7pQt9Tn1nL9tdPnXF5srJq4yrndcsr3X0W/S3/2TxU/uA5UDHdavr
|
||||||
|
XTesb3QPLh88M+QwdP6m681Lt7xuXbu94vbgcOjwnZHokdE77DtTd1PuvriXeW/h/sYH6AdFD6UeVjxS
|
||||||
|
fNTws+7PbaOWo6fHXMf6Hwc/vj/OGn/2S8Yv7ycKnpCfVEyqTDZPmU2dmnafvvF05dOJZ+nPFmYKf5X+
|
||||||
|
tfa5zvMffnP8rX82YnbiBf/Fp99LXsq/PPRq2aueuYC5R69TXy/MF72Rf3P4LeNt37vwd5MLWe+x7ys/
|
||||||
|
6H7o/ujz8cGn1E+f/gUDmPP8usTo0wAAAAlwSFlzAAAuIgAALiIBquLdkgAAEVpJREFUeF7tXQl0VNd5
|
||||||
|
Thq3Tk7tc+qmiZMm7YmdJj1OT3Gd0kTMG3mJnZQEJzaSjXETx0lqNwt2jWscQGixBAJLSMhgA8YYbIyQ
|
||||||
|
hHYJI4lFGMwioQWxyewgMdoXtKFd4u/337lPjDRv9pk3g+A75zsMWv577/fd+9/l3Rl9johu0Y/U/OIt
|
||||||
|
6sfrLwIYT2de+SJ4F/j34LfB+8Ap4L9J8uvvgfy9b4DfBO8EPy9DBBwC3gCI93fgDHAuuA7cDVaDzWAX
|
||||||
|
OAAOgcNgP9gN8vc+A4vB9eBr4M/Be8GAMiPgDIBAXwVDwbXgEbAPJC+RDToGvgfOBr8mi/UbAsIACMFp
|
||||||
|
ZRaYC7aBWuL5gh3gdvBZ8C5ZHV3hVwPQaM7hS0ETqCWQnqwDE8Apsnq6wC8GoJEPgFtAzt9aYviTPJ9k
|
||||||
|
gkGyuj6FrgagUd8CeVIcBLUaH0gcATeD35XV9wl0MQCN4OXjn8EroFZjA5m8qooE/1o2x6vwuQGouAEs
|
||||||
|
A7UadyPxOPgj2SyvwacGoMILwRsh3ThLTksx4BdkEz2GTwxABb8C8pJSqxGTgTvAb8jmegSvG4CK/QvI
|
||||||
|
O1Wtik8mXgSnyma7Da8agAo9Auq5kfI3+Shkhmy+W/CaAajI42CvrNjNRJ7jZksZXIZXDEAFWPxA3FTp
|
||||||
|
xVHQLRM8NgAFPwTejD1/InkH/biUxWl4ZAAK5LP3mynnO+JV0KWJ2W0DUNCXwVOy4Fu8zhrQ6SWqJwbk
|
||||||
|
WxQa2Mxop6fSWyk0rYlCUhspZEs9zdxSJ8iv+WuhW5vpqYw27d93nXvB26RUduGWAQg+36KwwCULv7VF
|
||||||
|
iDx3Wx1tPNxCBy92UU17P7VdHaLWniE619JLu8900Nv7m+jFLBgCM9gs/l3NmCqlqU+nt+D/msYtk3LZ
|
||||||
|
hcsGIPB/gPaPF7jyKrW+rwNZnJCUBoraUU9H63po9No1NM8++odGac/ZDno5r45C2QitESGF59gv5dVT
|
||||||
|
clUHzc5gEyb8XOaVa6DDsyMU67wBCHg7WCULsEkezi9/jEptbfKLCdzrn0s30b5znWiS6xgeuUaby1so
|
||||||
|
NKVubDSwGZzCOG3NzTdRQXW7+NnM4+b2atUDPAPeIeXTBEK4ZMA8i+Ca5Ir+LrOOOvtHKGkfcit6kp4m
|
||||||
|
sBh/zDGRqaMfzfEMh5CuZiXXUOgWE72Ua6L1Jc10qqmXRkbNo4nT2PMw2sHcESvl0wTCOGcAAv0DyFtv
|
||||||
|
rULGyAKsO9SMUERD6EnRO+t1M4F76++zTNTUNSjK9wYutvVhzujTTGGrMG/wqNCqiwX5IsA/SxmtgDBO
|
||||||
|
G7DBIqhN8oR3suEqQpnRh7watcOcU31pAvfCWUgZ1Y3Xy/YlCk+Z28rlqrTTvkwpoxUQyrEBCPCvoONz
|
||||||
|
fVTg1xkm6hkYQajr4Mktdpd5uecrE9jg5IpWWaJvwRN1SHKtaA/PCfMLmyiq2DxPaNUN5KMKg5RzHBDO
|
||||||
|
KQNSLYLZJFfgVSz3tMBDeM0BrMNlr9H6fXfJ8V7AErK7f1iW5hsMjYxSSnkjPbnxLP1vbq2YE04399KV
|
||||||
|
vmGak9/kqF0FUs5xQFj7BuAXvwM6ddDGOfiNnQ0IYxvbTrYjVWDiwkrFW6OB83DaEd/3/obOfiq71Ekt
|
||||||
|
3YOkzgg8NUTxPOdgLpiV1TE6K7vzASnrGBDCoQF8b0cz6ESyqDG77BvAOI2VxJycy7bX2q4QJoYgDVxo
|
||||||
|
7ZPR9QVv4OzNb7OyOll8mpnWTNPXnlwnZR0DQtg2AAHuAPnCkmbwieQREFZQjzCOwfPChlJs/3mt7cFo
|
||||||
|
YAPn5NTRsFwa6on3kII05zUIjt4uXv9icx099u5pCn7rKBkSynoMC1K/LuUVQBi7BswcF9gBWYzfZ5vE
|
||||||
|
RsZZnG/powjsVsXc4IYR/DtLix2POm+C9wGrPjWfK1nWl3v6MxA+FB1xxgeX6OF3TpKSdASsIiMMMK48
|
||||||
|
TkpM4RwprwDC2TUgTw3uFFEZXgo2dA4glPNgu8pruyms0HxAJnaWThrBP7v2oHnfoQd48xWBelqmHe7t
|
||||||
|
Is2kNNJ/rj9HD648RsoKC+FVwgBj/MGDUl4BhNQ2AIH/FuTLq1aNtkfuFYWfXUEo18FGHKvrofg9DfRs
|
||||||
|
mknEcjQq2ABejeiFyEKTWXyUbU4z7fSLj0z06NpTELnKLLyl6BOZVDVgDM+8R8ps14AQy4Y6S1fmAXvg
|
||||||
|
npZ/oo0iiuro2VSYkdIgVhocX0zc0hQ2YDWWt3phIdrGp5+hW1vpZxsv0SOcZrR6uy1iFAQvLvqDlNmu
|
||||||
|
Ae9aCus0IQzn8/LL3QjnHbAZpZe6RE9fsL2O/jvTJFIdlzMz2URRhZflT/oer+fX0E/ePUXBttKMI3Ia
|
||||||
|
enNfhpRZ2wAI+XnQ4amnLXLamPdxHQ1i4+IL8AqqHvMMp6vdZ65Q8en2sXW5r/HbjZVYzVRoi+sMYZwx
|
||||||
|
saxWWbj1Swhn04B/BPkQSVNgu+TUAHKefB/LzMkE3s3PXgfxsbLRFNd5XlMWZT6AkDYN+JmVsE5QLEPz
|
||||||
|
WujXGY0iZ3N60GOHqheuDgzT4++U80SqJarz5DQUXfAcQlobACE5/fAb4jRFtkdOPatLWqmrf4RSKlvo
|
||||||
|
1fzL9MSGM7TuQJ04R7nR0dDRSw8mlGqL6gpXniDjkp2xyoKULyCslQH81MutCZgNWLz7+qaI83Jz9yAm
|
||||||
|
0A5q6/HeGb2/cPxyBxnivWEAT8T7c4Mjc+5EWCsD/gbkt4JqimyP6rGA+sRosqHgWD0Zlh/WFtUVsgHL
|
||||||
|
S44aI3O/hrBWBvCboN273cwTMJaHvEKZjEgsOkNKogcrIJViJVTeaIzefi/CWhnA7zJvGiesC+TVT85x
|
||||||
|
8wPryYYXNpl3upqiukQYsKKyR1my63sIa2UAv3WU3xelKbAj8k71lXz/nE76Em09A/Tjt5B+PF0BqUw6
|
||||||
|
MogN2RSEtjKAHz+6twdg8k6Yz4NOuXceFKgorm7yTv5XmXRkVIk78H2EtjLgfpBv+moL7AR5Mv5NRp1X
|
||||||
|
byf4GzH5n3kn/6vkkbS8dCpCWxnAnzrikQFMPiRbWFAnbkXc6OAN2BNreAPmjfwvyQbEH9I0gD/yxfM3
|
||||||
|
W/BxRFqTuBrYOzj+lsSNht0nG72bfphJVddgwL8jvJUBHk3C4yhNeCXfRJfaPL+p5i+8ln4Cq59KbSHd
|
||||||
|
ZVLloLJs7/0Ib2UAL0NbxgnpCWEC75Bnp5rog7IW6ujz7dURb+NsYxdvmswpQ0tItyiWod1KTJHmMpQ3
|
||||||
|
YvxhR9qCukiekGenN4tHjU9+VENPbzpLcbtq6GS9954X+BLLtp/y7uTLNG/EmozRBd9GEVYG8Gf37LEU
|
||||||
|
0RNy7/+o8gqdae6jQxc76eCFTqqo7aTGzsBPSRdbeuihRG/3fpANiC85qkTkaB5F8Adr8CeaaArqKsUj
|
||||||
|
yiJ9by14C2/keXnpqXIV5pTYPblB8zZ9BcVYGcDH0f9nKaJH5I1ZSgMduNCF8DcOjtS0k+L13C/JBize
|
||||||
|
EWeYn3wbihpvgHwgw+/71RbUDfIo+FNuvdWl3UAFn+a+KM59vLzyUWl+IPMbFHVd97EXZgPuAb3yKSfq
|
||||||
|
ZSUeBbFFNSgi8PHRwRrzut8Xvd/Ma8FR+XYfSf4FyJ+PoymqM1TvRIakNtP098/TQ5h4psWXUnzBaRQT
|
||||||
|
uDhZ1yknXi/uei0JHZTlpbVBr6z7IoqzNkAlRHR9Ira4E/lEcv31O5Hq9Q2Qe9bCrJPU3T+EYgILPajT
|
||||||
|
r96v8F3qYSL/G5bszuKOjiLHeP2FBETkj5G0FlmDapp5amsrzfiwhh5ZPeFOpCXxNSWxnGauKaed2OI7
|
||||||
|
8eZF3RCejXqjbj5MPWYDInJfZo1RpF0D+EOX7L4nbOzqdWqTSDN8J3Kst2sVbkF+sMGj4fmNlZR2uFas
|
||||||
|
uYflg3t/mLJy11lf530Q6/+3qoaw+vkOa4xibRvAgMj8oaYTRLe+eu3UnUgt8mhgIxLKKBhLvsdXltDc
|
||||||
|
zRV0qUXfXfKHBy7pID4ongUfKpfyOmXAf00U3ubVa0+IOCzAM+vKqOxCG6qhHzbziodvOvhq0rUk0k9Q
|
||||||
|
WPpLUl4BVMG2AbOyu+4CW1j8Jx1dvXaHLDx6/09XHabU0loaHNb32cG7n1zQT3w+fkgs75r6Pwl3S3kF
|
||||||
|
UA3bBjB+vvH8CnH1WqYLzeCukEcNVhnc459YXSaGf0evvk/O2OjovGqZdnQQn/l2NQVF5G2Qso4B1bFv
|
||||||
|
gCEs/X6kmhHNoCp5NHBDBPm1ShYbTKwQPZ1723T09tfTT4hnrL2D+h9N17Zdpd9uNI88UUet9viCGAFB
|
||||||
|
r29WpKxjQJXsG8AwLtv3sbhOpxUYjZi+5hg9s+E4zVpfRT9ZeZh+nFRKP11ZRqFry+mFD6soKreakg/V
|
||||||
|
iPzuz/V/TqVJ1E2s83UVX9yE2294baPV3y5AtRwboIRnT0OgUavAko++fZR++cFxKj7VQgPDI9Q3OCKE
|
||||||
|
HhgKjLOfc03d9ErqcX1TjiVhADLJdCnnOKB6jg1gGOP2pwsntQpAbxLzw/JSCsuqprNocCCgoaOPEgrP
|
||||||
|
0MOJJeZjZT17vUo++Vz6yU4poxVQTScNWJT5XfSefvNmQqMgJhuBhirxJTQ/4wRVXGqnUT9c0Drf3E3L
|
||||||
|
IfyPON2Ina0fer0gVoxJVcNBr31g9QZtFaiucwYwjEt2xdqcCywpRgRWOph0f7m+QuT/y+1XfbrD5Ztr
|
||||||
|
24/V05wtR8Wmzr/CS7JWscWrpHyaQNWdN0AJS7vDmFh2zmYqmkiZmnjF8WBCibhbuWbPeTqMyZiXnp4Y
|
||||||
|
wgdnfF2cl7Gc3x9Db+ccr/sEa4u87l9R3hAcnvllKZ8m0BTnDWAo4VmPGldyIXZSkRalGdwzeWTwaonP
|
||||||
|
gRZlV9O6vRcoq8JEu7E0LTnXSidMHSKNHK29Qofwf76Xw99/Dz8XiRXV7z48QjPeLkOqg+gwN2BEtyRv
|
||||||
|
WCNyQqRsNuGyAQxlya44p1KRPaqGQDxhCnrvGFlYlRZf558TcwxP+IEmuCXFI8eda6RcduGWAcaFaX9p
|
||||||
|
jD/0qdOp6GYia7K8pCp4UfqXpFx24ZYBDGVB6jeNKypMt0ywoPm8p9UYkW3zI8omwm0DGIbXN//AuKKy
|
||||||
|
VxSsVaGbiWYNhrBpdenPnHhkAAMTzUwUPnxTm6C2PWrbc1IWp+GxAQxDePavxlXkpiLazO2OKfqjlMMl
|
||||||
|
eMUABruPCt1kI4HbiuVm9PY/SRlchtcMYBjCMkJQMcwJN8HEzB0tqWrIGF3wvGy+W/CqAQwlLH2aknDY
|
||||||
|
xGthzYpPBnIHW1HRYozMeUw222143QDGtD8n3yP2CcKESZaSeAOaUFpuDM+8TzbXI/jEAIZxYepfGaIL
|
||||||
|
48yVngQpiVMO2qHEFq81Lkr32p819JkBKgyLMmeYD/Bu4NHAdU8sr1Ui85+SzfIafG4Aw7go4y5jbPEy
|
||||||
|
8TzhRpobxMitGjYu3fOOMWzrV2VzvApdDFDxw3mbpyhL92aL09RATkuibhitb35agIn2h7L6PoGuBqgw
|
||||||
|
hOc8Zow7UCQayyMiIPYOnONlmow7sEeJzPPoL+Q5C78YoAI76KBpMTtXK4nlLcZV6HVqz9MUyEfkMpkr
|
||||||
|
KnuMSz/ZpETkPCyrpwv8aoCKH8zdcPe0yG0vYum6X8wTLIivRoZczQgmVQ2izBIluvBVZeHWb8nq6IqA
|
||||||
|
MMASWDX9k+GN7X8wxO5JU5aXnjeLxoKxIVI4YYzKCQKrX7cUWpiJf/n7CWW1yrJ9WcaYwpeU8Cynj419
|
||||||
|
hYAzwBJB8zbdHhyVd78xpuA5ZfHOWEzgWeixFVgSNiBldGG0DICj4uE7PyEzvx4Q6YQ/ECm+5Cgm0jxl
|
||||||
|
8Y5lyhsfPw9zpyrzU3zyp8ndRUAbwFDrZViQdlvQ/NQ7kKPvNkYX3GuIKbpPWfrJFP7IFyXu4FQYM1V5
|
||||||
|
c//3lWV7p/A70JWobfcq4dlfN4Zn3WmYn3y7GseSgYCxulhW7Bb1p+YXb1Ev0uf+H9A3E1Z4VJUaAAAA
|
||||||
|
AElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
78
Core/Other/FormBackgroundWork.Designer.cs
generated
78
Core/Other/FormBackgroundWork.Designer.cs
generated
@@ -1,78 +0,0 @@
|
|||||||
using TweetDck.Core.Controls;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Other {
|
|
||||||
partial class FormBackgroundWork {
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing) {
|
|
||||||
if (disposing && (components != null)) {
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Windows Form Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent() {
|
|
||||||
this.progressBarUseless = new System.Windows.Forms.ProgressBar();
|
|
||||||
this.labelDescription = new RichTextLabel();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// progressBarUseless
|
|
||||||
//
|
|
||||||
this.progressBarUseless.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.progressBarUseless.Location = new System.Drawing.Point(12, 49);
|
|
||||||
this.progressBarUseless.MarqueeAnimationSpeed = 10;
|
|
||||||
this.progressBarUseless.Name = "progressBarUseless";
|
|
||||||
this.progressBarUseless.Size = new System.Drawing.Size(480, 23);
|
|
||||||
this.progressBarUseless.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
|
|
||||||
this.progressBarUseless.TabIndex = 0;
|
|
||||||
//
|
|
||||||
// labelDescription
|
|
||||||
//
|
|
||||||
this.labelDescription.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.labelDescription.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
|
||||||
this.labelDescription.Location = new System.Drawing.Point(12, 12);
|
|
||||||
this.labelDescription.Name = "labelDescription";
|
|
||||||
this.labelDescription.ReadOnly = true;
|
|
||||||
this.labelDescription.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
|
|
||||||
this.labelDescription.Size = new System.Drawing.Size(480, 31);
|
|
||||||
this.labelDescription.TabIndex = 1;
|
|
||||||
this.labelDescription.TabStop = false;
|
|
||||||
this.labelDescription.Text = "";
|
|
||||||
//
|
|
||||||
// FormBackgroundWork
|
|
||||||
//
|
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
|
||||||
this.ClientSize = new System.Drawing.Size(504, 84);
|
|
||||||
this.Controls.Add(this.labelDescription);
|
|
||||||
this.Controls.Add(this.progressBarUseless);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
|
||||||
this.Name = "FormBackgroundWork";
|
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
|
||||||
this.Text = "TweetDeck Migration";
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private System.Windows.Forms.ProgressBar progressBarUseless;
|
|
||||||
private RichTextLabel labelDescription;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using TweetDck.Core.Controls;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Other{
|
|
||||||
partial class FormBackgroundWork : Form{
|
|
||||||
public FormBackgroundWork(){
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
labelDescription.Rtf = RichTextLabel.Wrap(@"Please, watch this informationless progress bar showcase while some magic happens in the background...");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowWorkDialog(Action onBegin){
|
|
||||||
Shown += (sender, args) => onBegin();
|
|
||||||
ShowDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
80
Core/Other/FormMessage.Designer.cs
generated
Normal file
80
Core/Other/FormMessage.Designer.cs
generated
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
namespace TweetDck.Core.Other {
|
||||||
|
partial class FormMessage {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.panelActions = new System.Windows.Forms.Panel();
|
||||||
|
this.labelMessage = new System.Windows.Forms.Label();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// panelActions
|
||||||
|
//
|
||||||
|
this.panelActions.BackColor = System.Drawing.SystemColors.Control;
|
||||||
|
this.panelActions.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
|
this.panelActions.Location = new System.Drawing.Point(0, 84);
|
||||||
|
this.panelActions.Name = "panelActions";
|
||||||
|
this.panelActions.Size = new System.Drawing.Size(98, 49);
|
||||||
|
this.panelActions.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// labelMessage
|
||||||
|
//
|
||||||
|
this.labelMessage.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.labelMessage.AutoSize = true;
|
||||||
|
this.labelMessage.Font = System.Drawing.SystemFonts.MessageBoxFont;
|
||||||
|
this.labelMessage.Location = new System.Drawing.Point(62, 34);
|
||||||
|
this.labelMessage.Margin = new System.Windows.Forms.Padding(53, 24, 27, 24);
|
||||||
|
this.labelMessage.MaximumSize = new System.Drawing.Size(600, 0);
|
||||||
|
this.labelMessage.MinimumSize = new System.Drawing.Size(0, 24);
|
||||||
|
this.labelMessage.Name = "labelMessage";
|
||||||
|
this.labelMessage.Size = new System.Drawing.Size(0, 24);
|
||||||
|
this.labelMessage.TabIndex = 1;
|
||||||
|
this.labelMessage.SizeChanged += new System.EventHandler(this.labelMessage_SizeChanged);
|
||||||
|
//
|
||||||
|
// FormMessage
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.BackColor = System.Drawing.Color.White;
|
||||||
|
this.ClientSize = new System.Drawing.Size(98, 133);
|
||||||
|
this.Controls.Add(this.labelMessage);
|
||||||
|
this.Controls.Add(this.panelActions);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "FormMessage";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
|
this.SizeChanged += new System.EventHandler(this.FormMessage_SizeChanged);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Panel panelActions;
|
||||||
|
private System.Windows.Forms.Label labelMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
138
Core/Other/FormMessage.cs
Normal file
138
Core/Other/FormMessage.cs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other{
|
||||||
|
sealed partial class FormMessage : Form{
|
||||||
|
public Button ClickedButton { get; private set; }
|
||||||
|
|
||||||
|
public int ActionPanelY => panelActions.Location.Y;
|
||||||
|
|
||||||
|
private int ClientWidth{
|
||||||
|
get => ClientSize.Width;
|
||||||
|
set => ClientSize = new Size(value, ClientSize.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Icon icon;
|
||||||
|
private readonly bool isReady;
|
||||||
|
|
||||||
|
private int realFormWidth, minFormWidth;
|
||||||
|
private int buttonCount;
|
||||||
|
private int prevLabelWidth, prevLabelHeight;
|
||||||
|
private bool wasLabelMultiline;
|
||||||
|
|
||||||
|
public FormMessage(string caption, string text, MessageBoxIcon messageIcon){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.prevLabelWidth = labelMessage.Width;
|
||||||
|
this.prevLabelHeight = labelMessage.Height;
|
||||||
|
this.minFormWidth = 40;
|
||||||
|
|
||||||
|
switch(messageIcon){
|
||||||
|
case MessageBoxIcon.Information:
|
||||||
|
icon = SystemIcons.Information;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MessageBoxIcon.Warning:
|
||||||
|
icon = SystemIcons.Warning;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MessageBoxIcon.Error:
|
||||||
|
icon = SystemIcons.Error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MessageBoxIcon.Question:
|
||||||
|
icon = SystemIcons.Question;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
icon = null;
|
||||||
|
labelMessage.Location = new Point(labelMessage.Location.X-38, labelMessage.Location.Y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isReady = true;
|
||||||
|
|
||||||
|
this.Text = caption;
|
||||||
|
this.labelMessage.Text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FormMessage_SizeChanged(object sender, EventArgs e){
|
||||||
|
RecalculateButtonLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Button AddButton(string title, DialogResult result = DialogResult.OK){
|
||||||
|
Button button = new Button{
|
||||||
|
Anchor = AnchorStyles.Bottom,
|
||||||
|
Font = SystemFonts.MessageBoxFont,
|
||||||
|
Location = new Point(0, 12),
|
||||||
|
Size = new Size(88, 26),
|
||||||
|
TabIndex = buttonCount,
|
||||||
|
Text = title,
|
||||||
|
UseVisualStyleBackColor = true
|
||||||
|
};
|
||||||
|
|
||||||
|
button.Click += (sender, args) => {
|
||||||
|
ClickedButton = (Button)sender;
|
||||||
|
DialogResult = result;
|
||||||
|
Close();
|
||||||
|
};
|
||||||
|
|
||||||
|
panelActions.Controls.Add(button);
|
||||||
|
++buttonCount;
|
||||||
|
|
||||||
|
minFormWidth += 96;
|
||||||
|
ClientWidth = Math.Max(realFormWidth, minFormWidth);
|
||||||
|
RecalculateButtonLocation();
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddActionControl(Control control){
|
||||||
|
panelActions.Controls.Add(control);
|
||||||
|
|
||||||
|
minFormWidth += control.Width+control.Margin.Horizontal;
|
||||||
|
ClientWidth = Math.Max(realFormWidth, minFormWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecalculateButtonLocation(){
|
||||||
|
for(int index = 0; index < buttonCount; index++){
|
||||||
|
Control control = panelActions.Controls[index];
|
||||||
|
control.Location = new Point(ClientWidth-97-index*96, control.Location.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void labelMessage_SizeChanged(object sender, EventArgs e){
|
||||||
|
if (!isReady){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMultiline = labelMessage.Height > labelMessage.MinimumSize.Height;
|
||||||
|
|
||||||
|
if (isMultiline && !wasLabelMultiline){
|
||||||
|
labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y-8);
|
||||||
|
prevLabelHeight += 8;
|
||||||
|
}
|
||||||
|
else if (!isMultiline && wasLabelMultiline){
|
||||||
|
labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y+8);
|
||||||
|
prevLabelHeight -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
realFormWidth = ClientWidth-(icon == null ? 50 : 0)+labelMessage.Width-prevLabelWidth;
|
||||||
|
ClientWidth = Math.Max(realFormWidth, minFormWidth);
|
||||||
|
Height += labelMessage.Height-prevLabelHeight;
|
||||||
|
|
||||||
|
prevLabelWidth = labelMessage.Width;
|
||||||
|
prevLabelHeight = labelMessage.Height;
|
||||||
|
wasLabelMultiline = isMultiline;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e){
|
||||||
|
if (icon != null){
|
||||||
|
e.Graphics.DrawIcon(icon, 25, 26);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnPaint(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
106
Core/Other/FormPlugins.Designer.cs
generated
Normal file
106
Core/Other/FormPlugins.Designer.cs
generated
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
namespace TweetDck.Core.Other {
|
||||||
|
partial class FormPlugins {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.btnClose = new System.Windows.Forms.Button();
|
||||||
|
this.btnReload = new System.Windows.Forms.Button();
|
||||||
|
this.btnOpenFolder = new System.Windows.Forms.Button();
|
||||||
|
this.tabPanelPlugins = new TweetDck.Core.Controls.TabPanel();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// btnClose
|
||||||
|
//
|
||||||
|
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnClose.AutoSize = true;
|
||||||
|
this.btnClose.Location = new System.Drawing.Point(643, 439);
|
||||||
|
this.btnClose.Name = "btnClose";
|
||||||
|
this.btnClose.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnClose.Size = new System.Drawing.Size(49, 23);
|
||||||
|
this.btnClose.TabIndex = 1;
|
||||||
|
this.btnClose.Text = "Close";
|
||||||
|
this.btnClose.UseVisualStyleBackColor = true;
|
||||||
|
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
|
||||||
|
//
|
||||||
|
// btnReload
|
||||||
|
//
|
||||||
|
this.btnReload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.btnReload.AutoSize = true;
|
||||||
|
this.btnReload.Location = new System.Drawing.Point(131, 439);
|
||||||
|
this.btnReload.Name = "btnReload";
|
||||||
|
this.btnReload.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnReload.Size = new System.Drawing.Size(71, 23);
|
||||||
|
this.btnReload.TabIndex = 2;
|
||||||
|
this.btnReload.Text = "Reload All";
|
||||||
|
this.btnReload.UseVisualStyleBackColor = true;
|
||||||
|
this.btnReload.Click += new System.EventHandler(this.btnReload_Click);
|
||||||
|
//
|
||||||
|
// btnOpenFolder
|
||||||
|
//
|
||||||
|
this.btnOpenFolder.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.btnOpenFolder.AutoSize = true;
|
||||||
|
this.btnOpenFolder.Location = new System.Drawing.Point(12, 439);
|
||||||
|
this.btnOpenFolder.Name = "btnOpenFolder";
|
||||||
|
this.btnOpenFolder.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnOpenFolder.Size = new System.Drawing.Size(113, 23);
|
||||||
|
this.btnOpenFolder.TabIndex = 3;
|
||||||
|
this.btnOpenFolder.Text = "Open Plugin Folder";
|
||||||
|
this.btnOpenFolder.UseVisualStyleBackColor = true;
|
||||||
|
this.btnOpenFolder.Click += new System.EventHandler(this.btnOpenFolder_Click);
|
||||||
|
//
|
||||||
|
// tabPanelPlugins
|
||||||
|
//
|
||||||
|
this.tabPanelPlugins.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.tabPanelPlugins.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.tabPanelPlugins.Name = "tabPanelPlugins";
|
||||||
|
this.tabPanelPlugins.Size = new System.Drawing.Size(680, 421);
|
||||||
|
this.tabPanelPlugins.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// FormPlugins
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(704, 474);
|
||||||
|
this.Controls.Add(this.tabPanelPlugins);
|
||||||
|
this.Controls.Add(this.btnOpenFolder);
|
||||||
|
this.Controls.Add(this.btnReload);
|
||||||
|
this.Controls.Add(this.btnClose);
|
||||||
|
this.Icon = global::TweetDck.Properties.Resources.icon;
|
||||||
|
this.MinimumSize = new System.Drawing.Size(480, 320);
|
||||||
|
this.Name = "FormPlugins";
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Button btnClose;
|
||||||
|
private System.Windows.Forms.Button btnReload;
|
||||||
|
private System.Windows.Forms.Button btnOpenFolder;
|
||||||
|
private TweetDck.Core.Controls.TabPanel tabPanelPlugins;
|
||||||
|
}
|
||||||
|
}
|
||||||
124
Core/Other/FormPlugins.cs
Normal file
124
Core/Other/FormPlugins.cs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Plugins;
|
||||||
|
using TweetDck.Plugins.Controls;
|
||||||
|
using TweetDck.Plugins.Enums;
|
||||||
|
using TweetDck.Plugins.Events;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other{
|
||||||
|
sealed partial class FormPlugins : Form{
|
||||||
|
private readonly PluginManager pluginManager;
|
||||||
|
private readonly TabButton tabBtnOfficial, tabBtnCustom;
|
||||||
|
private readonly PluginListFlowLayout flowLayoutPlugins;
|
||||||
|
|
||||||
|
private PluginGroup? selectedGroup;
|
||||||
|
|
||||||
|
public FormPlugins(){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Text = Program.BrandName+" Plugins";
|
||||||
|
}
|
||||||
|
|
||||||
|
public FormPlugins(PluginManager pluginManager) : this(){
|
||||||
|
this.pluginManager = pluginManager;
|
||||||
|
this.pluginManager.Reloaded += pluginManager_Reloaded;
|
||||||
|
|
||||||
|
this.flowLayoutPlugins = new PluginListFlowLayout();
|
||||||
|
this.flowLayoutPlugins.Resize += flowLayoutPlugins_Resize;
|
||||||
|
|
||||||
|
this.tabPanelPlugins.SetupTabPanel(90);
|
||||||
|
this.tabPanelPlugins.ReplaceContent(flowLayoutPlugins);
|
||||||
|
|
||||||
|
this.tabBtnOfficial = tabPanelPlugins.AddButton("", () => SelectGroup(PluginGroup.Official));
|
||||||
|
this.tabBtnCustom = tabPanelPlugins.AddButton("", () => SelectGroup(PluginGroup.Custom));
|
||||||
|
|
||||||
|
this.pluginManager_Reloaded(pluginManager, null);
|
||||||
|
|
||||||
|
Shown += (sender, args) => {
|
||||||
|
Program.UserConfig.PluginsWindow.Restore(this, false);
|
||||||
|
this.tabPanelPlugins.SelectTab(tabBtnOfficial);
|
||||||
|
};
|
||||||
|
|
||||||
|
FormClosed += (sender, args) => {
|
||||||
|
Program.UserConfig.PluginsWindow.Save(this);
|
||||||
|
Program.UserConfig.Save();
|
||||||
|
};
|
||||||
|
|
||||||
|
Disposed += (sender, args) => this.pluginManager.Reloaded -= pluginManager_Reloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectGroup(PluginGroup group){
|
||||||
|
if (selectedGroup.HasValue && selectedGroup == group)return;
|
||||||
|
|
||||||
|
selectedGroup = group;
|
||||||
|
|
||||||
|
ReloadPluginTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReloadPluginTab(){
|
||||||
|
if (!selectedGroup.HasValue)return;
|
||||||
|
|
||||||
|
flowLayoutPlugins.SuspendLayout();
|
||||||
|
flowLayoutPlugins.Controls.Clear();
|
||||||
|
|
||||||
|
Plugin[] plugins = pluginManager.GetPluginsByGroup(selectedGroup.Value).OrderBy(plugin => !plugin.CanRun ? 0 : pluginManager.Config.IsEnabled(plugin) ? 1 : 2).ThenBy(plugin => plugin.Name).ToArray();
|
||||||
|
|
||||||
|
for(int index = 0; index < plugins.Length; index++){
|
||||||
|
flowLayoutPlugins.Controls.Add(new PluginControl(pluginManager, plugins[index]));
|
||||||
|
|
||||||
|
if (index < plugins.Length-1){
|
||||||
|
flowLayoutPlugins.Controls.Add(new Panel{
|
||||||
|
BackColor = Color.DimGray,
|
||||||
|
Size = new Size(1, 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flowLayoutPlugins.ResumeLayout(true);
|
||||||
|
flowLayoutPlugins_Resize(flowLayoutPlugins, new EventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pluginManager_Reloaded(object sender, PluginErrorEventArgs e){
|
||||||
|
tabBtnOfficial.Text = "Official: "+pluginManager.CountPluginByGroup(PluginGroup.Official);
|
||||||
|
tabBtnCustom.Text = "Custom: "+pluginManager.CountPluginByGroup(PluginGroup.Custom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flowLayoutPlugins_Resize(object sender, EventArgs e){
|
||||||
|
if (flowLayoutPlugins.Controls.Count == 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Control lastControl = flowLayoutPlugins.Controls[flowLayoutPlugins.Controls.Count-1];
|
||||||
|
bool showScrollBar = lastControl.Location.Y+lastControl.Height >= flowLayoutPlugins.Height;
|
||||||
|
int horizontalOffset = showScrollBar ? SystemInformation.VerticalScrollBarWidth : 0;
|
||||||
|
|
||||||
|
flowLayoutPlugins.AutoScroll = showScrollBar;
|
||||||
|
flowLayoutPlugins.VerticalScroll.Visible = showScrollBar;
|
||||||
|
|
||||||
|
foreach(Control control in flowLayoutPlugins.Controls){
|
||||||
|
control.Width = flowLayoutPlugins.Width-control.Margin.Horizontal-horizontalOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
flowLayoutPlugins.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnOpenFolder_Click(object sender, EventArgs e){
|
||||||
|
using(Process.Start("explorer.exe", "\""+pluginManager.PathCustomPlugins+"\"")){}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnReload_Click(object sender, EventArgs e){
|
||||||
|
if (MessageBox.Show("This will also reload the browser window. Do you want to proceed?", "Reloading Plugins", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
|
||||||
|
pluginManager.Reload();
|
||||||
|
ReloadPluginTab();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnClose_Click(object sender, EventArgs e){
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Core/Other/FormPlugins.resx
Normal file
120
Core/Other/FormPlugins.resx
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
391
Core/Other/FormSettings.Designer.cs
generated
391
Core/Other/FormSettings.Designer.cs
generated
@@ -23,377 +23,68 @@
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.groupNotificationLocation = new System.Windows.Forms.GroupBox();
|
this.btnClose = new System.Windows.Forms.Button();
|
||||||
this.labelDisplay = new System.Windows.Forms.Label();
|
this.labelTip = new System.Windows.Forms.Label();
|
||||||
this.comboBoxDisplay = new System.Windows.Forms.ComboBox();
|
this.tabPanel = new TweetDck.Core.Controls.TabPanel();
|
||||||
this.labelEdgeDistance = new System.Windows.Forms.Label();
|
|
||||||
this.trackBarEdgeDistance = new System.Windows.Forms.TrackBar();
|
|
||||||
this.radioLocCustom = new System.Windows.Forms.RadioButton();
|
|
||||||
this.radioLocBR = new System.Windows.Forms.RadioButton();
|
|
||||||
this.radioLocBL = new System.Windows.Forms.RadioButton();
|
|
||||||
this.radioLocTR = new System.Windows.Forms.RadioButton();
|
|
||||||
this.radioLocTL = new System.Windows.Forms.RadioButton();
|
|
||||||
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
|
|
||||||
this.tableColumn2Panel = new System.Windows.Forms.Panel();
|
|
||||||
this.groupUserInterface = new System.Windows.Forms.GroupBox();
|
|
||||||
this.comboBoxTrayType = new System.Windows.Forms.ComboBox();
|
|
||||||
this.labelTrayType = new System.Windows.Forms.Label();
|
|
||||||
this.checkUpdateNotifications = new System.Windows.Forms.CheckBox();
|
|
||||||
this.checkNotificationTimer = new System.Windows.Forms.CheckBox();
|
|
||||||
this.groupNotificationDuration = new System.Windows.Forms.GroupBox();
|
|
||||||
this.radioDurVeryLong = new System.Windows.Forms.RadioButton();
|
|
||||||
this.radioDurLong = new System.Windows.Forms.RadioButton();
|
|
||||||
this.radioDurMedium = new System.Windows.Forms.RadioButton();
|
|
||||||
this.radioDurShort = new System.Windows.Forms.RadioButton();
|
|
||||||
this.groupNotificationLocation.SuspendLayout();
|
|
||||||
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).BeginInit();
|
|
||||||
this.tableLayout.SuspendLayout();
|
|
||||||
this.tableColumn2Panel.SuspendLayout();
|
|
||||||
this.groupUserInterface.SuspendLayout();
|
|
||||||
this.groupNotificationDuration.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// groupNotificationLocation
|
// btnClose
|
||||||
//
|
//
|
||||||
this.groupNotificationLocation.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnClose.AutoSize = true;
|
||||||
|
this.btnClose.Location = new System.Drawing.Point(443, 349);
|
||||||
|
this.btnClose.Name = "btnClose";
|
||||||
|
this.btnClose.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnClose.Size = new System.Drawing.Size(49, 23);
|
||||||
|
this.btnClose.TabIndex = 4;
|
||||||
|
this.btnClose.Text = "Close";
|
||||||
|
this.btnClose.UseVisualStyleBackColor = true;
|
||||||
|
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
|
||||||
|
//
|
||||||
|
// labelTip
|
||||||
|
//
|
||||||
|
this.labelTip.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.labelTip.AutoSize = true;
|
||||||
|
this.labelTip.Location = new System.Drawing.Point(12, 351);
|
||||||
|
this.labelTip.Name = "labelTip";
|
||||||
|
this.labelTip.Size = new System.Drawing.Size(310, 13);
|
||||||
|
this.labelTip.TabIndex = 5;
|
||||||
|
this.labelTip.Text = "Tip: Move your cursor over an option to see detailed explanation";
|
||||||
|
//
|
||||||
|
// tabPanel
|
||||||
|
//
|
||||||
|
this.tabPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.groupNotificationLocation.Controls.Add(this.labelDisplay);
|
this.tabPanel.Location = new System.Drawing.Point(12, 12);
|
||||||
this.groupNotificationLocation.Controls.Add(this.comboBoxDisplay);
|
this.tabPanel.Name = "tabPanel";
|
||||||
this.groupNotificationLocation.Controls.Add(this.labelEdgeDistance);
|
this.tabPanel.Size = new System.Drawing.Size(480, 331);
|
||||||
this.groupNotificationLocation.Controls.Add(this.trackBarEdgeDistance);
|
this.tabPanel.TabIndex = 3;
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocCustom);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocBR);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocBL);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocTR);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocTL);
|
|
||||||
this.groupNotificationLocation.Location = new System.Drawing.Point(6, 6);
|
|
||||||
this.groupNotificationLocation.Name = "groupNotificationLocation";
|
|
||||||
this.groupNotificationLocation.Size = new System.Drawing.Size(183, 270);
|
|
||||||
this.groupNotificationLocation.TabIndex = 0;
|
|
||||||
this.groupNotificationLocation.TabStop = false;
|
|
||||||
this.groupNotificationLocation.Text = "Notification Location";
|
|
||||||
//
|
|
||||||
// labelDisplay
|
|
||||||
//
|
|
||||||
this.labelDisplay.AutoSize = true;
|
|
||||||
this.labelDisplay.Location = new System.Drawing.Point(6, 148);
|
|
||||||
this.labelDisplay.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
|
||||||
this.labelDisplay.Name = "labelDisplay";
|
|
||||||
this.labelDisplay.Size = new System.Drawing.Size(41, 13);
|
|
||||||
this.labelDisplay.TabIndex = 8;
|
|
||||||
this.labelDisplay.Text = "Display";
|
|
||||||
//
|
|
||||||
// comboBoxDisplay
|
|
||||||
//
|
|
||||||
this.comboBoxDisplay.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.comboBoxDisplay.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
|
||||||
this.comboBoxDisplay.FormattingEnabled = true;
|
|
||||||
this.comboBoxDisplay.Location = new System.Drawing.Point(9, 164);
|
|
||||||
this.comboBoxDisplay.Name = "comboBoxDisplay";
|
|
||||||
this.comboBoxDisplay.Size = new System.Drawing.Size(168, 21);
|
|
||||||
this.comboBoxDisplay.TabIndex = 7;
|
|
||||||
this.comboBoxDisplay.SelectedValueChanged += new System.EventHandler(this.comboBoxDisplay_SelectedValueChanged);
|
|
||||||
//
|
|
||||||
// labelEdgeDistance
|
|
||||||
//
|
|
||||||
this.labelEdgeDistance.AutoSize = true;
|
|
||||||
this.labelEdgeDistance.Location = new System.Drawing.Point(6, 197);
|
|
||||||
this.labelEdgeDistance.Margin = new System.Windows.Forms.Padding(3, 9, 3, 0);
|
|
||||||
this.labelEdgeDistance.Name = "labelEdgeDistance";
|
|
||||||
this.labelEdgeDistance.Size = new System.Drawing.Size(103, 13);
|
|
||||||
this.labelEdgeDistance.TabIndex = 6;
|
|
||||||
this.labelEdgeDistance.Text = "Distance From Edge";
|
|
||||||
//
|
|
||||||
// trackBarEdgeDistance
|
|
||||||
//
|
|
||||||
this.trackBarEdgeDistance.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.trackBarEdgeDistance.LargeChange = 8;
|
|
||||||
this.trackBarEdgeDistance.Location = new System.Drawing.Point(6, 213);
|
|
||||||
this.trackBarEdgeDistance.Maximum = 40;
|
|
||||||
this.trackBarEdgeDistance.Minimum = 8;
|
|
||||||
this.trackBarEdgeDistance.Name = "trackBarEdgeDistance";
|
|
||||||
this.trackBarEdgeDistance.Size = new System.Drawing.Size(171, 45);
|
|
||||||
this.trackBarEdgeDistance.SmallChange = 2;
|
|
||||||
this.trackBarEdgeDistance.TabIndex = 5;
|
|
||||||
this.trackBarEdgeDistance.TickFrequency = 2;
|
|
||||||
this.trackBarEdgeDistance.Value = 8;
|
|
||||||
this.trackBarEdgeDistance.ValueChanged += new System.EventHandler(this.trackBarEdgeDistance_ValueChanged);
|
|
||||||
//
|
|
||||||
// radioLocCustom
|
|
||||||
//
|
|
||||||
this.radioLocCustom.AutoSize = true;
|
|
||||||
this.radioLocCustom.Location = new System.Drawing.Point(7, 116);
|
|
||||||
this.radioLocCustom.Name = "radioLocCustom";
|
|
||||||
this.radioLocCustom.Size = new System.Drawing.Size(60, 17);
|
|
||||||
this.radioLocCustom.TabIndex = 4;
|
|
||||||
this.radioLocCustom.TabStop = true;
|
|
||||||
this.radioLocCustom.Text = "Custom";
|
|
||||||
this.radioLocCustom.UseVisualStyleBackColor = true;
|
|
||||||
this.radioLocCustom.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
this.radioLocCustom.Click += new System.EventHandler(this.radioLoc_Click);
|
|
||||||
//
|
|
||||||
// radioLocBR
|
|
||||||
//
|
|
||||||
this.radioLocBR.AutoSize = true;
|
|
||||||
this.radioLocBR.Location = new System.Drawing.Point(7, 92);
|
|
||||||
this.radioLocBR.Name = "radioLocBR";
|
|
||||||
this.radioLocBR.Size = new System.Drawing.Size(86, 17);
|
|
||||||
this.radioLocBR.TabIndex = 3;
|
|
||||||
this.radioLocBR.TabStop = true;
|
|
||||||
this.radioLocBR.Text = "Bottom Right";
|
|
||||||
this.radioLocBR.UseVisualStyleBackColor = true;
|
|
||||||
this.radioLocBR.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
this.radioLocBR.Click += new System.EventHandler(this.radioLoc_Click);
|
|
||||||
//
|
|
||||||
// radioLocBL
|
|
||||||
//
|
|
||||||
this.radioLocBL.AutoSize = true;
|
|
||||||
this.radioLocBL.Location = new System.Drawing.Point(7, 68);
|
|
||||||
this.radioLocBL.Name = "radioLocBL";
|
|
||||||
this.radioLocBL.Size = new System.Drawing.Size(79, 17);
|
|
||||||
this.radioLocBL.TabIndex = 2;
|
|
||||||
this.radioLocBL.TabStop = true;
|
|
||||||
this.radioLocBL.Text = "Bottom Left";
|
|
||||||
this.radioLocBL.UseVisualStyleBackColor = true;
|
|
||||||
this.radioLocBL.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
this.radioLocBL.Click += new System.EventHandler(this.radioLoc_Click);
|
|
||||||
//
|
|
||||||
// radioLocTR
|
|
||||||
//
|
|
||||||
this.radioLocTR.AutoSize = true;
|
|
||||||
this.radioLocTR.Location = new System.Drawing.Point(7, 44);
|
|
||||||
this.radioLocTR.Name = "radioLocTR";
|
|
||||||
this.radioLocTR.Size = new System.Drawing.Size(72, 17);
|
|
||||||
this.radioLocTR.TabIndex = 1;
|
|
||||||
this.radioLocTR.TabStop = true;
|
|
||||||
this.radioLocTR.Text = "Top Right";
|
|
||||||
this.radioLocTR.UseVisualStyleBackColor = true;
|
|
||||||
this.radioLocTR.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
this.radioLocTR.Click += new System.EventHandler(this.radioLoc_Click);
|
|
||||||
//
|
|
||||||
// radioLocTL
|
|
||||||
//
|
|
||||||
this.radioLocTL.AutoSize = true;
|
|
||||||
this.radioLocTL.Location = new System.Drawing.Point(7, 20);
|
|
||||||
this.radioLocTL.Name = "radioLocTL";
|
|
||||||
this.radioLocTL.Size = new System.Drawing.Size(65, 17);
|
|
||||||
this.radioLocTL.TabIndex = 0;
|
|
||||||
this.radioLocTL.TabStop = true;
|
|
||||||
this.radioLocTL.Text = "Top Left";
|
|
||||||
this.radioLocTL.UseVisualStyleBackColor = true;
|
|
||||||
this.radioLocTL.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
this.radioLocTL.Click += new System.EventHandler(this.radioLoc_Click);
|
|
||||||
//
|
|
||||||
// tableLayout
|
|
||||||
//
|
|
||||||
this.tableLayout.ColumnCount = 2;
|
|
||||||
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
|
||||||
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
|
||||||
this.tableLayout.Controls.Add(this.tableColumn2Panel, 1, 0);
|
|
||||||
this.tableLayout.Controls.Add(this.groupNotificationLocation, 0, 0);
|
|
||||||
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
|
|
||||||
this.tableLayout.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.FixedSize;
|
|
||||||
this.tableLayout.Location = new System.Drawing.Point(0, 0);
|
|
||||||
this.tableLayout.Name = "tableLayout";
|
|
||||||
this.tableLayout.Padding = new System.Windows.Forms.Padding(3);
|
|
||||||
this.tableLayout.RowCount = 1;
|
|
||||||
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
|
||||||
this.tableLayout.Size = new System.Drawing.Size(384, 282);
|
|
||||||
this.tableLayout.TabIndex = 2;
|
|
||||||
//
|
|
||||||
// tableColumn2Panel
|
|
||||||
//
|
|
||||||
this.tableColumn2Panel.Controls.Add(this.groupUserInterface);
|
|
||||||
this.tableColumn2Panel.Controls.Add(this.groupNotificationDuration);
|
|
||||||
this.tableColumn2Panel.Dock = System.Windows.Forms.DockStyle.Fill;
|
|
||||||
this.tableColumn2Panel.Location = new System.Drawing.Point(192, 3);
|
|
||||||
this.tableColumn2Panel.Margin = new System.Windows.Forms.Padding(0);
|
|
||||||
this.tableColumn2Panel.Name = "tableColumn2Panel";
|
|
||||||
this.tableColumn2Panel.Size = new System.Drawing.Size(189, 276);
|
|
||||||
this.tableColumn2Panel.TabIndex = 3;
|
|
||||||
//
|
|
||||||
// groupUserInterface
|
|
||||||
//
|
|
||||||
this.groupUserInterface.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.groupUserInterface.Controls.Add(this.comboBoxTrayType);
|
|
||||||
this.groupUserInterface.Controls.Add(this.labelTrayType);
|
|
||||||
this.groupUserInterface.Controls.Add(this.checkUpdateNotifications);
|
|
||||||
this.groupUserInterface.Controls.Add(this.checkNotificationTimer);
|
|
||||||
this.groupUserInterface.Location = new System.Drawing.Point(3, 128);
|
|
||||||
this.groupUserInterface.Name = "groupUserInterface";
|
|
||||||
this.groupUserInterface.Size = new System.Drawing.Size(183, 145);
|
|
||||||
this.groupUserInterface.TabIndex = 3;
|
|
||||||
this.groupUserInterface.TabStop = false;
|
|
||||||
this.groupUserInterface.Text = "User Interface";
|
|
||||||
//
|
|
||||||
// comboBoxTrayType
|
|
||||||
//
|
|
||||||
this.comboBoxTrayType.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.comboBoxTrayType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
|
||||||
this.comboBoxTrayType.FormattingEnabled = true;
|
|
||||||
this.comboBoxTrayType.Location = new System.Drawing.Point(9, 93);
|
|
||||||
this.comboBoxTrayType.Margin = new System.Windows.Forms.Padding(3, 3, 3, 12);
|
|
||||||
this.comboBoxTrayType.Name = "comboBoxTrayType";
|
|
||||||
this.comboBoxTrayType.Size = new System.Drawing.Size(168, 21);
|
|
||||||
this.comboBoxTrayType.TabIndex = 10;
|
|
||||||
this.comboBoxTrayType.SelectedIndexChanged += new System.EventHandler(this.comboBoxTrayType_SelectedIndexChanged);
|
|
||||||
//
|
|
||||||
// labelTrayType
|
|
||||||
//
|
|
||||||
this.labelTrayType.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
|
||||||
this.labelTrayType.AutoSize = true;
|
|
||||||
this.labelTrayType.Location = new System.Drawing.Point(6, 77);
|
|
||||||
this.labelTrayType.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
|
||||||
this.labelTrayType.Name = "labelTrayType";
|
|
||||||
this.labelTrayType.Size = new System.Drawing.Size(52, 13);
|
|
||||||
this.labelTrayType.TabIndex = 9;
|
|
||||||
this.labelTrayType.Text = "Tray Icon";
|
|
||||||
//
|
|
||||||
// checkUpdateNotifications
|
|
||||||
//
|
|
||||||
this.checkUpdateNotifications.AutoSize = true;
|
|
||||||
this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 45);
|
|
||||||
this.checkUpdateNotifications.Margin = new System.Windows.Forms.Padding(3, 4, 3, 3);
|
|
||||||
this.checkUpdateNotifications.Name = "checkUpdateNotifications";
|
|
||||||
this.checkUpdateNotifications.Size = new System.Drawing.Size(115, 17);
|
|
||||||
this.checkUpdateNotifications.TabIndex = 5;
|
|
||||||
this.checkUpdateNotifications.Text = "Check for Updates";
|
|
||||||
this.checkUpdateNotifications.UseVisualStyleBackColor = true;
|
|
||||||
this.checkUpdateNotifications.CheckedChanged += new System.EventHandler(this.checkUpdateNotifications_CheckedChanged);
|
|
||||||
//
|
|
||||||
// checkNotificationTimer
|
|
||||||
//
|
|
||||||
this.checkNotificationTimer.AutoSize = true;
|
|
||||||
this.checkNotificationTimer.Location = new System.Drawing.Point(6, 21);
|
|
||||||
this.checkNotificationTimer.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
|
|
||||||
this.checkNotificationTimer.Name = "checkNotificationTimer";
|
|
||||||
this.checkNotificationTimer.Size = new System.Drawing.Size(145, 17);
|
|
||||||
this.checkNotificationTimer.TabIndex = 4;
|
|
||||||
this.checkNotificationTimer.Text = "Display Notification Timer";
|
|
||||||
this.checkNotificationTimer.UseVisualStyleBackColor = true;
|
|
||||||
this.checkNotificationTimer.CheckedChanged += new System.EventHandler(this.checkNotificationTimer_CheckedChanged);
|
|
||||||
//
|
|
||||||
// groupNotificationDuration
|
|
||||||
//
|
|
||||||
this.groupNotificationDuration.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.groupNotificationDuration.Controls.Add(this.radioDurVeryLong);
|
|
||||||
this.groupNotificationDuration.Controls.Add(this.radioDurLong);
|
|
||||||
this.groupNotificationDuration.Controls.Add(this.radioDurMedium);
|
|
||||||
this.groupNotificationDuration.Controls.Add(this.radioDurShort);
|
|
||||||
this.groupNotificationDuration.Location = new System.Drawing.Point(3, 3);
|
|
||||||
this.groupNotificationDuration.Name = "groupNotificationDuration";
|
|
||||||
this.groupNotificationDuration.Size = new System.Drawing.Size(183, 119);
|
|
||||||
this.groupNotificationDuration.TabIndex = 2;
|
|
||||||
this.groupNotificationDuration.TabStop = false;
|
|
||||||
this.groupNotificationDuration.Text = "Notification Duration";
|
|
||||||
//
|
|
||||||
// radioDurVeryLong
|
|
||||||
//
|
|
||||||
this.radioDurVeryLong.AutoSize = true;
|
|
||||||
this.radioDurVeryLong.Location = new System.Drawing.Point(6, 92);
|
|
||||||
this.radioDurVeryLong.Name = "radioDurVeryLong";
|
|
||||||
this.radioDurVeryLong.Size = new System.Drawing.Size(73, 17);
|
|
||||||
this.radioDurVeryLong.TabIndex = 3;
|
|
||||||
this.radioDurVeryLong.TabStop = true;
|
|
||||||
this.radioDurVeryLong.Text = "Very Long";
|
|
||||||
this.radioDurVeryLong.UseVisualStyleBackColor = true;
|
|
||||||
this.radioDurVeryLong.CheckedChanged += new System.EventHandler(this.radioDur_CheckedChanged);
|
|
||||||
this.radioDurVeryLong.Click += new System.EventHandler(this.radioDur_Click);
|
|
||||||
//
|
|
||||||
// radioDurLong
|
|
||||||
//
|
|
||||||
this.radioDurLong.AutoSize = true;
|
|
||||||
this.radioDurLong.Location = new System.Drawing.Point(6, 68);
|
|
||||||
this.radioDurLong.Name = "radioDurLong";
|
|
||||||
this.radioDurLong.Size = new System.Drawing.Size(49, 17);
|
|
||||||
this.radioDurLong.TabIndex = 2;
|
|
||||||
this.radioDurLong.TabStop = true;
|
|
||||||
this.radioDurLong.Text = "Long";
|
|
||||||
this.radioDurLong.UseVisualStyleBackColor = true;
|
|
||||||
this.radioDurLong.CheckedChanged += new System.EventHandler(this.radioDur_CheckedChanged);
|
|
||||||
this.radioDurLong.Click += new System.EventHandler(this.radioDur_Click);
|
|
||||||
//
|
|
||||||
// radioDurMedium
|
|
||||||
//
|
|
||||||
this.radioDurMedium.AutoSize = true;
|
|
||||||
this.radioDurMedium.Location = new System.Drawing.Point(6, 44);
|
|
||||||
this.radioDurMedium.Name = "radioDurMedium";
|
|
||||||
this.radioDurMedium.Size = new System.Drawing.Size(62, 17);
|
|
||||||
this.radioDurMedium.TabIndex = 1;
|
|
||||||
this.radioDurMedium.TabStop = true;
|
|
||||||
this.radioDurMedium.Text = "Medium";
|
|
||||||
this.radioDurMedium.UseVisualStyleBackColor = true;
|
|
||||||
this.radioDurMedium.CheckedChanged += new System.EventHandler(this.radioDur_CheckedChanged);
|
|
||||||
this.radioDurMedium.Click += new System.EventHandler(this.radioDur_Click);
|
|
||||||
//
|
|
||||||
// radioDurShort
|
|
||||||
//
|
|
||||||
this.radioDurShort.AutoSize = true;
|
|
||||||
this.radioDurShort.Location = new System.Drawing.Point(6, 20);
|
|
||||||
this.radioDurShort.Name = "radioDurShort";
|
|
||||||
this.radioDurShort.Size = new System.Drawing.Size(50, 17);
|
|
||||||
this.radioDurShort.TabIndex = 0;
|
|
||||||
this.radioDurShort.TabStop = true;
|
|
||||||
this.radioDurShort.Text = "Short";
|
|
||||||
this.radioDurShort.UseVisualStyleBackColor = true;
|
|
||||||
this.radioDurShort.CheckedChanged += new System.EventHandler(this.radioDur_CheckedChanged);
|
|
||||||
this.radioDurShort.Click += new System.EventHandler(this.radioDur_Click);
|
|
||||||
//
|
//
|
||||||
// FormSettings
|
// FormSettings
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(384, 282);
|
this.ClientSize = new System.Drawing.Size(504, 384);
|
||||||
this.Controls.Add(this.tableLayout);
|
this.Controls.Add(this.labelTip);
|
||||||
|
this.Controls.Add(this.btnClose);
|
||||||
|
this.Controls.Add(this.tabPanel);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
this.Icon = ((System.Drawing.Icon)(TweetDck.Properties.Resources.ResourceManager.GetObject("icon")));
|
this.Icon = global::TweetDck.Properties.Resources.icon;
|
||||||
this.MaximizeBox = false;
|
this.MaximizeBox = false;
|
||||||
this.MinimizeBox = false;
|
this.MinimizeBox = false;
|
||||||
this.Name = "FormSettings";
|
this.Name = "FormSettings";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormSettings_FormClosing);
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormSettings_FormClosing);
|
||||||
this.groupNotificationLocation.ResumeLayout(false);
|
|
||||||
this.groupNotificationLocation.PerformLayout();
|
|
||||||
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).EndInit();
|
|
||||||
this.tableLayout.ResumeLayout(false);
|
|
||||||
this.tableColumn2Panel.ResumeLayout(false);
|
|
||||||
this.groupUserInterface.ResumeLayout(false);
|
|
||||||
this.groupUserInterface.PerformLayout();
|
|
||||||
this.groupNotificationDuration.ResumeLayout(false);
|
|
||||||
this.groupNotificationDuration.PerformLayout();
|
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.GroupBox groupNotificationLocation;
|
private Controls.TabPanel tabPanel;
|
||||||
private System.Windows.Forms.RadioButton radioLocCustom;
|
private System.Windows.Forms.Button btnClose;
|
||||||
private System.Windows.Forms.RadioButton radioLocBR;
|
private System.Windows.Forms.Label labelTip;
|
||||||
private System.Windows.Forms.RadioButton radioLocBL;
|
|
||||||
private System.Windows.Forms.RadioButton radioLocTR;
|
|
||||||
private System.Windows.Forms.RadioButton radioLocTL;
|
|
||||||
private System.Windows.Forms.Label labelEdgeDistance;
|
|
||||||
private System.Windows.Forms.TrackBar trackBarEdgeDistance;
|
|
||||||
private System.Windows.Forms.Label labelDisplay;
|
|
||||||
private System.Windows.Forms.ComboBox comboBoxDisplay;
|
|
||||||
private System.Windows.Forms.TableLayoutPanel tableLayout;
|
|
||||||
private System.Windows.Forms.Panel tableColumn2Panel;
|
|
||||||
private System.Windows.Forms.GroupBox groupUserInterface;
|
|
||||||
private System.Windows.Forms.GroupBox groupNotificationDuration;
|
|
||||||
private System.Windows.Forms.RadioButton radioDurVeryLong;
|
|
||||||
private System.Windows.Forms.RadioButton radioDurLong;
|
|
||||||
private System.Windows.Forms.RadioButton radioDurMedium;
|
|
||||||
private System.Windows.Forms.RadioButton radioDurShort;
|
|
||||||
private System.Windows.Forms.CheckBox checkNotificationTimer;
|
|
||||||
private System.Windows.Forms.CheckBox checkUpdateNotifications;
|
|
||||||
private System.Windows.Forms.ComboBox comboBoxTrayType;
|
|
||||||
private System.Windows.Forms.Label labelTrayType;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,146 +1,68 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Configuration;
|
using TweetDck.Core.Other.Settings;
|
||||||
using TweetDck.Core.Handling;
|
using TweetDck.Plugins;
|
||||||
|
using TweetDck.Updates;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other{
|
namespace TweetDck.Core.Other{
|
||||||
sealed partial class FormSettings : Form{
|
sealed partial class FormSettings : Form{
|
||||||
private static UserConfig Config{
|
public const int TabIndexNotification = 1;
|
||||||
get{
|
|
||||||
return Program.UserConfig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly FormNotification notification;
|
private readonly FormBrowser browser;
|
||||||
private bool isLoaded;
|
private readonly Dictionary<Type, BaseTabSettings> tabs = new Dictionary<Type, BaseTabSettings>(4);
|
||||||
|
|
||||||
public FormSettings(FormBrowser browserForm){
|
public FormSettings(FormBrowser browser, PluginManager plugins, UpdateHandler updates, int startTabIndex = 0){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Shown += (sender, args) => isLoaded = true;
|
|
||||||
|
|
||||||
Text = Program.BrandName+" Settings";
|
Text = Program.BrandName+" Settings";
|
||||||
|
|
||||||
notification = new FormNotification(browserForm,false){ CanMoveWindow = () => radioLocCustom.Checked };
|
this.browser = browser;
|
||||||
|
this.browser.PauseNotification();
|
||||||
|
|
||||||
notification.Move += (sender, args) => {
|
this.tabPanel.SetupTabPanel(100);
|
||||||
if (radioLocCustom.Checked){
|
this.tabPanel.AddButton("General", () => SelectTab(() => new TabSettingsGeneral(updates)));
|
||||||
Config.CustomNotificationPosition = notification.Location;
|
this.tabPanel.AddButton("Notifications", () => SelectTab(() => new TabSettingsNotifications(browser.CreateNotificationForm(false))));
|
||||||
}
|
this.tabPanel.AddButton("Sounds", () => SelectTab(() => new TabSettingsSounds()));
|
||||||
};
|
this.tabPanel.AddButton("Advanced", () => SelectTab(() => new TabSettingsAdvanced(browser.ReinjectCustomCSS, plugins)));
|
||||||
|
|
||||||
notification.Show(this);
|
this.tabPanel.SelectTab(tabPanel.Buttons.ElementAt(startTabIndex));
|
||||||
|
|
||||||
switch(Config.NotificationPosition){
|
|
||||||
case TweetNotification.Position.TopLeft: radioLocTL.Checked = true; break;
|
|
||||||
case TweetNotification.Position.TopRight: radioLocTR.Checked = true; break;
|
|
||||||
case TweetNotification.Position.BottomLeft: radioLocBL.Checked = true; break;
|
|
||||||
case TweetNotification.Position.BottomRight: radioLocBR.Checked = true; break;
|
|
||||||
case TweetNotification.Position.Custom: radioLocCustom.Checked = true; break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(Config.NotificationDuration){
|
private void SelectTab<T>(Func<T> constructor) where T : BaseTabSettings{
|
||||||
case TweetNotification.Duration.Short: radioDurShort.Checked = true; break;
|
if (tabs.TryGetValue(typeof(T), out BaseTabSettings control)){
|
||||||
case TweetNotification.Duration.Medium: radioDurMedium.Checked = true; break;
|
tabPanel.ReplaceContent(control);
|
||||||
case TweetNotification.Duration.Long: radioDurLong.Checked = true; break;
|
|
||||||
case TweetNotification.Duration.VeryLong: radioDurVeryLong.Checked = true; break;
|
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
comboBoxDisplay.Items.Add("(Same As "+Program.BrandName+")");
|
control = tabs[typeof(T)] = constructor();
|
||||||
|
control.OnReady();
|
||||||
foreach(Screen screen in Screen.AllScreens){
|
tabPanel.ReplaceContent(control);
|
||||||
comboBoxDisplay.Items.Add(screen.DeviceName+" ("+screen.Bounds.Width+"x"+screen.Bounds.Height+")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
comboBoxDisplay.SelectedIndex = Math.Min(comboBoxDisplay.Items.Count-1,Config.NotificationDisplay);
|
|
||||||
|
|
||||||
comboBoxTrayType.Items.Add("Disabled");
|
|
||||||
comboBoxTrayType.Items.Add("Display Icon Only");
|
|
||||||
comboBoxTrayType.Items.Add("Minimize to Tray");
|
|
||||||
comboBoxTrayType.Items.Add("Close to Tray");
|
|
||||||
comboBoxTrayType.SelectedIndex = Math.Min(Math.Max((int)Config.TrayBehavior,0),comboBoxTrayType.Items.Count-1);
|
|
||||||
|
|
||||||
trackBarEdgeDistance.Value = Config.NotificationEdgeDistance;
|
|
||||||
checkNotificationTimer.Checked = Config.DisplayNotificationTimer;
|
|
||||||
checkUpdateNotifications.Checked = Config.EnableUpdateCheck;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FormSettings_FormClosing(object sender, FormClosingEventArgs e){
|
private void FormSettings_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
Config.Save();
|
foreach(BaseTabSettings control in tabs.Values){
|
||||||
|
control.OnClosing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void radioLoc_CheckedChanged(object sender, EventArgs e){
|
Program.UserConfig.Save();
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
if (radioLocTL.Checked)Config.NotificationPosition = TweetNotification.Position.TopLeft;
|
foreach(BaseTabSettings control in tabs.Values){
|
||||||
else if (radioLocTR.Checked)Config.NotificationPosition = TweetNotification.Position.TopRight;
|
control.Dispose();
|
||||||
else if (radioLocBL.Checked)Config.NotificationPosition = TweetNotification.Position.BottomLeft;
|
|
||||||
else if (radioLocBR.Checked)Config.NotificationPosition = TweetNotification.Position.BottomRight;
|
|
||||||
else if (radioLocCustom.Checked){
|
|
||||||
if (!Config.IsCustomNotificationPositionSet){
|
|
||||||
Config.CustomNotificationPosition = notification.Location;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Config.NotificationPosition = TweetNotification.Position.Custom;
|
browser.ResumeNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = !radioLocCustom.Checked;
|
private void btnClose_Click(object sender, EventArgs e){
|
||||||
notification.ShowNotificationForSettings(false);
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void radioLoc_Click(object sender, EventArgs e){
|
public void ReloadUI(){
|
||||||
if (!isLoaded)return;
|
tabs.Clear();
|
||||||
|
tabPanel.Content.Controls.Clear();
|
||||||
notification.ShowNotificationForSettings(false);
|
tabPanel.ActiveButton.Callback();
|
||||||
}
|
|
||||||
|
|
||||||
private void comboBoxDisplay_SelectedValueChanged(object sender, EventArgs e){
|
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
Config.NotificationDisplay = comboBoxDisplay.SelectedIndex;
|
|
||||||
notification.ShowNotificationForSettings(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void trackBarEdgeDistance_ValueChanged(object sender, EventArgs e){
|
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
Config.NotificationEdgeDistance = trackBarEdgeDistance.Value;
|
|
||||||
notification.ShowNotificationForSettings(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void radioDur_CheckedChanged(object sender, EventArgs e){
|
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
if (radioDurShort.Checked)Config.NotificationDuration = TweetNotification.Duration.Short;
|
|
||||||
else if (radioDurMedium.Checked)Config.NotificationDuration = TweetNotification.Duration.Medium;
|
|
||||||
else if (radioDurLong.Checked)Config.NotificationDuration = TweetNotification.Duration.Long;
|
|
||||||
else if (radioDurVeryLong.Checked)Config.NotificationDuration = TweetNotification.Duration.VeryLong;
|
|
||||||
|
|
||||||
notification.ShowNotificationForSettings(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void radioDur_Click(object sender, EventArgs e){
|
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
notification.ShowNotificationForSettings(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void comboBoxTrayType_SelectedIndexChanged(object sender, EventArgs e){
|
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
Config.TrayBehavior = (TrayIcon.Behavior)comboBoxTrayType.SelectedIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkNotificationTimer_CheckedChanged(object sender, EventArgs e){
|
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
Config.DisplayNotificationTimer = checkNotificationTimer.Checked;
|
|
||||||
notification.ShowNotificationForSettings(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkUpdateNotifications_CheckedChanged(object sender, EventArgs e){
|
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
Config.EnableUpdateCheck = checkUpdateNotifications.Checked;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
120
Core/Other/FormSettings.resx
Normal file
120
Core/Other/FormSettings.resx
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
21
Core/Other/Settings/BaseTabSettings.cs
Normal file
21
Core/Other/Settings/BaseTabSettings.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Configuration;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings{
|
||||||
|
class BaseTabSettings : UserControl{
|
||||||
|
protected static UserConfig Config => Program.UserConfig;
|
||||||
|
|
||||||
|
public BaseTabSettings(){
|
||||||
|
Padding = new Padding(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnReady(){}
|
||||||
|
public virtual void OnClosing(){}
|
||||||
|
|
||||||
|
protected static void PromptRestart(){
|
||||||
|
if (MessageBox.Show("The application must restart for the setting to take place. Do you want to restart now?", Program.BrandName+" Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes){
|
||||||
|
Program.Restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
208
Core/Other/Settings/Dialogs/DialogSettingsCSS.Designer.cs
generated
Normal file
208
Core/Other/Settings/Dialogs/DialogSettingsCSS.Designer.cs
generated
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
namespace TweetDck.Core.Other.Settings.Dialogs {
|
||||||
|
partial class DialogSettingsCSS {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.textBoxBrowserCSS = new System.Windows.Forms.TextBox();
|
||||||
|
this.btnCancel = new System.Windows.Forms.Button();
|
||||||
|
this.btnApply = new System.Windows.Forms.Button();
|
||||||
|
this.splitContainer = new System.Windows.Forms.SplitContainer();
|
||||||
|
this.labelBrowser = new System.Windows.Forms.Label();
|
||||||
|
this.labelNotification = new System.Windows.Forms.Label();
|
||||||
|
this.textBoxNotificationCSS = new System.Windows.Forms.TextBox();
|
||||||
|
this.labelWarning = new System.Windows.Forms.Label();
|
||||||
|
this.btnOpenWiki = new System.Windows.Forms.Button();
|
||||||
|
this.timerTestBrowser = new System.Windows.Forms.Timer(this.components);
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
|
||||||
|
this.splitContainer.Panel1.SuspendLayout();
|
||||||
|
this.splitContainer.Panel2.SuspendLayout();
|
||||||
|
this.splitContainer.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// textBoxBrowserCSS
|
||||||
|
//
|
||||||
|
this.textBoxBrowserCSS.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.textBoxBrowserCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.textBoxBrowserCSS.Location = new System.Drawing.Point(0, 16);
|
||||||
|
this.textBoxBrowserCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
||||||
|
this.textBoxBrowserCSS.Multiline = true;
|
||||||
|
this.textBoxBrowserCSS.Name = "textBoxBrowserCSS";
|
||||||
|
this.textBoxBrowserCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
|
this.textBoxBrowserCSS.Size = new System.Drawing.Size(373, 253);
|
||||||
|
this.textBoxBrowserCSS.TabIndex = 1;
|
||||||
|
this.textBoxBrowserCSS.WordWrap = false;
|
||||||
|
this.textBoxBrowserCSS.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBoxBrowserCSS_KeyUp);
|
||||||
|
//
|
||||||
|
// btnCancel
|
||||||
|
//
|
||||||
|
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnCancel.Location = new System.Drawing.Point(654, 287);
|
||||||
|
this.btnCancel.Name = "btnCancel";
|
||||||
|
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
||||||
|
this.btnCancel.TabIndex = 2;
|
||||||
|
this.btnCancel.Text = "Cancel";
|
||||||
|
this.btnCancel.UseVisualStyleBackColor = true;
|
||||||
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||||
|
//
|
||||||
|
// btnApply
|
||||||
|
//
|
||||||
|
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnApply.Location = new System.Drawing.Point(716, 287);
|
||||||
|
this.btnApply.Name = "btnApply";
|
||||||
|
this.btnApply.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnApply.Size = new System.Drawing.Size(56, 23);
|
||||||
|
this.btnApply.TabIndex = 1;
|
||||||
|
this.btnApply.Text = "Apply";
|
||||||
|
this.btnApply.UseVisualStyleBackColor = true;
|
||||||
|
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
|
||||||
|
//
|
||||||
|
// splitContainer
|
||||||
|
//
|
||||||
|
this.splitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.splitContainer.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.splitContainer.Name = "splitContainer";
|
||||||
|
//
|
||||||
|
// splitContainer.Panel1
|
||||||
|
//
|
||||||
|
this.splitContainer.Panel1.Controls.Add(this.labelBrowser);
|
||||||
|
this.splitContainer.Panel1.Controls.Add(this.textBoxBrowserCSS);
|
||||||
|
this.splitContainer.Panel1MinSize = 64;
|
||||||
|
//
|
||||||
|
// splitContainer.Panel2
|
||||||
|
//
|
||||||
|
this.splitContainer.Panel2.Controls.Add(this.labelNotification);
|
||||||
|
this.splitContainer.Panel2.Controls.Add(this.textBoxNotificationCSS);
|
||||||
|
this.splitContainer.Panel2MinSize = 64;
|
||||||
|
this.splitContainer.Size = new System.Drawing.Size(760, 269);
|
||||||
|
this.splitContainer.SplitterDistance = 373;
|
||||||
|
this.splitContainer.SplitterWidth = 5;
|
||||||
|
this.splitContainer.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// labelBrowser
|
||||||
|
//
|
||||||
|
this.labelBrowser.AutoSize = true;
|
||||||
|
this.labelBrowser.Location = new System.Drawing.Point(-3, 0);
|
||||||
|
this.labelBrowser.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
|
this.labelBrowser.Name = "labelBrowser";
|
||||||
|
this.labelBrowser.Size = new System.Drawing.Size(45, 13);
|
||||||
|
this.labelBrowser.TabIndex = 0;
|
||||||
|
this.labelBrowser.Text = "Browser";
|
||||||
|
//
|
||||||
|
// labelNotification
|
||||||
|
//
|
||||||
|
this.labelNotification.AutoSize = true;
|
||||||
|
this.labelNotification.Location = new System.Drawing.Point(-3, 0);
|
||||||
|
this.labelNotification.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
|
this.labelNotification.Name = "labelNotification";
|
||||||
|
this.labelNotification.Size = new System.Drawing.Size(60, 13);
|
||||||
|
this.labelNotification.TabIndex = 0;
|
||||||
|
this.labelNotification.Text = "Notification";
|
||||||
|
//
|
||||||
|
// textBoxNotificationCSS
|
||||||
|
//
|
||||||
|
this.textBoxNotificationCSS.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.textBoxNotificationCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.textBoxNotificationCSS.Location = new System.Drawing.Point(0, 16);
|
||||||
|
this.textBoxNotificationCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
||||||
|
this.textBoxNotificationCSS.Multiline = true;
|
||||||
|
this.textBoxNotificationCSS.Name = "textBoxNotificationCSS";
|
||||||
|
this.textBoxNotificationCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
|
this.textBoxNotificationCSS.Size = new System.Drawing.Size(372, 253);
|
||||||
|
this.textBoxNotificationCSS.TabIndex = 1;
|
||||||
|
this.textBoxNotificationCSS.WordWrap = false;
|
||||||
|
//
|
||||||
|
// labelWarning
|
||||||
|
//
|
||||||
|
this.labelWarning.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.labelWarning.AutoSize = true;
|
||||||
|
this.labelWarning.Location = new System.Drawing.Point(91, 292);
|
||||||
|
this.labelWarning.Name = "labelWarning";
|
||||||
|
this.labelWarning.Size = new System.Drawing.Size(341, 13);
|
||||||
|
this.labelWarning.TabIndex = 3;
|
||||||
|
this.labelWarning.Text = "The code is not validated, please make sure there are no syntax errors.";
|
||||||
|
//
|
||||||
|
// btnOpenWiki
|
||||||
|
//
|
||||||
|
this.btnOpenWiki.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.btnOpenWiki.AutoSize = true;
|
||||||
|
this.btnOpenWiki.Location = new System.Drawing.Point(12, 287);
|
||||||
|
this.btnOpenWiki.Name = "btnOpenWiki";
|
||||||
|
this.btnOpenWiki.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnOpenWiki.Size = new System.Drawing.Size(73, 23);
|
||||||
|
this.btnOpenWiki.TabIndex = 4;
|
||||||
|
this.btnOpenWiki.Text = "Open Wiki";
|
||||||
|
this.btnOpenWiki.UseVisualStyleBackColor = true;
|
||||||
|
this.btnOpenWiki.Click += new System.EventHandler(this.btnOpenWiki_Click);
|
||||||
|
//
|
||||||
|
// timerTestBrowser
|
||||||
|
//
|
||||||
|
this.timerTestBrowser.Interval = 500;
|
||||||
|
this.timerTestBrowser.Tick += new System.EventHandler(this.timerTestBrowser_Tick);
|
||||||
|
//
|
||||||
|
// DialogSettingsCSS
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(784, 322);
|
||||||
|
this.Controls.Add(this.btnOpenWiki);
|
||||||
|
this.Controls.Add(this.labelWarning);
|
||||||
|
this.Controls.Add(this.splitContainer);
|
||||||
|
this.Controls.Add(this.btnApply);
|
||||||
|
this.Controls.Add(this.btnCancel);
|
||||||
|
this.MinimumSize = new System.Drawing.Size(600, 160);
|
||||||
|
this.Name = "DialogSettingsCSS";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.splitContainer.Panel1.ResumeLayout(false);
|
||||||
|
this.splitContainer.Panel1.PerformLayout();
|
||||||
|
this.splitContainer.Panel2.ResumeLayout(false);
|
||||||
|
this.splitContainer.Panel2.PerformLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
|
||||||
|
this.splitContainer.ResumeLayout(false);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.TextBox textBoxBrowserCSS;
|
||||||
|
private System.Windows.Forms.Button btnCancel;
|
||||||
|
private System.Windows.Forms.Button btnApply;
|
||||||
|
private System.Windows.Forms.SplitContainer splitContainer;
|
||||||
|
private System.Windows.Forms.TextBox textBoxNotificationCSS;
|
||||||
|
private System.Windows.Forms.Label labelBrowser;
|
||||||
|
private System.Windows.Forms.Label labelNotification;
|
||||||
|
private System.Windows.Forms.Label labelWarning;
|
||||||
|
private System.Windows.Forms.Button btnOpenWiki;
|
||||||
|
private System.Windows.Forms.Timer timerTestBrowser;
|
||||||
|
}
|
||||||
|
}
|
||||||
51
Core/Other/Settings/Dialogs/DialogSettingsCSS.cs
Normal file
51
Core/Other/Settings/Dialogs/DialogSettingsCSS.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings.Dialogs{
|
||||||
|
sealed partial class DialogSettingsCSS : Form{
|
||||||
|
public string BrowserCSS => textBoxBrowserCSS.Text;
|
||||||
|
public string NotificationCSS => textBoxNotificationCSS.Text;
|
||||||
|
|
||||||
|
private readonly Action<string> reinjectBrowserCSS;
|
||||||
|
|
||||||
|
public DialogSettingsCSS(Action<string> reinjectBrowserCSS){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Text = Program.BrandName+" Settings - CSS";
|
||||||
|
|
||||||
|
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
||||||
|
|
||||||
|
textBoxBrowserCSS.EnableMultilineShortcuts();
|
||||||
|
textBoxBrowserCSS.Text = Program.UserConfig.CustomBrowserCSS ?? "";
|
||||||
|
|
||||||
|
textBoxNotificationCSS.EnableMultilineShortcuts();
|
||||||
|
textBoxNotificationCSS.Text = Program.UserConfig.CustomNotificationCSS ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void textBoxBrowserCSS_KeyUp(object sender, KeyEventArgs e){
|
||||||
|
timerTestBrowser.Stop();
|
||||||
|
timerTestBrowser.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerTestBrowser_Tick(object sender, EventArgs e){
|
||||||
|
reinjectBrowserCSS(textBoxBrowserCSS.Text);
|
||||||
|
timerTestBrowser.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnOpenWiki_Click(object sender, EventArgs e){
|
||||||
|
BrowserUtils.OpenExternalBrowserUnsafe("https://github.com/chylex/TweetDuck/wiki");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnApply_Click(object sender, EventArgs e){
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel_Click(object sender, EventArgs e){
|
||||||
|
DialogResult = DialogResult.Cancel;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Core/Other/Settings/Dialogs/DialogSettingsCefArgs.Designer.cs
generated
Normal file
120
Core/Other/Settings/Dialogs/DialogSettingsCefArgs.Designer.cs
generated
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
namespace TweetDck.Core.Other.Settings.Dialogs {
|
||||||
|
partial class DialogSettingsCefArgs {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.textBoxArgs = new System.Windows.Forms.TextBox();
|
||||||
|
this.btnCancel = new System.Windows.Forms.Button();
|
||||||
|
this.btnApply = new System.Windows.Forms.Button();
|
||||||
|
this.btnHelp = new System.Windows.Forms.Button();
|
||||||
|
this.labelWarning = new System.Windows.Forms.Label();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// textBoxArgs
|
||||||
|
//
|
||||||
|
this.textBoxArgs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.textBoxArgs.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.textBoxArgs.Location = new System.Drawing.Point(12, 28);
|
||||||
|
this.textBoxArgs.Multiline = true;
|
||||||
|
this.textBoxArgs.Name = "textBoxArgs";
|
||||||
|
this.textBoxArgs.Size = new System.Drawing.Size(460, 193);
|
||||||
|
this.textBoxArgs.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// btnCancel
|
||||||
|
//
|
||||||
|
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnCancel.Location = new System.Drawing.Point(354, 227);
|
||||||
|
this.btnCancel.Name = "btnCancel";
|
||||||
|
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
||||||
|
this.btnCancel.TabIndex = 3;
|
||||||
|
this.btnCancel.Text = "Cancel";
|
||||||
|
this.btnCancel.UseVisualStyleBackColor = true;
|
||||||
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||||
|
//
|
||||||
|
// btnApply
|
||||||
|
//
|
||||||
|
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnApply.Location = new System.Drawing.Point(416, 227);
|
||||||
|
this.btnApply.Name = "btnApply";
|
||||||
|
this.btnApply.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnApply.Size = new System.Drawing.Size(56, 23);
|
||||||
|
this.btnApply.TabIndex = 2;
|
||||||
|
this.btnApply.Text = "Apply";
|
||||||
|
this.btnApply.UseVisualStyleBackColor = true;
|
||||||
|
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
|
||||||
|
//
|
||||||
|
// btnHelp
|
||||||
|
//
|
||||||
|
this.btnHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.btnHelp.AutoSize = true;
|
||||||
|
this.btnHelp.Location = new System.Drawing.Point(12, 227);
|
||||||
|
this.btnHelp.Name = "btnHelp";
|
||||||
|
this.btnHelp.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnHelp.Size = new System.Drawing.Size(124, 23);
|
||||||
|
this.btnHelp.TabIndex = 4;
|
||||||
|
this.btnHelp.Text = "List of Chromium Args";
|
||||||
|
this.btnHelp.UseVisualStyleBackColor = true;
|
||||||
|
this.btnHelp.Click += new System.EventHandler(this.btnHelp_Click);
|
||||||
|
//
|
||||||
|
// labelWarning
|
||||||
|
//
|
||||||
|
this.labelWarning.AutoSize = true;
|
||||||
|
this.labelWarning.Location = new System.Drawing.Point(12, 9);
|
||||||
|
this.labelWarning.Margin = new System.Windows.Forms.Padding(3, 0, 3, 3);
|
||||||
|
this.labelWarning.Name = "labelWarning";
|
||||||
|
this.labelWarning.Size = new System.Drawing.Size(423, 13);
|
||||||
|
this.labelWarning.TabIndex = 0;
|
||||||
|
this.labelWarning.Text = "Warning: Some arguments may cause the program to stop working, edit at your own r" +
|
||||||
|
"isk.";
|
||||||
|
//
|
||||||
|
// DialogSettingsCefArgs
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(484, 262);
|
||||||
|
this.Controls.Add(this.labelWarning);
|
||||||
|
this.Controls.Add(this.btnHelp);
|
||||||
|
this.Controls.Add(this.btnApply);
|
||||||
|
this.Controls.Add(this.btnCancel);
|
||||||
|
this.Controls.Add(this.textBoxArgs);
|
||||||
|
this.MinimumSize = new System.Drawing.Size(500, 160);
|
||||||
|
this.Name = "DialogSettingsCefArgs";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.TextBox textBoxArgs;
|
||||||
|
private System.Windows.Forms.Button btnCancel;
|
||||||
|
private System.Windows.Forms.Button btnApply;
|
||||||
|
private System.Windows.Forms.Button btnHelp;
|
||||||
|
private System.Windows.Forms.Label labelWarning;
|
||||||
|
}
|
||||||
|
}
|
||||||
47
Core/Other/Settings/Dialogs/DialogSettingsCefArgs.cs
Normal file
47
Core/Other/Settings/Dialogs/DialogSettingsCefArgs.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings.Dialogs{
|
||||||
|
sealed partial class DialogSettingsCefArgs : Form{
|
||||||
|
public string CefArgs => textBoxArgs.Text;
|
||||||
|
|
||||||
|
public DialogSettingsCefArgs(){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Text = Program.BrandName+" Settings - CEF Arguments";
|
||||||
|
|
||||||
|
textBoxArgs.EnableMultilineShortcuts();
|
||||||
|
textBoxArgs.Text = Program.UserConfig.CustomCefArgs ?? "";
|
||||||
|
textBoxArgs.Select(textBoxArgs.Text.Length, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnHelp_Click(object sender, EventArgs e){
|
||||||
|
BrowserUtils.OpenExternalBrowserUnsafe("http://peter.sh/experiments/chromium-command-line-switches/");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnApply_Click(object sender, EventArgs e){
|
||||||
|
string prevArgs = Program.UserConfig.CustomCefArgs;
|
||||||
|
|
||||||
|
if (CefArgs == prevArgs){
|
||||||
|
DialogResult = DialogResult.Cancel;
|
||||||
|
Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = CommandLineArgsParser.ReadCefArguments(CefArgs).Count;
|
||||||
|
string prompt = count == 0 && !string.IsNullOrWhiteSpace(prevArgs) ? "All arguments will be removed from the settings. Continue?" : count+(count == 1 ? " argument" : " arguments")+" will be added to the settings. Continue?";
|
||||||
|
|
||||||
|
if (MessageBox.Show(prompt, "Confirm CEF Arguments", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK){
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel_Click(object sender, EventArgs e){
|
||||||
|
DialogResult = DialogResult.Cancel;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
130
Core/Other/Settings/Dialogs/DialogSettingsExport.Designer.cs
generated
Normal file
130
Core/Other/Settings/Dialogs/DialogSettingsExport.Designer.cs
generated
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
namespace TweetDck.Core.Other.Settings.Dialogs {
|
||||||
|
partial class DialogSettingsExport {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.btnCancel = new System.Windows.Forms.Button();
|
||||||
|
this.btnApply = new System.Windows.Forms.Button();
|
||||||
|
this.cbConfig = new System.Windows.Forms.CheckBox();
|
||||||
|
this.cbSession = new System.Windows.Forms.CheckBox();
|
||||||
|
this.cbPluginData = new System.Windows.Forms.CheckBox();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// btnCancel
|
||||||
|
//
|
||||||
|
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnCancel.AutoSize = true;
|
||||||
|
this.btnCancel.Location = new System.Drawing.Point(176, 97);
|
||||||
|
this.btnCancel.Name = "btnCancel";
|
||||||
|
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
||||||
|
this.btnCancel.TabIndex = 4;
|
||||||
|
this.btnCancel.Text = "Cancel";
|
||||||
|
this.btnCancel.UseVisualStyleBackColor = true;
|
||||||
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||||
|
//
|
||||||
|
// btnApply
|
||||||
|
//
|
||||||
|
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnApply.AutoSize = true;
|
||||||
|
this.btnApply.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||||
|
this.btnApply.Location = new System.Drawing.Point(144, 97);
|
||||||
|
this.btnApply.Name = "btnApply";
|
||||||
|
this.btnApply.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnApply.Size = new System.Drawing.Size(26, 23);
|
||||||
|
this.btnApply.TabIndex = 3;
|
||||||
|
this.btnApply.Text = " ";
|
||||||
|
this.btnApply.UseVisualStyleBackColor = true;
|
||||||
|
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
|
||||||
|
//
|
||||||
|
// cbConfig
|
||||||
|
//
|
||||||
|
this.cbConfig.AutoSize = true;
|
||||||
|
this.cbConfig.Location = new System.Drawing.Point(13, 13);
|
||||||
|
this.cbConfig.Name = "cbConfig";
|
||||||
|
this.cbConfig.Size = new System.Drawing.Size(106, 17);
|
||||||
|
this.cbConfig.TabIndex = 0;
|
||||||
|
this.cbConfig.Text = "Program Settings";
|
||||||
|
this.toolTip.SetToolTip(this.cbConfig, "Interface, notification, and update settings.\r\nIncludes a list of disabled plugin" +
|
||||||
|
"s.");
|
||||||
|
this.cbConfig.UseVisualStyleBackColor = true;
|
||||||
|
this.cbConfig.CheckedChanged += new System.EventHandler(this.cbConfig_CheckedChanged);
|
||||||
|
//
|
||||||
|
// cbSession
|
||||||
|
//
|
||||||
|
this.cbSession.AutoSize = true;
|
||||||
|
this.cbSession.Location = new System.Drawing.Point(13, 37);
|
||||||
|
this.cbSession.Name = "cbSession";
|
||||||
|
this.cbSession.Size = new System.Drawing.Size(92, 17);
|
||||||
|
this.cbSession.TabIndex = 1;
|
||||||
|
this.cbSession.Text = "Login Session";
|
||||||
|
this.toolTip.SetToolTip(this.cbSession, "A token that allows logging into the\r\ncurrent TweetDeck account.");
|
||||||
|
this.cbSession.UseVisualStyleBackColor = true;
|
||||||
|
this.cbSession.CheckedChanged += new System.EventHandler(this.cbSession_CheckedChanged);
|
||||||
|
//
|
||||||
|
// cbPluginData
|
||||||
|
//
|
||||||
|
this.cbPluginData.AutoSize = true;
|
||||||
|
this.cbPluginData.Location = new System.Drawing.Point(13, 61);
|
||||||
|
this.cbPluginData.Name = "cbPluginData";
|
||||||
|
this.cbPluginData.Size = new System.Drawing.Size(81, 17);
|
||||||
|
this.cbPluginData.TabIndex = 2;
|
||||||
|
this.cbPluginData.Text = "Plugin Data";
|
||||||
|
this.toolTip.SetToolTip(this.cbPluginData, "Data files generated by plugins.\r\nDoes not include the plugins themselves.");
|
||||||
|
this.cbPluginData.UseVisualStyleBackColor = true;
|
||||||
|
this.cbPluginData.CheckedChanged += new System.EventHandler(this.cbPluginData_CheckedChanged);
|
||||||
|
//
|
||||||
|
// DialogSettingsExport
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(244, 132);
|
||||||
|
this.Controls.Add(this.cbPluginData);
|
||||||
|
this.Controls.Add(this.cbSession);
|
||||||
|
this.Controls.Add(this.cbConfig);
|
||||||
|
this.Controls.Add(this.btnApply);
|
||||||
|
this.Controls.Add(this.btnCancel);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.MinimumSize = new System.Drawing.Size(200, 170);
|
||||||
|
this.Name = "DialogSettingsExport";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Button btnCancel;
|
||||||
|
private System.Windows.Forms.Button btnApply;
|
||||||
|
private System.Windows.Forms.CheckBox cbConfig;
|
||||||
|
private System.Windows.Forms.CheckBox cbSession;
|
||||||
|
private System.Windows.Forms.CheckBox cbPluginData;
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
}
|
||||||
|
}
|
||||||
80
Core/Other/Settings/Dialogs/DialogSettingsExport.cs
Normal file
80
Core/Other/Settings/Dialogs/DialogSettingsExport.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Other.Settings.Export;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings.Dialogs{
|
||||||
|
sealed partial class DialogSettingsExport : Form{
|
||||||
|
public static DialogSettingsExport Import(ExportFileFlags flags){
|
||||||
|
return new DialogSettingsExport(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DialogSettingsExport Export(){
|
||||||
|
return new DialogSettingsExport(ExportFileFlags.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExportFileFlags Flags{
|
||||||
|
get => selectedFlags;
|
||||||
|
|
||||||
|
set{
|
||||||
|
// this will call events and SetFlag, which also updates the UI
|
||||||
|
cbConfig.Checked = value.HasFlag(ExportFileFlags.Config);
|
||||||
|
cbSession.Checked = value.HasFlag(ExportFileFlags.Session);
|
||||||
|
cbPluginData.Checked = value.HasFlag(ExportFileFlags.PluginData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly bool isExporting;
|
||||||
|
private ExportFileFlags selectedFlags = ExportFileFlags.None;
|
||||||
|
|
||||||
|
private DialogSettingsExport(ExportFileFlags importFlags){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.isExporting = importFlags == ExportFileFlags.None;
|
||||||
|
|
||||||
|
if (isExporting){
|
||||||
|
Text = "Export Profile";
|
||||||
|
btnApply.Text = "Export Profile";
|
||||||
|
Flags = ExportFileFlags.All & ~ExportFileFlags.Session;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Text = "Import Profile";
|
||||||
|
Flags = importFlags;
|
||||||
|
|
||||||
|
cbConfig.Enabled = cbConfig.Checked;
|
||||||
|
cbSession.Enabled = cbSession.Checked;
|
||||||
|
cbPluginData.Enabled = cbPluginData.Checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetFlag(ExportFileFlags flag, bool enable){
|
||||||
|
selectedFlags = enable ? selectedFlags | flag : selectedFlags & ~flag;
|
||||||
|
btnApply.Enabled = selectedFlags != ExportFileFlags.None;
|
||||||
|
|
||||||
|
if (!isExporting){
|
||||||
|
btnApply.Text = selectedFlags.HasFlag(ExportFileFlags.Session) ? "Import && Restart" : "Import Profile";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cbConfig_CheckedChanged(object sender, EventArgs e){
|
||||||
|
SetFlag(ExportFileFlags.Config, cbConfig.Checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cbSession_CheckedChanged(object sender, EventArgs e){
|
||||||
|
SetFlag(ExportFileFlags.Session, cbSession.Checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cbPluginData_CheckedChanged(object sender, EventArgs e){
|
||||||
|
SetFlag(ExportFileFlags.PluginData, cbPluginData.Checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnApply_Click(object sender, EventArgs e){
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel_Click(object sender, EventArgs e){
|
||||||
|
DialogResult = DialogResult.Cancel;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
161
Core/Other/Settings/Dialogs/DialogSettingsRestart.Designer.cs
generated
Normal file
161
Core/Other/Settings/Dialogs/DialogSettingsRestart.Designer.cs
generated
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
namespace TweetDck.Core.Other.Settings.Dialogs {
|
||||||
|
partial class DialogSettingsRestart {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.btnCancel = new System.Windows.Forms.Button();
|
||||||
|
this.btnRestart = new System.Windows.Forms.Button();
|
||||||
|
this.cbLogging = new System.Windows.Forms.CheckBox();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.cbDebugUpdates = new System.Windows.Forms.CheckBox();
|
||||||
|
this.labelLocale = new System.Windows.Forms.Label();
|
||||||
|
this.comboLocale = new System.Windows.Forms.ComboBox();
|
||||||
|
this.labelDataFolder = new System.Windows.Forms.Label();
|
||||||
|
this.tbDataFolder = new System.Windows.Forms.TextBox();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// btnCancel
|
||||||
|
//
|
||||||
|
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnCancel.AutoSize = true;
|
||||||
|
this.btnCancel.Location = new System.Drawing.Point(160, 171);
|
||||||
|
this.btnCancel.Name = "btnCancel";
|
||||||
|
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
||||||
|
this.btnCancel.TabIndex = 7;
|
||||||
|
this.btnCancel.Text = "Cancel";
|
||||||
|
this.btnCancel.UseVisualStyleBackColor = true;
|
||||||
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||||
|
//
|
||||||
|
// btnRestart
|
||||||
|
//
|
||||||
|
this.btnRestart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnRestart.AutoSize = true;
|
||||||
|
this.btnRestart.Location = new System.Drawing.Point(97, 171);
|
||||||
|
this.btnRestart.Name = "btnRestart";
|
||||||
|
this.btnRestart.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnRestart.Size = new System.Drawing.Size(57, 23);
|
||||||
|
this.btnRestart.TabIndex = 6;
|
||||||
|
this.btnRestart.Text = "Restart";
|
||||||
|
this.btnRestart.UseVisualStyleBackColor = true;
|
||||||
|
this.btnRestart.Click += new System.EventHandler(this.btnRestart_Click);
|
||||||
|
//
|
||||||
|
// cbLogging
|
||||||
|
//
|
||||||
|
this.cbLogging.AutoSize = true;
|
||||||
|
this.cbLogging.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.cbLogging.Name = "cbLogging";
|
||||||
|
this.cbLogging.Size = new System.Drawing.Size(64, 17);
|
||||||
|
this.cbLogging.TabIndex = 0;
|
||||||
|
this.cbLogging.Text = "Logging";
|
||||||
|
this.toolTip.SetToolTip(this.cbLogging, "Logging JavaScript output into a\r\ndebug.txt file in the data folder.");
|
||||||
|
this.cbLogging.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// cbDebugUpdates
|
||||||
|
//
|
||||||
|
this.cbDebugUpdates.AutoSize = true;
|
||||||
|
this.cbDebugUpdates.Location = new System.Drawing.Point(12, 35);
|
||||||
|
this.cbDebugUpdates.Name = "cbDebugUpdates";
|
||||||
|
this.cbDebugUpdates.Size = new System.Drawing.Size(127, 17);
|
||||||
|
this.cbDebugUpdates.TabIndex = 1;
|
||||||
|
this.cbDebugUpdates.Text = "Pre-Release Updates";
|
||||||
|
this.toolTip.SetToolTip(this.cbDebugUpdates, "Allows updating to pre-releases.");
|
||||||
|
this.cbDebugUpdates.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelLocale
|
||||||
|
//
|
||||||
|
this.labelLocale.AutoSize = true;
|
||||||
|
this.labelLocale.Location = new System.Drawing.Point(12, 67);
|
||||||
|
this.labelLocale.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelLocale.Name = "labelLocale";
|
||||||
|
this.labelLocale.Size = new System.Drawing.Size(39, 13);
|
||||||
|
this.labelLocale.TabIndex = 2;
|
||||||
|
this.labelLocale.Text = "Locale";
|
||||||
|
//
|
||||||
|
// comboLocale
|
||||||
|
//
|
||||||
|
this.comboLocale.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.comboLocale.FormattingEnabled = true;
|
||||||
|
this.comboLocale.Location = new System.Drawing.Point(15, 83);
|
||||||
|
this.comboLocale.Name = "comboLocale";
|
||||||
|
this.comboLocale.Size = new System.Drawing.Size(201, 21);
|
||||||
|
this.comboLocale.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// labelDataFolder
|
||||||
|
//
|
||||||
|
this.labelDataFolder.AutoSize = true;
|
||||||
|
this.labelDataFolder.Location = new System.Drawing.Point(12, 119);
|
||||||
|
this.labelDataFolder.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelDataFolder.Name = "labelDataFolder";
|
||||||
|
this.labelDataFolder.Size = new System.Drawing.Size(62, 13);
|
||||||
|
this.labelDataFolder.TabIndex = 4;
|
||||||
|
this.labelDataFolder.Text = "Data Folder";
|
||||||
|
//
|
||||||
|
// tbDataFolder
|
||||||
|
//
|
||||||
|
this.tbDataFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.tbDataFolder.Location = new System.Drawing.Point(15, 135);
|
||||||
|
this.tbDataFolder.Name = "tbDataFolder";
|
||||||
|
this.tbDataFolder.Size = new System.Drawing.Size(201, 20);
|
||||||
|
this.tbDataFolder.TabIndex = 5;
|
||||||
|
//
|
||||||
|
// DialogSettingsRestart
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(228, 206);
|
||||||
|
this.Controls.Add(this.tbDataFolder);
|
||||||
|
this.Controls.Add(this.labelDataFolder);
|
||||||
|
this.Controls.Add(this.comboLocale);
|
||||||
|
this.Controls.Add(this.labelLocale);
|
||||||
|
this.Controls.Add(this.cbDebugUpdates);
|
||||||
|
this.Controls.Add(this.cbLogging);
|
||||||
|
this.Controls.Add(this.btnRestart);
|
||||||
|
this.Controls.Add(this.btnCancel);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "DialogSettingsRestart";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Button btnCancel;
|
||||||
|
private System.Windows.Forms.Button btnRestart;
|
||||||
|
private System.Windows.Forms.CheckBox cbLogging;
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
private System.Windows.Forms.CheckBox cbDebugUpdates;
|
||||||
|
private System.Windows.Forms.Label labelLocale;
|
||||||
|
private System.Windows.Forms.ComboBox comboLocale;
|
||||||
|
private System.Windows.Forms.Label labelDataFolder;
|
||||||
|
private System.Windows.Forms.TextBox tbDataFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
62
Core/Other/Settings/Dialogs/DialogSettingsRestart.cs
Normal file
62
Core/Other/Settings/Dialogs/DialogSettingsRestart.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Configuration;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings.Dialogs{
|
||||||
|
sealed partial class DialogSettingsRestart : Form{
|
||||||
|
private const string DefaultLocale = "en-US";
|
||||||
|
|
||||||
|
public CommandLineArgs Args { get; private set; }
|
||||||
|
|
||||||
|
public DialogSettingsRestart(CommandLineArgs currentArgs){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
try{
|
||||||
|
object[] locales = Directory.EnumerateFiles(Path.Combine(Program.ProgramPath, "locales"), "*.pak", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToArray<object>();
|
||||||
|
comboLocale.Items.AddRange(locales);
|
||||||
|
}catch{
|
||||||
|
comboLocale.Items.Add(DefaultLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
cbLogging.Checked = currentArgs.HasFlag(Arguments.ArgLogging);
|
||||||
|
cbDebugUpdates.Checked = currentArgs.HasFlag(Arguments.ArgDebugUpdates);
|
||||||
|
comboLocale.SelectedItem = currentArgs.GetValue(Arguments.ArgLocale, DefaultLocale);
|
||||||
|
tbDataFolder.Text = currentArgs.GetValue(Arguments.ArgDataFolder, string.Empty);
|
||||||
|
|
||||||
|
Text = Program.BrandName+" Arguments";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnRestart_Click(object sender, EventArgs e){
|
||||||
|
Args = new CommandLineArgs();
|
||||||
|
|
||||||
|
if (cbLogging.Checked){
|
||||||
|
Args.AddFlag(Arguments.ArgLogging);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cbDebugUpdates.Checked){
|
||||||
|
Args.AddFlag(Arguments.ArgDebugUpdates);
|
||||||
|
}
|
||||||
|
|
||||||
|
string locale = comboLocale.SelectedItem as string;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(locale) && locale != DefaultLocale){
|
||||||
|
Args.SetValue(Arguments.ArgLocale, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(tbDataFolder.Text)){
|
||||||
|
Args.SetValue(Arguments.ArgDataFolder, tbDataFolder.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel_Click(object sender, EventArgs e){
|
||||||
|
DialogResult = DialogResult.Cancel;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
135
Core/Other/Settings/Export/CombinedFileStream.cs
Normal file
135
Core/Other/Settings/Export/CombinedFileStream.cs
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings.Export{
|
||||||
|
class CombinedFileStream : IDisposable{
|
||||||
|
public const char KeySeparator = '|';
|
||||||
|
|
||||||
|
private readonly Stream stream;
|
||||||
|
|
||||||
|
public CombinedFileStream(Stream stream){
|
||||||
|
this.stream = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteFile(string[] identifier, string path){
|
||||||
|
WriteFile(string.Join(KeySeparator.ToString(), identifier), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteFile(string identifier, string path){
|
||||||
|
byte[] name = Encoding.UTF8.GetBytes(identifier);
|
||||||
|
|
||||||
|
if (name.Length > 255){
|
||||||
|
throw new ArgumentOutOfRangeException("Identifier cannot be 256 or more characters long: "+identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] contents;
|
||||||
|
|
||||||
|
using(FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
|
||||||
|
int index = 0;
|
||||||
|
int left = (int)fileStream.Length;
|
||||||
|
|
||||||
|
contents = new byte[left];
|
||||||
|
|
||||||
|
while(left > 0){
|
||||||
|
int read = fileStream.Read(contents, index, left);
|
||||||
|
index += read;
|
||||||
|
left -= read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.WriteByte((byte)name.Length);
|
||||||
|
stream.Write(name, 0, name.Length);
|
||||||
|
stream.Write(BitConverter.GetBytes(contents.Length), 0, 4);
|
||||||
|
stream.Write(contents, 0, contents.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entry ReadFile(){
|
||||||
|
int nameLength = stream.ReadByte();
|
||||||
|
|
||||||
|
if (nameLength == -1){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] name = new byte[nameLength];
|
||||||
|
stream.Read(name, 0, nameLength);
|
||||||
|
|
||||||
|
byte[] contentLength = new byte[4];
|
||||||
|
stream.Read(contentLength, 0, 4);
|
||||||
|
|
||||||
|
byte[] contents = new byte[BitConverter.ToInt32(contentLength, 0)];
|
||||||
|
stream.Read(contents, 0, contents.Length);
|
||||||
|
|
||||||
|
return new Entry(Encoding.UTF8.GetString(name), contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SkipFile(){
|
||||||
|
int nameLength = stream.ReadByte();
|
||||||
|
|
||||||
|
if (nameLength == -1){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] name = new byte[nameLength];
|
||||||
|
stream.Read(name, 0, nameLength);
|
||||||
|
|
||||||
|
byte[] contentLength = new byte[4];
|
||||||
|
stream.Read(contentLength, 0, 4);
|
||||||
|
|
||||||
|
stream.Position += BitConverter.ToInt32(contentLength, 0);
|
||||||
|
|
||||||
|
string keyName = Encoding.UTF8.GetString(name);
|
||||||
|
int separatorIndex = keyName.IndexOf(KeySeparator);
|
||||||
|
return separatorIndex == -1 ? keyName : keyName.Substring(0, separatorIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Flush(){
|
||||||
|
stream.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisposable.Dispose(){
|
||||||
|
stream.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Entry{
|
||||||
|
public string Identifier { get; }
|
||||||
|
|
||||||
|
public string KeyName{
|
||||||
|
get{
|
||||||
|
int index = Identifier.IndexOf(KeySeparator);
|
||||||
|
return index == -1 ? Identifier : Identifier.Substring(0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] KeyValue{
|
||||||
|
get{
|
||||||
|
int index = Identifier.IndexOf(KeySeparator);
|
||||||
|
return index == -1 ? new string[0] : Identifier.Substring(index+1).Split(KeySeparator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly byte[] contents;
|
||||||
|
|
||||||
|
public Entry(string identifier, byte[] contents){
|
||||||
|
this.Identifier = identifier;
|
||||||
|
this.contents = contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteToFile(string path){
|
||||||
|
File.WriteAllBytes(path, contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteToFile(string path, bool createDirectory){
|
||||||
|
if (createDirectory){
|
||||||
|
string dir = Path.GetDirectoryName(path);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(dir)){
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllBytes(path, contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Core/Other/Settings/Export/ExportFileFlags.cs
Normal file
12
Core/Other/Settings/Export/ExportFileFlags.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings.Export{
|
||||||
|
[Flags]
|
||||||
|
enum ExportFileFlags{
|
||||||
|
None = 0,
|
||||||
|
Config = 1,
|
||||||
|
Session = 2,
|
||||||
|
PluginData = 4,
|
||||||
|
All = Config|Session|PluginData
|
||||||
|
}
|
||||||
|
}
|
||||||
184
Core/Other/Settings/Export/ExportManager.cs
Normal file
184
Core/Other/Settings/Export/ExportManager.cs
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Configuration;
|
||||||
|
using TweetDck.Plugins;
|
||||||
|
using TweetDck.Plugins.Enums;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings.Export{
|
||||||
|
sealed class ExportManager{
|
||||||
|
private static readonly string CookiesPath = Path.Combine(Program.StoragePath, "Cookies");
|
||||||
|
private static readonly string TempCookiesPath = Path.Combine(Program.StoragePath, "CookiesTmp");
|
||||||
|
|
||||||
|
public bool IsRestarting { get; private set; }
|
||||||
|
public Exception LastException { get; private set; }
|
||||||
|
|
||||||
|
private readonly string file;
|
||||||
|
private readonly PluginManager plugins;
|
||||||
|
|
||||||
|
public ExportManager(string file, PluginManager plugins){
|
||||||
|
this.file = file;
|
||||||
|
this.plugins = plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Export(ExportFileFlags flags){
|
||||||
|
try{
|
||||||
|
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))){
|
||||||
|
if (flags.HasFlag(ExportFileFlags.Config)){
|
||||||
|
stream.WriteFile("config", Program.ConfigFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags.HasFlag(ExportFileFlags.PluginData)){
|
||||||
|
stream.WriteFile("plugin.config", Program.PluginConfigFilePath);
|
||||||
|
|
||||||
|
foreach(Plugin plugin in plugins.Plugins){
|
||||||
|
foreach(PathInfo path in EnumerateFilesRelative(plugin.GetPluginFolder(PluginFolder.Data))){
|
||||||
|
try{
|
||||||
|
stream.WriteFile(new string[]{ "plugin.data", plugin.Identifier, path.Relative }, path.Full);
|
||||||
|
}catch(ArgumentOutOfRangeException e){
|
||||||
|
MessageBox.Show("Could not include a plugin file in the export. "+e.Message, "Export Profile", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags.HasFlag(ExportFileFlags.Session)){
|
||||||
|
stream.WriteFile("cookies", CookiesPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}catch(Exception e){
|
||||||
|
LastException = e;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExportFileFlags GetImportFlags(){
|
||||||
|
ExportFileFlags flags = ExportFileFlags.None;
|
||||||
|
|
||||||
|
try{
|
||||||
|
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None))){
|
||||||
|
string key;
|
||||||
|
|
||||||
|
while((key = stream.SkipFile()) != null){
|
||||||
|
switch(key){
|
||||||
|
case "config":
|
||||||
|
flags |= ExportFileFlags.Config;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "plugin.config":
|
||||||
|
case "plugin.data":
|
||||||
|
flags |= ExportFileFlags.PluginData;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "cookies":
|
||||||
|
flags |= ExportFileFlags.Session;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(Exception e){
|
||||||
|
LastException = e;
|
||||||
|
flags = ExportFileFlags.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Import(ExportFileFlags flags){
|
||||||
|
try{
|
||||||
|
HashSet<string> missingPlugins = new HashSet<string>();
|
||||||
|
|
||||||
|
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None))){
|
||||||
|
CombinedFileStream.Entry entry;
|
||||||
|
|
||||||
|
while((entry = stream.ReadFile()) != null){
|
||||||
|
switch(entry.KeyName){
|
||||||
|
case "config":
|
||||||
|
if (flags.HasFlag(ExportFileFlags.Config)){
|
||||||
|
entry.WriteToFile(Program.ConfigFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "plugin.config":
|
||||||
|
if (flags.HasFlag(ExportFileFlags.PluginData)){
|
||||||
|
entry.WriteToFile(Program.PluginConfigFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "plugin.data":
|
||||||
|
if (flags.HasFlag(ExportFileFlags.PluginData)){
|
||||||
|
string[] value = entry.KeyValue;
|
||||||
|
|
||||||
|
entry.WriteToFile(Path.Combine(Program.PluginDataPath, value[0], value[1]), true);
|
||||||
|
|
||||||
|
if (!plugins.IsPluginInstalled(value[0])){
|
||||||
|
missingPlugins.Add(value[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "cookies":
|
||||||
|
if (flags.HasFlag(ExportFileFlags.Session)){
|
||||||
|
entry.WriteToFile(Path.Combine(Program.StoragePath, TempCookiesPath));
|
||||||
|
IsRestarting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingPlugins.Count > 0){
|
||||||
|
MessageBox.Show("Detected missing plugins when importing plugin data:"+Environment.NewLine+string.Join(Environment.NewLine, missingPlugins), "Importing "+Program.BrandName+" Profile", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsRestarting){
|
||||||
|
Program.Restart(new string[]{ Arguments.ArgImportCookies });
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Program.ReloadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}catch(Exception e){
|
||||||
|
LastException = e;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ImportCookies(){
|
||||||
|
if (File.Exists(TempCookiesPath)){
|
||||||
|
try{
|
||||||
|
if (File.Exists(CookiesPath)){
|
||||||
|
File.Delete(CookiesPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.Move(TempCookiesPath, CookiesPath);
|
||||||
|
}catch(Exception e){
|
||||||
|
Program.Reporter.HandleException("Profile Import Error", "Could not import the cookie file to restore login session.", true, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<PathInfo> EnumerateFilesRelative(string root){
|
||||||
|
return Directory.Exists(root) ? Directory.EnumerateFiles(root, "*.*", SearchOption.AllDirectories).Select(fullPath => new PathInfo{
|
||||||
|
Full = fullPath,
|
||||||
|
Relative = fullPath.Substring(root.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) // strip leading separator character
|
||||||
|
}) : Enumerable.Empty<PathInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PathInfo{
|
||||||
|
public string Full { get; set; }
|
||||||
|
public string Relative { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
243
Core/Other/Settings/TabSettingsAdvanced.Designer.cs
generated
Normal file
243
Core/Other/Settings/TabSettingsAdvanced.Designer.cs
generated
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
namespace TweetDck.Core.Other.Settings {
|
||||||
|
partial class TabSettingsAdvanced {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.btnClearCache = new System.Windows.Forms.Button();
|
||||||
|
this.checkHardwareAcceleration = new System.Windows.Forms.CheckBox();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.btnEditCefArgs = new System.Windows.Forms.Button();
|
||||||
|
this.btnEditCSS = new System.Windows.Forms.Button();
|
||||||
|
this.btnRestartArgs = new System.Windows.Forms.Button();
|
||||||
|
this.btnRestart = new System.Windows.Forms.Button();
|
||||||
|
this.btnOpenAppFolder = new System.Windows.Forms.Button();
|
||||||
|
this.btnOpenDataFolder = new System.Windows.Forms.Button();
|
||||||
|
this.btnReset = new System.Windows.Forms.Button();
|
||||||
|
this.btnImport = new System.Windows.Forms.Button();
|
||||||
|
this.btnExport = new System.Windows.Forms.Button();
|
||||||
|
this.groupPerformance = new System.Windows.Forms.GroupBox();
|
||||||
|
this.groupConfiguration = new System.Windows.Forms.GroupBox();
|
||||||
|
this.groupApp = new System.Windows.Forms.GroupBox();
|
||||||
|
this.groupPerformance.SuspendLayout();
|
||||||
|
this.groupConfiguration.SuspendLayout();
|
||||||
|
this.groupApp.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// btnClearCache
|
||||||
|
//
|
||||||
|
this.btnClearCache.Location = new System.Drawing.Point(6, 44);
|
||||||
|
this.btnClearCache.Name = "btnClearCache";
|
||||||
|
this.btnClearCache.Size = new System.Drawing.Size(171, 23);
|
||||||
|
this.btnClearCache.TabIndex = 1;
|
||||||
|
this.btnClearCache.Text = "Clear Cache (calculating)";
|
||||||
|
this.toolTip.SetToolTip(this.btnClearCache, "Clearing cache will free up space taken by downloaded images and other resources." +
|
||||||
|
"");
|
||||||
|
this.btnClearCache.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// checkHardwareAcceleration
|
||||||
|
//
|
||||||
|
this.checkHardwareAcceleration.AutoSize = true;
|
||||||
|
this.checkHardwareAcceleration.Location = new System.Drawing.Point(9, 21);
|
||||||
|
this.checkHardwareAcceleration.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
|
this.checkHardwareAcceleration.Name = "checkHardwareAcceleration";
|
||||||
|
this.checkHardwareAcceleration.Size = new System.Drawing.Size(134, 17);
|
||||||
|
this.checkHardwareAcceleration.TabIndex = 0;
|
||||||
|
this.checkHardwareAcceleration.Text = "Hardware Acceleration";
|
||||||
|
this.toolTip.SetToolTip(this.checkHardwareAcceleration, "Uses your graphics card to improve performance.\r\nDisable if you experience issues" +
|
||||||
|
" with rendering.");
|
||||||
|
this.checkHardwareAcceleration.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnEditCefArgs
|
||||||
|
//
|
||||||
|
this.btnEditCefArgs.Location = new System.Drawing.Point(6, 19);
|
||||||
|
this.btnEditCefArgs.Name = "btnEditCefArgs";
|
||||||
|
this.btnEditCefArgs.Size = new System.Drawing.Size(171, 23);
|
||||||
|
this.btnEditCefArgs.TabIndex = 0;
|
||||||
|
this.btnEditCefArgs.Text = "Edit CEF Arguments";
|
||||||
|
this.toolTip.SetToolTip(this.btnEditCefArgs, "Set custom command line arguments for Chromium Embedded Framework.");
|
||||||
|
this.btnEditCefArgs.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnEditCSS
|
||||||
|
//
|
||||||
|
this.btnEditCSS.Location = new System.Drawing.Point(6, 48);
|
||||||
|
this.btnEditCSS.Name = "btnEditCSS";
|
||||||
|
this.btnEditCSS.Size = new System.Drawing.Size(171, 23);
|
||||||
|
this.btnEditCSS.TabIndex = 1;
|
||||||
|
this.btnEditCSS.Text = "Edit CSS";
|
||||||
|
this.toolTip.SetToolTip(this.btnEditCSS, "Set custom CSS for browser and notification windows.");
|
||||||
|
this.btnEditCSS.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnRestartArgs
|
||||||
|
//
|
||||||
|
this.btnRestartArgs.Location = new System.Drawing.Point(6, 106);
|
||||||
|
this.btnRestartArgs.Name = "btnRestartArgs";
|
||||||
|
this.btnRestartArgs.Size = new System.Drawing.Size(171, 23);
|
||||||
|
this.btnRestartArgs.TabIndex = 3;
|
||||||
|
this.btnRestartArgs.Text = "Restart with Arguments";
|
||||||
|
this.toolTip.SetToolTip(this.btnRestartArgs, "Restarts the program with customizable\r\ncommand line arguments.");
|
||||||
|
this.btnRestartArgs.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnRestart
|
||||||
|
//
|
||||||
|
this.btnRestart.Location = new System.Drawing.Point(6, 77);
|
||||||
|
this.btnRestart.Name = "btnRestart";
|
||||||
|
this.btnRestart.Size = new System.Drawing.Size(171, 23);
|
||||||
|
this.btnRestart.TabIndex = 2;
|
||||||
|
this.btnRestart.Text = "Restart the Program";
|
||||||
|
this.toolTip.SetToolTip(this.btnRestart, "Restarts the program using the same command\r\nline arguments that were used at lau" +
|
||||||
|
"nch.");
|
||||||
|
this.btnRestart.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnOpenAppFolder
|
||||||
|
//
|
||||||
|
this.btnOpenAppFolder.Location = new System.Drawing.Point(6, 19);
|
||||||
|
this.btnOpenAppFolder.Name = "btnOpenAppFolder";
|
||||||
|
this.btnOpenAppFolder.Size = new System.Drawing.Size(171, 23);
|
||||||
|
this.btnOpenAppFolder.TabIndex = 0;
|
||||||
|
this.btnOpenAppFolder.Text = "Open Program Folder";
|
||||||
|
this.toolTip.SetToolTip(this.btnOpenAppFolder, "Opens the folder where the app is located.");
|
||||||
|
this.btnOpenAppFolder.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnOpenDataFolder
|
||||||
|
//
|
||||||
|
this.btnOpenDataFolder.Location = new System.Drawing.Point(6, 48);
|
||||||
|
this.btnOpenDataFolder.Name = "btnOpenDataFolder";
|
||||||
|
this.btnOpenDataFolder.Size = new System.Drawing.Size(171, 23);
|
||||||
|
this.btnOpenDataFolder.TabIndex = 1;
|
||||||
|
this.btnOpenDataFolder.Text = "Open Data Folder";
|
||||||
|
this.toolTip.SetToolTip(this.btnOpenDataFolder, "Opens the folder where your profile data is located.");
|
||||||
|
this.btnOpenDataFolder.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnReset
|
||||||
|
//
|
||||||
|
this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.btnReset.AutoSize = true;
|
||||||
|
this.btnReset.Location = new System.Drawing.Point(190, 268);
|
||||||
|
this.btnReset.Name = "btnReset";
|
||||||
|
this.btnReset.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnReset.Size = new System.Drawing.Size(102, 23);
|
||||||
|
this.btnReset.TabIndex = 5;
|
||||||
|
this.btnReset.Text = "Restore Defaults";
|
||||||
|
this.btnReset.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnImport
|
||||||
|
//
|
||||||
|
this.btnImport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.btnImport.AutoSize = true;
|
||||||
|
this.btnImport.Location = new System.Drawing.Point(100, 268);
|
||||||
|
this.btnImport.Name = "btnImport";
|
||||||
|
this.btnImport.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnImport.Size = new System.Drawing.Size(84, 23);
|
||||||
|
this.btnImport.TabIndex = 4;
|
||||||
|
this.btnImport.Text = "Import Profile";
|
||||||
|
this.btnImport.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnExport
|
||||||
|
//
|
||||||
|
this.btnExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.btnExport.AutoSize = true;
|
||||||
|
this.btnExport.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||||
|
this.btnExport.Location = new System.Drawing.Point(9, 268);
|
||||||
|
this.btnExport.Name = "btnExport";
|
||||||
|
this.btnExport.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnExport.Size = new System.Drawing.Size(85, 23);
|
||||||
|
this.btnExport.TabIndex = 3;
|
||||||
|
this.btnExport.Text = "Export Profile";
|
||||||
|
this.btnExport.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// groupPerformance
|
||||||
|
//
|
||||||
|
this.groupPerformance.Controls.Add(this.checkHardwareAcceleration);
|
||||||
|
this.groupPerformance.Controls.Add(this.btnClearCache);
|
||||||
|
this.groupPerformance.Location = new System.Drawing.Point(9, 9);
|
||||||
|
this.groupPerformance.Name = "groupPerformance";
|
||||||
|
this.groupPerformance.Size = new System.Drawing.Size(183, 74);
|
||||||
|
this.groupPerformance.TabIndex = 0;
|
||||||
|
this.groupPerformance.TabStop = false;
|
||||||
|
this.groupPerformance.Text = "Performance";
|
||||||
|
//
|
||||||
|
// groupConfiguration
|
||||||
|
//
|
||||||
|
this.groupConfiguration.Controls.Add(this.btnEditCSS);
|
||||||
|
this.groupConfiguration.Controls.Add(this.btnEditCefArgs);
|
||||||
|
this.groupConfiguration.Location = new System.Drawing.Point(9, 89);
|
||||||
|
this.groupConfiguration.Name = "groupConfiguration";
|
||||||
|
this.groupConfiguration.Size = new System.Drawing.Size(183, 77);
|
||||||
|
this.groupConfiguration.TabIndex = 1;
|
||||||
|
this.groupConfiguration.TabStop = false;
|
||||||
|
this.groupConfiguration.Text = "Configuration";
|
||||||
|
//
|
||||||
|
// groupApp
|
||||||
|
//
|
||||||
|
this.groupApp.Controls.Add(this.btnOpenDataFolder);
|
||||||
|
this.groupApp.Controls.Add(this.btnOpenAppFolder);
|
||||||
|
this.groupApp.Controls.Add(this.btnRestartArgs);
|
||||||
|
this.groupApp.Controls.Add(this.btnRestart);
|
||||||
|
this.groupApp.Location = new System.Drawing.Point(198, 9);
|
||||||
|
this.groupApp.Name = "groupApp";
|
||||||
|
this.groupApp.Size = new System.Drawing.Size(183, 135);
|
||||||
|
this.groupApp.TabIndex = 2;
|
||||||
|
this.groupApp.TabStop = false;
|
||||||
|
this.groupApp.Text = "App";
|
||||||
|
//
|
||||||
|
// TabSettingsAdvanced
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.groupApp);
|
||||||
|
this.Controls.Add(this.groupConfiguration);
|
||||||
|
this.Controls.Add(this.groupPerformance);
|
||||||
|
this.Controls.Add(this.btnReset);
|
||||||
|
this.Controls.Add(this.btnImport);
|
||||||
|
this.Controls.Add(this.btnExport);
|
||||||
|
this.Name = "TabSettingsAdvanced";
|
||||||
|
this.Size = new System.Drawing.Size(478, 300);
|
||||||
|
this.groupPerformance.ResumeLayout(false);
|
||||||
|
this.groupPerformance.PerformLayout();
|
||||||
|
this.groupConfiguration.ResumeLayout(false);
|
||||||
|
this.groupApp.ResumeLayout(false);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Button btnClearCache;
|
||||||
|
private System.Windows.Forms.CheckBox checkHardwareAcceleration;
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
private System.Windows.Forms.Button btnReset;
|
||||||
|
private System.Windows.Forms.Button btnImport;
|
||||||
|
private System.Windows.Forms.Button btnExport;
|
||||||
|
private System.Windows.Forms.GroupBox groupPerformance;
|
||||||
|
private System.Windows.Forms.GroupBox groupConfiguration;
|
||||||
|
private System.Windows.Forms.Button btnEditCefArgs;
|
||||||
|
private System.Windows.Forms.Button btnEditCSS;
|
||||||
|
private System.Windows.Forms.GroupBox groupApp;
|
||||||
|
private System.Windows.Forms.Button btnRestartArgs;
|
||||||
|
private System.Windows.Forms.Button btnRestart;
|
||||||
|
private System.Windows.Forms.Button btnOpenAppFolder;
|
||||||
|
private System.Windows.Forms.Button btnOpenDataFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
209
Core/Other/Settings/TabSettingsAdvanced.cs
Normal file
209
Core/Other/Settings/TabSettingsAdvanced.cs
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Configuration;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Other.Settings.Dialogs;
|
||||||
|
using TweetDck.Core.Other.Settings.Export;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
using TweetDck.Plugins;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings{
|
||||||
|
partial class TabSettingsAdvanced : BaseTabSettings{
|
||||||
|
private readonly Action<string> reinjectBrowserCSS;
|
||||||
|
private readonly PluginManager plugins;
|
||||||
|
|
||||||
|
public TabSettingsAdvanced(Action<string> reinjectBrowserCSS, PluginManager plugins){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
||||||
|
this.plugins = plugins;
|
||||||
|
|
||||||
|
checkHardwareAcceleration.Checked = HardwareAcceleration.IsEnabled;
|
||||||
|
|
||||||
|
BrowserCache.CalculateCacheSize(bytes => this.InvokeSafe(() => {
|
||||||
|
if (bytes == -1L){
|
||||||
|
btnClearCache.Text = "Clear Cache (unknown size)";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
btnClearCache.Text = "Clear Cache ("+(int)Math.Ceiling(bytes/(1024.0*1024.0))+" MB)";
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReady(){
|
||||||
|
btnClearCache.Click += btnClearCache_Click;
|
||||||
|
checkHardwareAcceleration.CheckedChanged += checkHardwareAcceleration_CheckedChanged;
|
||||||
|
|
||||||
|
btnEditCefArgs.Click += btnEditCefArgs_Click;
|
||||||
|
btnEditCSS.Click += btnEditCSS_Click;
|
||||||
|
|
||||||
|
btnExport.Click += btnExport_Click;
|
||||||
|
btnImport.Click += btnImport_Click;
|
||||||
|
btnReset.Click += btnReset_Click;
|
||||||
|
|
||||||
|
btnOpenAppFolder.Click += btnOpenAppFolder_Click;
|
||||||
|
btnOpenDataFolder.Click += btnOpenDataFolder_Click;
|
||||||
|
btnRestart.Click += btnRestart_Click;
|
||||||
|
btnRestartArgs.Click += btnRestartArgs_Click;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnClearCache_Click(object sender, EventArgs e){
|
||||||
|
btnClearCache.Enabled = false;
|
||||||
|
BrowserCache.SetClearOnExit();
|
||||||
|
|
||||||
|
MessageBox.Show("Cache will be automatically cleared when "+Program.BrandName+" exits.", "Clear Cache", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkHardwareAcceleration_CheckedChanged(object sender, EventArgs e){
|
||||||
|
bool succeeded = false;
|
||||||
|
|
||||||
|
if (checkHardwareAcceleration.Checked){
|
||||||
|
if (HardwareAcceleration.CanEnable){
|
||||||
|
succeeded = HardwareAcceleration.Enable();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
MessageBox.Show("Cannot enable hardware acceleration, the libraries libEGL.dll and libGLESv2.dll could not be restored.", Program.BrandName+" Settings", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
succeeded = HardwareAcceleration.Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (succeeded){
|
||||||
|
PromptRestart();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
checkHardwareAcceleration.CheckedChanged -= checkHardwareAcceleration_CheckedChanged;
|
||||||
|
checkHardwareAcceleration.Checked = HardwareAcceleration.IsEnabled;
|
||||||
|
checkHardwareAcceleration.CheckedChanged += checkHardwareAcceleration_CheckedChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnEditCefArgs_Click(object sender, EventArgs e){
|
||||||
|
DialogSettingsCefArgs form = new DialogSettingsCefArgs();
|
||||||
|
|
||||||
|
if (form.ShowDialog(ParentForm) == DialogResult.OK){
|
||||||
|
Config.CustomCefArgs = form.CefArgs;
|
||||||
|
form.Dispose();
|
||||||
|
PromptRestart();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
form.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnEditCSS_Click(object sender, EventArgs e){
|
||||||
|
using(DialogSettingsCSS form = new DialogSettingsCSS(reinjectBrowserCSS)){
|
||||||
|
if (form.ShowDialog(ParentForm) == DialogResult.OK){
|
||||||
|
Config.CustomBrowserCSS = form.BrowserCSS;
|
||||||
|
Config.CustomNotificationCSS = form.NotificationCSS;
|
||||||
|
}
|
||||||
|
|
||||||
|
reinjectBrowserCSS(Config.CustomBrowserCSS); // reinject on cancel too, because the CSS is updated while typing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnExport_Click(object sender, EventArgs e){
|
||||||
|
ExportFileFlags flags;
|
||||||
|
|
||||||
|
using(DialogSettingsExport dialog = DialogSettingsExport.Export()){
|
||||||
|
if (dialog.ShowDialog() != DialogResult.OK){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = dialog.Flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
string file;
|
||||||
|
|
||||||
|
using(SaveFileDialog dialog = new SaveFileDialog{
|
||||||
|
AddExtension = true,
|
||||||
|
AutoUpgradeEnabled = true,
|
||||||
|
OverwritePrompt = true,
|
||||||
|
DefaultExt = "tdsettings",
|
||||||
|
FileName = Program.BrandName+".tdsettings",
|
||||||
|
Title = "Export "+Program.BrandName+" Settings",
|
||||||
|
Filter = Program.BrandName+" Settings (*.tdsettings)|*.tdsettings"
|
||||||
|
}){
|
||||||
|
if (dialog.ShowDialog() != DialogResult.OK){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = dialog.FileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
Program.UserConfig.Save();
|
||||||
|
|
||||||
|
ExportManager manager = new ExportManager(file, plugins);
|
||||||
|
|
||||||
|
if (!manager.Export(flags)){
|
||||||
|
Program.Reporter.HandleException("Profile Export Error", "An exception happened while exporting "+Program.BrandName+" settings.", true, manager.LastException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnImport_Click(object sender, EventArgs e){
|
||||||
|
string file;
|
||||||
|
|
||||||
|
using(OpenFileDialog dialog = new OpenFileDialog{
|
||||||
|
AutoUpgradeEnabled = true,
|
||||||
|
DereferenceLinks = true,
|
||||||
|
Title = "Import "+Program.BrandName+" Settings",
|
||||||
|
Filter = Program.BrandName+" Settings (*.tdsettings)|*.tdsettings"
|
||||||
|
}){
|
||||||
|
if (dialog.ShowDialog() != DialogResult.OK){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = dialog.FileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExportManager manager = new ExportManager(file, plugins);
|
||||||
|
ExportFileFlags flags;
|
||||||
|
|
||||||
|
using(DialogSettingsExport dialog = DialogSettingsExport.Import(manager.GetImportFlags())){
|
||||||
|
if (dialog.ShowDialog() != DialogResult.OK){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = dialog.Flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager.Import(flags)){
|
||||||
|
if (!manager.IsRestarting){
|
||||||
|
((FormSettings)ParentForm).ReloadUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Program.Reporter.HandleException("Profile Import Error", "An exception happened while importing "+Program.BrandName+" settings.", true, manager.LastException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnReset_Click(object sender, EventArgs e){
|
||||||
|
if (MessageBox.Show("This will reset all of your program settings. Plugins will not be affected. Do you want to proceed?", "Reset "+Program.BrandName+" Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
|
||||||
|
Program.ResetConfig();
|
||||||
|
((FormSettings)ParentForm).ReloadUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnOpenAppFolder_Click(object sender, EventArgs e){
|
||||||
|
using(Process.Start("explorer.exe", "\""+Program.ProgramPath+"\"")){}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnOpenDataFolder_Click(object sender, EventArgs e){
|
||||||
|
using(Process.Start("explorer.exe", "\""+Program.StoragePath+"\"")){}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnRestart_Click(object sender, EventArgs e){
|
||||||
|
Program.Restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnRestartArgs_Click(object sender, EventArgs e){
|
||||||
|
using(DialogSettingsRestart dialog = new DialogSettingsRestart(Arguments.GetCurrentClean())){
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK){
|
||||||
|
Program.RestartWithArgs(dialog.Args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
266
Core/Other/Settings/TabSettingsGeneral.Designer.cs
generated
Normal file
266
Core/Other/Settings/TabSettingsGeneral.Designer.cs
generated
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
namespace TweetDck.Core.Other.Settings {
|
||||||
|
partial class TabSettingsGeneral {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.checkExpandLinks = new System.Windows.Forms.CheckBox();
|
||||||
|
this.comboBoxTrayType = new System.Windows.Forms.ComboBox();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.checkTrayHighlight = new System.Windows.Forms.CheckBox();
|
||||||
|
this.checkSpellCheck = new System.Windows.Forms.CheckBox();
|
||||||
|
this.checkUpdateNotifications = new System.Windows.Forms.CheckBox();
|
||||||
|
this.btnCheckUpdates = new System.Windows.Forms.Button();
|
||||||
|
this.labelZoomValue = new System.Windows.Forms.Label();
|
||||||
|
this.checkSwitchAccountSelectors = new System.Windows.Forms.CheckBox();
|
||||||
|
this.groupTray = new System.Windows.Forms.GroupBox();
|
||||||
|
this.labelTrayIcon = new System.Windows.Forms.Label();
|
||||||
|
this.groupInterface = new System.Windows.Forms.GroupBox();
|
||||||
|
this.trackBarZoom = new System.Windows.Forms.TrackBar();
|
||||||
|
this.labelZoom = new System.Windows.Forms.Label();
|
||||||
|
this.groupUpdates = new System.Windows.Forms.GroupBox();
|
||||||
|
this.zoomUpdateTimer = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.groupTray.SuspendLayout();
|
||||||
|
this.groupInterface.SuspendLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarZoom)).BeginInit();
|
||||||
|
this.groupUpdates.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// checkExpandLinks
|
||||||
|
//
|
||||||
|
this.checkExpandLinks.AutoSize = true;
|
||||||
|
this.checkExpandLinks.Location = new System.Drawing.Point(9, 21);
|
||||||
|
this.checkExpandLinks.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
|
this.checkExpandLinks.Name = "checkExpandLinks";
|
||||||
|
this.checkExpandLinks.Size = new System.Drawing.Size(166, 17);
|
||||||
|
this.checkExpandLinks.TabIndex = 0;
|
||||||
|
this.checkExpandLinks.Text = "Expand Links When Hovered";
|
||||||
|
this.toolTip.SetToolTip(this.checkExpandLinks, "Expands links inside the tweets. If disabled,\r\nthe full links show up in a toolti" +
|
||||||
|
"p instead.");
|
||||||
|
this.checkExpandLinks.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// comboBoxTrayType
|
||||||
|
//
|
||||||
|
this.comboBoxTrayType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
|
this.comboBoxTrayType.FormattingEnabled = true;
|
||||||
|
this.comboBoxTrayType.Location = new System.Drawing.Point(6, 19);
|
||||||
|
this.comboBoxTrayType.Name = "comboBoxTrayType";
|
||||||
|
this.comboBoxTrayType.Size = new System.Drawing.Size(171, 21);
|
||||||
|
this.comboBoxTrayType.TabIndex = 0;
|
||||||
|
this.toolTip.SetToolTip(this.comboBoxTrayType, "Changes behavior of the Tray icon.\r\nRight-click the icon for an action menu.");
|
||||||
|
//
|
||||||
|
// checkTrayHighlight
|
||||||
|
//
|
||||||
|
this.checkTrayHighlight.AutoSize = true;
|
||||||
|
this.checkTrayHighlight.Location = new System.Drawing.Point(9, 70);
|
||||||
|
this.checkTrayHighlight.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
|
this.checkTrayHighlight.Name = "checkTrayHighlight";
|
||||||
|
this.checkTrayHighlight.Size = new System.Drawing.Size(103, 17);
|
||||||
|
this.checkTrayHighlight.TabIndex = 2;
|
||||||
|
this.checkTrayHighlight.Text = "Enable Highlight";
|
||||||
|
this.toolTip.SetToolTip(this.checkTrayHighlight, "Highlights the tray icon if there are new tweets.\r\nOnly works for columns with po" +
|
||||||
|
"pup or audio notifications.\r\nThe icon resets when the main window is restored.");
|
||||||
|
this.checkTrayHighlight.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// checkSpellCheck
|
||||||
|
//
|
||||||
|
this.checkSpellCheck.AutoSize = true;
|
||||||
|
this.checkSpellCheck.Location = new System.Drawing.Point(9, 67);
|
||||||
|
this.checkSpellCheck.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkSpellCheck.Name = "checkSpellCheck";
|
||||||
|
this.checkSpellCheck.Size = new System.Drawing.Size(119, 17);
|
||||||
|
this.checkSpellCheck.TabIndex = 2;
|
||||||
|
this.checkSpellCheck.Text = "Enable Spell Check";
|
||||||
|
this.toolTip.SetToolTip(this.checkSpellCheck, "Underlines words that are spelled incorrectly.");
|
||||||
|
this.checkSpellCheck.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// checkUpdateNotifications
|
||||||
|
//
|
||||||
|
this.checkUpdateNotifications.AutoSize = true;
|
||||||
|
this.checkUpdateNotifications.Location = new System.Drawing.Point(9, 21);
|
||||||
|
this.checkUpdateNotifications.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
|
this.checkUpdateNotifications.Name = "checkUpdateNotifications";
|
||||||
|
this.checkUpdateNotifications.Size = new System.Drawing.Size(165, 17);
|
||||||
|
this.checkUpdateNotifications.TabIndex = 0;
|
||||||
|
this.checkUpdateNotifications.Text = "Check Updates Automatically";
|
||||||
|
this.toolTip.SetToolTip(this.checkUpdateNotifications, "Checks for updates every hour.\r\nIf an update is dismissed, it will not appear aga" +
|
||||||
|
"in.");
|
||||||
|
this.checkUpdateNotifications.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnCheckUpdates
|
||||||
|
//
|
||||||
|
this.btnCheckUpdates.Location = new System.Drawing.Point(6, 44);
|
||||||
|
this.btnCheckUpdates.Name = "btnCheckUpdates";
|
||||||
|
this.btnCheckUpdates.Size = new System.Drawing.Size(171, 23);
|
||||||
|
this.btnCheckUpdates.TabIndex = 1;
|
||||||
|
this.btnCheckUpdates.Text = "Check Updates Now";
|
||||||
|
this.toolTip.SetToolTip(this.btnCheckUpdates, "Forces an update check, even for updates that had been dismissed.");
|
||||||
|
this.btnCheckUpdates.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelZoomValue
|
||||||
|
//
|
||||||
|
this.labelZoomValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.labelZoomValue.BackColor = System.Drawing.Color.Transparent;
|
||||||
|
this.labelZoomValue.Location = new System.Drawing.Point(139, 116);
|
||||||
|
this.labelZoomValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
|
this.labelZoomValue.Name = "labelZoomValue";
|
||||||
|
this.labelZoomValue.Size = new System.Drawing.Size(38, 13);
|
||||||
|
this.labelZoomValue.TabIndex = 5;
|
||||||
|
this.labelZoomValue.Text = "100%";
|
||||||
|
this.labelZoomValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||||
|
this.toolTip.SetToolTip(this.labelZoomValue, "Changes the zoom level.\r\nAlso affects notifications and screenshots.");
|
||||||
|
//
|
||||||
|
// checkSwitchAccountSelectors
|
||||||
|
//
|
||||||
|
this.checkSwitchAccountSelectors.AutoSize = true;
|
||||||
|
this.checkSwitchAccountSelectors.Location = new System.Drawing.Point(9, 44);
|
||||||
|
this.checkSwitchAccountSelectors.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkSwitchAccountSelectors.Name = "checkSwitchAccountSelectors";
|
||||||
|
this.checkSwitchAccountSelectors.Size = new System.Drawing.Size(172, 17);
|
||||||
|
this.checkSwitchAccountSelectors.TabIndex = 1;
|
||||||
|
this.checkSwitchAccountSelectors.Text = "Shift Selects Multiple Accounts";
|
||||||
|
this.toolTip.SetToolTip(this.checkSwitchAccountSelectors, "When (re)tweeting, click to select a single account or hold Shift to\r\nselect mult" +
|
||||||
|
"iple accounts, instead of TweetDeck\'s default behavior.");
|
||||||
|
this.checkSwitchAccountSelectors.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// groupTray
|
||||||
|
//
|
||||||
|
this.groupTray.Controls.Add(this.checkTrayHighlight);
|
||||||
|
this.groupTray.Controls.Add(this.labelTrayIcon);
|
||||||
|
this.groupTray.Controls.Add(this.comboBoxTrayType);
|
||||||
|
this.groupTray.Location = new System.Drawing.Point(9, 168);
|
||||||
|
this.groupTray.Name = "groupTray";
|
||||||
|
this.groupTray.Size = new System.Drawing.Size(183, 93);
|
||||||
|
this.groupTray.TabIndex = 1;
|
||||||
|
this.groupTray.TabStop = false;
|
||||||
|
this.groupTray.Text = "System Tray";
|
||||||
|
//
|
||||||
|
// labelTrayIcon
|
||||||
|
//
|
||||||
|
this.labelTrayIcon.AutoSize = true;
|
||||||
|
this.labelTrayIcon.Location = new System.Drawing.Point(6, 52);
|
||||||
|
this.labelTrayIcon.Margin = new System.Windows.Forms.Padding(3, 9, 3, 0);
|
||||||
|
this.labelTrayIcon.Name = "labelTrayIcon";
|
||||||
|
this.labelTrayIcon.Size = new System.Drawing.Size(52, 13);
|
||||||
|
this.labelTrayIcon.TabIndex = 1;
|
||||||
|
this.labelTrayIcon.Text = "Tray Icon";
|
||||||
|
//
|
||||||
|
// groupInterface
|
||||||
|
//
|
||||||
|
this.groupInterface.Controls.Add(this.checkSwitchAccountSelectors);
|
||||||
|
this.groupInterface.Controls.Add(this.labelZoomValue);
|
||||||
|
this.groupInterface.Controls.Add(this.trackBarZoom);
|
||||||
|
this.groupInterface.Controls.Add(this.labelZoom);
|
||||||
|
this.groupInterface.Controls.Add(this.checkSpellCheck);
|
||||||
|
this.groupInterface.Controls.Add(this.checkExpandLinks);
|
||||||
|
this.groupInterface.Location = new System.Drawing.Point(9, 9);
|
||||||
|
this.groupInterface.Name = "groupInterface";
|
||||||
|
this.groupInterface.Size = new System.Drawing.Size(183, 153);
|
||||||
|
this.groupInterface.TabIndex = 0;
|
||||||
|
this.groupInterface.TabStop = false;
|
||||||
|
this.groupInterface.Text = "User Interface";
|
||||||
|
//
|
||||||
|
// trackBarZoom
|
||||||
|
//
|
||||||
|
this.trackBarZoom.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.trackBarZoom.AutoSize = false;
|
||||||
|
this.trackBarZoom.LargeChange = 25;
|
||||||
|
this.trackBarZoom.Location = new System.Drawing.Point(6, 115);
|
||||||
|
this.trackBarZoom.Maximum = 200;
|
||||||
|
this.trackBarZoom.Minimum = 50;
|
||||||
|
this.trackBarZoom.Name = "trackBarZoom";
|
||||||
|
this.trackBarZoom.Size = new System.Drawing.Size(141, 30);
|
||||||
|
this.trackBarZoom.SmallChange = 5;
|
||||||
|
this.trackBarZoom.TabIndex = 4;
|
||||||
|
this.trackBarZoom.TickFrequency = 25;
|
||||||
|
this.trackBarZoom.Value = 100;
|
||||||
|
//
|
||||||
|
// labelZoom
|
||||||
|
//
|
||||||
|
this.labelZoom.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.labelZoom.AutoSize = true;
|
||||||
|
this.labelZoom.Location = new System.Drawing.Point(5, 99);
|
||||||
|
this.labelZoom.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelZoom.Name = "labelZoom";
|
||||||
|
this.labelZoom.Size = new System.Drawing.Size(34, 13);
|
||||||
|
this.labelZoom.TabIndex = 3;
|
||||||
|
this.labelZoom.Text = "Zoom";
|
||||||
|
//
|
||||||
|
// groupUpdates
|
||||||
|
//
|
||||||
|
this.groupUpdates.Controls.Add(this.checkUpdateNotifications);
|
||||||
|
this.groupUpdates.Controls.Add(this.btnCheckUpdates);
|
||||||
|
this.groupUpdates.Location = new System.Drawing.Point(198, 9);
|
||||||
|
this.groupUpdates.Name = "groupUpdates";
|
||||||
|
this.groupUpdates.Size = new System.Drawing.Size(183, 75);
|
||||||
|
this.groupUpdates.TabIndex = 2;
|
||||||
|
this.groupUpdates.TabStop = false;
|
||||||
|
this.groupUpdates.Text = "Updates";
|
||||||
|
//
|
||||||
|
// zoomUpdateTimer
|
||||||
|
//
|
||||||
|
this.zoomUpdateTimer.Interval = 250;
|
||||||
|
this.zoomUpdateTimer.Tick += new System.EventHandler(this.zoomUpdateTimer_Tick);
|
||||||
|
//
|
||||||
|
// TabSettingsGeneral
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.groupUpdates);
|
||||||
|
this.Controls.Add(this.groupInterface);
|
||||||
|
this.Controls.Add(this.groupTray);
|
||||||
|
this.Name = "TabSettingsGeneral";
|
||||||
|
this.Size = new System.Drawing.Size(478, 300);
|
||||||
|
this.groupTray.ResumeLayout(false);
|
||||||
|
this.groupTray.PerformLayout();
|
||||||
|
this.groupInterface.ResumeLayout(false);
|
||||||
|
this.groupInterface.PerformLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarZoom)).EndInit();
|
||||||
|
this.groupUpdates.ResumeLayout(false);
|
||||||
|
this.groupUpdates.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.CheckBox checkExpandLinks;
|
||||||
|
private System.Windows.Forms.ComboBox comboBoxTrayType;
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
private System.Windows.Forms.GroupBox groupTray;
|
||||||
|
private System.Windows.Forms.GroupBox groupInterface;
|
||||||
|
private System.Windows.Forms.Label labelTrayIcon;
|
||||||
|
private System.Windows.Forms.CheckBox checkTrayHighlight;
|
||||||
|
private System.Windows.Forms.CheckBox checkSpellCheck;
|
||||||
|
private System.Windows.Forms.GroupBox groupUpdates;
|
||||||
|
private System.Windows.Forms.CheckBox checkUpdateNotifications;
|
||||||
|
private System.Windows.Forms.Button btnCheckUpdates;
|
||||||
|
private System.Windows.Forms.Label labelZoom;
|
||||||
|
private System.Windows.Forms.Label labelZoomValue;
|
||||||
|
private System.Windows.Forms.TrackBar trackBarZoom;
|
||||||
|
private System.Windows.Forms.Timer zoomUpdateTimer;
|
||||||
|
private System.Windows.Forms.CheckBox checkSwitchAccountSelectors;
|
||||||
|
}
|
||||||
|
}
|
||||||
118
Core/Other/Settings/TabSettingsGeneral.cs
Normal file
118
Core/Other/Settings/TabSettingsGeneral.cs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Updates;
|
||||||
|
using TweetDck.Updates.Events;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings{
|
||||||
|
partial class TabSettingsGeneral : BaseTabSettings{
|
||||||
|
private readonly UpdateHandler updates;
|
||||||
|
private int updateCheckEventId = -1;
|
||||||
|
|
||||||
|
public TabSettingsGeneral(UpdateHandler updates){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.updates = updates;
|
||||||
|
this.updates.CheckFinished += updates_CheckFinished;
|
||||||
|
Disposed += (sender, args) => this.updates.CheckFinished -= updates_CheckFinished;
|
||||||
|
|
||||||
|
comboBoxTrayType.Items.Add("Disabled");
|
||||||
|
comboBoxTrayType.Items.Add("Display Icon Only");
|
||||||
|
comboBoxTrayType.Items.Add("Minimize to Tray");
|
||||||
|
comboBoxTrayType.Items.Add("Close to Tray");
|
||||||
|
comboBoxTrayType.Items.Add("Combined");
|
||||||
|
comboBoxTrayType.SelectedIndex = Math.Min(Math.Max((int)Config.TrayBehavior, 0), comboBoxTrayType.Items.Count-1);
|
||||||
|
|
||||||
|
toolTip.SetToolTip(trackBarZoom, toolTip.GetToolTip(labelZoomValue));
|
||||||
|
trackBarZoom.SetValueSafe(Config.ZoomLevel);
|
||||||
|
labelZoomValue.Text = trackBarZoom.Value+"%";
|
||||||
|
|
||||||
|
checkExpandLinks.Checked = Config.ExpandLinksOnHover;
|
||||||
|
checkSwitchAccountSelectors.Checked = Config.SwitchAccountSelectors;
|
||||||
|
checkSpellCheck.Checked = Config.EnableSpellCheck;
|
||||||
|
checkTrayHighlight.Checked = Config.EnableTrayHighlight;
|
||||||
|
|
||||||
|
checkUpdateNotifications.Checked = Config.EnableUpdateCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReady(){
|
||||||
|
checkExpandLinks.CheckedChanged += checkExpandLinks_CheckedChanged;
|
||||||
|
checkSwitchAccountSelectors.CheckedChanged += checkSwitchAccountSelectors_CheckedChanged;
|
||||||
|
checkSpellCheck.CheckedChanged += checkSpellCheck_CheckedChanged;
|
||||||
|
trackBarZoom.ValueChanged += trackBarZoom_ValueChanged;
|
||||||
|
|
||||||
|
comboBoxTrayType.SelectedIndexChanged += comboBoxTrayType_SelectedIndexChanged;
|
||||||
|
checkTrayHighlight.CheckedChanged += checkTrayHighlight_CheckedChanged;
|
||||||
|
|
||||||
|
checkUpdateNotifications.CheckedChanged += checkUpdateNotifications_CheckedChanged;
|
||||||
|
btnCheckUpdates.Click += btnCheckUpdates_Click;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnClosing(){
|
||||||
|
Config.ZoomLevel = trackBarZoom.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkExpandLinks_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.ExpandLinksOnHover = checkExpandLinks.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSwitchAccountSelectors_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.SwitchAccountSelectors = checkSwitchAccountSelectors.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSpellCheck_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.EnableSpellCheck = checkSpellCheck.Checked;
|
||||||
|
PromptRestart();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trackBarZoom_ValueChanged(object sender, EventArgs e){
|
||||||
|
if (trackBarZoom.Value % trackBarZoom.SmallChange != 0){
|
||||||
|
trackBarZoom.Value = trackBarZoom.SmallChange*(int)Math.Floor(((double)trackBarZoom.Value/trackBarZoom.SmallChange)+0.5);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
zoomUpdateTimer.Stop();
|
||||||
|
zoomUpdateTimer.Start();
|
||||||
|
labelZoomValue.Text = trackBarZoom.Value+"%";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void comboBoxTrayType_SelectedIndexChanged(object sender, EventArgs e){
|
||||||
|
Config.TrayBehavior = (TrayIcon.Behavior)comboBoxTrayType.SelectedIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkTrayHighlight_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.EnableTrayHighlight = checkTrayHighlight.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkUpdateNotifications_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.EnableUpdateCheck = checkUpdateNotifications.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCheckUpdates_Click(object sender, EventArgs e){
|
||||||
|
updateCheckEventId = updates.Check(true);
|
||||||
|
|
||||||
|
if (updateCheckEventId == -1){
|
||||||
|
MessageBox.Show("Sorry, your system is no longer supported.", "Unsupported System", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
btnCheckUpdates.Enabled = false;
|
||||||
|
updates.DismissUpdate(string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||||
|
if (e.EventId == updateCheckEventId){
|
||||||
|
btnCheckUpdates.Enabled = true;
|
||||||
|
|
||||||
|
if (!e.UpdateAvailable){
|
||||||
|
MessageBox.Show("Your version of "+Program.BrandName+" is up to date.", "No Updates Available", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zoomUpdateTimer_Tick(object sender, EventArgs e){
|
||||||
|
Config.ZoomLevel = trackBarZoom.Value;
|
||||||
|
zoomUpdateTimer.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
454
Core/Other/Settings/TabSettingsNotifications.Designer.cs
generated
Normal file
454
Core/Other/Settings/TabSettingsNotifications.Designer.cs
generated
Normal file
@@ -0,0 +1,454 @@
|
|||||||
|
namespace TweetDck.Core.Other.Settings {
|
||||||
|
partial class TabSettingsNotifications {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.groupNotificationLocation = new System.Windows.Forms.GroupBox();
|
||||||
|
this.labelEdgeDistanceValue = new System.Windows.Forms.Label();
|
||||||
|
this.labelDisplay = new System.Windows.Forms.Label();
|
||||||
|
this.comboBoxDisplay = new System.Windows.Forms.ComboBox();
|
||||||
|
this.labelEdgeDistance = new System.Windows.Forms.Label();
|
||||||
|
this.radioLocCustom = new System.Windows.Forms.RadioButton();
|
||||||
|
this.radioLocBR = new System.Windows.Forms.RadioButton();
|
||||||
|
this.radioLocBL = new System.Windows.Forms.RadioButton();
|
||||||
|
this.radioLocTR = new System.Windows.Forms.RadioButton();
|
||||||
|
this.radioLocTL = new System.Windows.Forms.RadioButton();
|
||||||
|
this.trackBarEdgeDistance = new System.Windows.Forms.TrackBar();
|
||||||
|
this.groupNotificationDuration = new System.Windows.Forms.GroupBox();
|
||||||
|
this.tableLayoutDurationButtons = new System.Windows.Forms.TableLayoutPanel();
|
||||||
|
this.btnDurationMedium = new TweetDck.Core.Controls.FlatButton();
|
||||||
|
this.btnDurationLong = new TweetDck.Core.Controls.FlatButton();
|
||||||
|
this.btnDurationShort = new TweetDck.Core.Controls.FlatButton();
|
||||||
|
this.labelDurationValue = new System.Windows.Forms.Label();
|
||||||
|
this.trackBarDuration = new System.Windows.Forms.TrackBar();
|
||||||
|
this.groupUserInterface = new System.Windows.Forms.GroupBox();
|
||||||
|
this.checkSkipOnLinkClick = new System.Windows.Forms.CheckBox();
|
||||||
|
this.checkColumnName = new System.Windows.Forms.CheckBox();
|
||||||
|
this.labelIdlePause = new System.Windows.Forms.Label();
|
||||||
|
this.comboBoxIdlePause = new System.Windows.Forms.ComboBox();
|
||||||
|
this.checkNonIntrusive = new System.Windows.Forms.CheckBox();
|
||||||
|
this.checkTimerCountDown = new System.Windows.Forms.CheckBox();
|
||||||
|
this.checkNotificationTimer = new System.Windows.Forms.CheckBox();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.groupNotificationLocation.SuspendLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).BeginInit();
|
||||||
|
this.groupNotificationDuration.SuspendLayout();
|
||||||
|
this.tableLayoutDurationButtons.SuspendLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarDuration)).BeginInit();
|
||||||
|
this.groupUserInterface.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// groupNotificationLocation
|
||||||
|
//
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.labelEdgeDistanceValue);
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.labelDisplay);
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.comboBoxDisplay);
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.labelEdgeDistance);
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.radioLocCustom);
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.radioLocBR);
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.radioLocBL);
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.radioLocTR);
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.radioLocTL);
|
||||||
|
this.groupNotificationLocation.Controls.Add(this.trackBarEdgeDistance);
|
||||||
|
this.groupNotificationLocation.Location = new System.Drawing.Point(198, 9);
|
||||||
|
this.groupNotificationLocation.Name = "groupNotificationLocation";
|
||||||
|
this.groupNotificationLocation.Size = new System.Drawing.Size(183, 282);
|
||||||
|
this.groupNotificationLocation.TabIndex = 2;
|
||||||
|
this.groupNotificationLocation.TabStop = false;
|
||||||
|
this.groupNotificationLocation.Text = "Location";
|
||||||
|
//
|
||||||
|
// labelEdgeDistanceValue
|
||||||
|
//
|
||||||
|
this.labelEdgeDistanceValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.labelEdgeDistanceValue.Location = new System.Drawing.Point(143, 217);
|
||||||
|
this.labelEdgeDistanceValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
|
this.labelEdgeDistanceValue.Name = "labelEdgeDistanceValue";
|
||||||
|
this.labelEdgeDistanceValue.Size = new System.Drawing.Size(34, 13);
|
||||||
|
this.labelEdgeDistanceValue.TabIndex = 9;
|
||||||
|
this.labelEdgeDistanceValue.Text = "0 px";
|
||||||
|
this.labelEdgeDistanceValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||||
|
//
|
||||||
|
// labelDisplay
|
||||||
|
//
|
||||||
|
this.labelDisplay.AutoSize = true;
|
||||||
|
this.labelDisplay.Location = new System.Drawing.Point(5, 144);
|
||||||
|
this.labelDisplay.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelDisplay.Name = "labelDisplay";
|
||||||
|
this.labelDisplay.Size = new System.Drawing.Size(41, 13);
|
||||||
|
this.labelDisplay.TabIndex = 5;
|
||||||
|
this.labelDisplay.Text = "Display";
|
||||||
|
//
|
||||||
|
// comboBoxDisplay
|
||||||
|
//
|
||||||
|
this.comboBoxDisplay.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.comboBoxDisplay.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
|
this.comboBoxDisplay.FormattingEnabled = true;
|
||||||
|
this.comboBoxDisplay.Location = new System.Drawing.Point(6, 160);
|
||||||
|
this.comboBoxDisplay.Name = "comboBoxDisplay";
|
||||||
|
this.comboBoxDisplay.Size = new System.Drawing.Size(171, 21);
|
||||||
|
this.comboBoxDisplay.TabIndex = 6;
|
||||||
|
//
|
||||||
|
// labelEdgeDistance
|
||||||
|
//
|
||||||
|
this.labelEdgeDistance.AutoSize = true;
|
||||||
|
this.labelEdgeDistance.Location = new System.Drawing.Point(5, 196);
|
||||||
|
this.labelEdgeDistance.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelEdgeDistance.Name = "labelEdgeDistance";
|
||||||
|
this.labelEdgeDistance.Size = new System.Drawing.Size(103, 13);
|
||||||
|
this.labelEdgeDistance.TabIndex = 7;
|
||||||
|
this.labelEdgeDistance.Text = "Distance From Edge";
|
||||||
|
//
|
||||||
|
// radioLocCustom
|
||||||
|
//
|
||||||
|
this.radioLocCustom.AutoSize = true;
|
||||||
|
this.radioLocCustom.Location = new System.Drawing.Point(8, 112);
|
||||||
|
this.radioLocCustom.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
|
this.radioLocCustom.Name = "radioLocCustom";
|
||||||
|
this.radioLocCustom.Size = new System.Drawing.Size(60, 17);
|
||||||
|
this.radioLocCustom.TabIndex = 4;
|
||||||
|
this.radioLocCustom.TabStop = true;
|
||||||
|
this.radioLocCustom.Text = "Custom";
|
||||||
|
this.toolTip.SetToolTip(this.radioLocCustom, "Drag the notification window to the desired location.");
|
||||||
|
this.radioLocCustom.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// radioLocBR
|
||||||
|
//
|
||||||
|
this.radioLocBR.AutoSize = true;
|
||||||
|
this.radioLocBR.Location = new System.Drawing.Point(8, 89);
|
||||||
|
this.radioLocBR.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
|
this.radioLocBR.Name = "radioLocBR";
|
||||||
|
this.radioLocBR.Size = new System.Drawing.Size(86, 17);
|
||||||
|
this.radioLocBR.TabIndex = 3;
|
||||||
|
this.radioLocBR.TabStop = true;
|
||||||
|
this.radioLocBR.Text = "Bottom Right";
|
||||||
|
this.radioLocBR.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// radioLocBL
|
||||||
|
//
|
||||||
|
this.radioLocBL.AutoSize = true;
|
||||||
|
this.radioLocBL.Location = new System.Drawing.Point(8, 66);
|
||||||
|
this.radioLocBL.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
|
this.radioLocBL.Name = "radioLocBL";
|
||||||
|
this.radioLocBL.Size = new System.Drawing.Size(79, 17);
|
||||||
|
this.radioLocBL.TabIndex = 2;
|
||||||
|
this.radioLocBL.TabStop = true;
|
||||||
|
this.radioLocBL.Text = "Bottom Left";
|
||||||
|
this.radioLocBL.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// radioLocTR
|
||||||
|
//
|
||||||
|
this.radioLocTR.AutoSize = true;
|
||||||
|
this.radioLocTR.Location = new System.Drawing.Point(8, 43);
|
||||||
|
this.radioLocTR.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
|
this.radioLocTR.Name = "radioLocTR";
|
||||||
|
this.radioLocTR.Size = new System.Drawing.Size(72, 17);
|
||||||
|
this.radioLocTR.TabIndex = 1;
|
||||||
|
this.radioLocTR.TabStop = true;
|
||||||
|
this.radioLocTR.Text = "Top Right";
|
||||||
|
this.radioLocTR.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// radioLocTL
|
||||||
|
//
|
||||||
|
this.radioLocTL.AutoSize = true;
|
||||||
|
this.radioLocTL.Location = new System.Drawing.Point(8, 20);
|
||||||
|
this.radioLocTL.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
|
||||||
|
this.radioLocTL.Name = "radioLocTL";
|
||||||
|
this.radioLocTL.Size = new System.Drawing.Size(65, 17);
|
||||||
|
this.radioLocTL.TabIndex = 0;
|
||||||
|
this.radioLocTL.TabStop = true;
|
||||||
|
this.radioLocTL.Text = "Top Left";
|
||||||
|
this.radioLocTL.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// trackBarEdgeDistance
|
||||||
|
//
|
||||||
|
this.trackBarEdgeDistance.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.trackBarEdgeDistance.AutoSize = false;
|
||||||
|
this.trackBarEdgeDistance.LargeChange = 8;
|
||||||
|
this.trackBarEdgeDistance.Location = new System.Drawing.Point(8, 212);
|
||||||
|
this.trackBarEdgeDistance.Maximum = 40;
|
||||||
|
this.trackBarEdgeDistance.Minimum = 8;
|
||||||
|
this.trackBarEdgeDistance.Name = "trackBarEdgeDistance";
|
||||||
|
this.trackBarEdgeDistance.Size = new System.Drawing.Size(141, 30);
|
||||||
|
this.trackBarEdgeDistance.SmallChange = 2;
|
||||||
|
this.trackBarEdgeDistance.TabIndex = 8;
|
||||||
|
this.trackBarEdgeDistance.TickFrequency = 4;
|
||||||
|
this.trackBarEdgeDistance.Value = 8;
|
||||||
|
//
|
||||||
|
// groupNotificationDuration
|
||||||
|
//
|
||||||
|
this.groupNotificationDuration.Controls.Add(this.tableLayoutDurationButtons);
|
||||||
|
this.groupNotificationDuration.Controls.Add(this.labelDurationValue);
|
||||||
|
this.groupNotificationDuration.Controls.Add(this.trackBarDuration);
|
||||||
|
this.groupNotificationDuration.Location = new System.Drawing.Point(9, 202);
|
||||||
|
this.groupNotificationDuration.Name = "groupNotificationDuration";
|
||||||
|
this.groupNotificationDuration.Size = new System.Drawing.Size(183, 89);
|
||||||
|
this.groupNotificationDuration.TabIndex = 1;
|
||||||
|
this.groupNotificationDuration.TabStop = false;
|
||||||
|
this.groupNotificationDuration.Text = "Duration";
|
||||||
|
//
|
||||||
|
// tableLayoutDurationButtons
|
||||||
|
//
|
||||||
|
this.tableLayoutDurationButtons.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.tableLayoutDurationButtons.ColumnCount = 3;
|
||||||
|
this.tableLayoutDurationButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 32F));
|
||||||
|
this.tableLayoutDurationButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 36F));
|
||||||
|
this.tableLayoutDurationButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 32F));
|
||||||
|
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationMedium, 0, 0);
|
||||||
|
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationLong, 1, 0);
|
||||||
|
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationShort, 0, 0);
|
||||||
|
this.tableLayoutDurationButtons.Location = new System.Drawing.Point(6, 56);
|
||||||
|
this.tableLayoutDurationButtons.Name = "tableLayoutDurationButtons";
|
||||||
|
this.tableLayoutDurationButtons.RowCount = 1;
|
||||||
|
this.tableLayoutDurationButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
|
this.tableLayoutDurationButtons.Size = new System.Drawing.Size(171, 27);
|
||||||
|
this.tableLayoutDurationButtons.TabIndex = 2;
|
||||||
|
//
|
||||||
|
// btnDurationMedium
|
||||||
|
//
|
||||||
|
this.btnDurationMedium.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.btnDurationMedium.FlatAppearance.BorderColor = System.Drawing.Color.Gray;
|
||||||
|
this.btnDurationMedium.FlatAppearance.MouseDownBackColor = System.Drawing.SystemColors.ControlLight;
|
||||||
|
this.btnDurationMedium.FlatAppearance.MouseOverBackColor = System.Drawing.Color.White;
|
||||||
|
this.btnDurationMedium.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.btnDurationMedium.Location = new System.Drawing.Point(55, 1);
|
||||||
|
this.btnDurationMedium.Margin = new System.Windows.Forms.Padding(1);
|
||||||
|
this.btnDurationMedium.Name = "btnDurationMedium";
|
||||||
|
this.btnDurationMedium.Size = new System.Drawing.Size(59, 25);
|
||||||
|
this.btnDurationMedium.TabIndex = 1;
|
||||||
|
this.btnDurationMedium.Text = "Medium";
|
||||||
|
this.btnDurationMedium.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnDurationLong
|
||||||
|
//
|
||||||
|
this.btnDurationLong.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.btnDurationLong.FlatAppearance.BorderColor = System.Drawing.Color.Gray;
|
||||||
|
this.btnDurationLong.FlatAppearance.MouseDownBackColor = System.Drawing.SystemColors.ControlLight;
|
||||||
|
this.btnDurationLong.FlatAppearance.MouseOverBackColor = System.Drawing.Color.White;
|
||||||
|
this.btnDurationLong.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.btnDurationLong.Location = new System.Drawing.Point(116, 1);
|
||||||
|
this.btnDurationLong.Margin = new System.Windows.Forms.Padding(1);
|
||||||
|
this.btnDurationLong.Name = "btnDurationLong";
|
||||||
|
this.btnDurationLong.Size = new System.Drawing.Size(54, 25);
|
||||||
|
this.btnDurationLong.TabIndex = 2;
|
||||||
|
this.btnDurationLong.Text = "Long";
|
||||||
|
this.btnDurationLong.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnDurationShort
|
||||||
|
//
|
||||||
|
this.btnDurationShort.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.btnDurationShort.FlatAppearance.BorderColor = System.Drawing.Color.Gray;
|
||||||
|
this.btnDurationShort.FlatAppearance.MouseDownBackColor = System.Drawing.SystemColors.ControlLight;
|
||||||
|
this.btnDurationShort.FlatAppearance.MouseOverBackColor = System.Drawing.Color.White;
|
||||||
|
this.btnDurationShort.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.btnDurationShort.Location = new System.Drawing.Point(1, 1);
|
||||||
|
this.btnDurationShort.Margin = new System.Windows.Forms.Padding(1);
|
||||||
|
this.btnDurationShort.Name = "btnDurationShort";
|
||||||
|
this.btnDurationShort.Size = new System.Drawing.Size(52, 25);
|
||||||
|
this.btnDurationShort.TabIndex = 0;
|
||||||
|
this.btnDurationShort.Text = "Short";
|
||||||
|
this.btnDurationShort.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelDurationValue
|
||||||
|
//
|
||||||
|
this.labelDurationValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.labelDurationValue.BackColor = System.Drawing.Color.Transparent;
|
||||||
|
this.labelDurationValue.Location = new System.Drawing.Point(129, 20);
|
||||||
|
this.labelDurationValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
|
this.labelDurationValue.Name = "labelDurationValue";
|
||||||
|
this.labelDurationValue.Size = new System.Drawing.Size(48, 13);
|
||||||
|
this.labelDurationValue.TabIndex = 1;
|
||||||
|
this.labelDurationValue.Text = "0 ms/c";
|
||||||
|
this.labelDurationValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||||
|
this.toolTip.SetToolTip(this.labelDurationValue, "Milliseconds per character.");
|
||||||
|
//
|
||||||
|
// trackBarDuration
|
||||||
|
//
|
||||||
|
this.trackBarDuration.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.trackBarDuration.AutoSize = false;
|
||||||
|
this.trackBarDuration.Location = new System.Drawing.Point(6, 19);
|
||||||
|
this.trackBarDuration.Maximum = 60;
|
||||||
|
this.trackBarDuration.Minimum = 10;
|
||||||
|
this.trackBarDuration.Name = "trackBarDuration";
|
||||||
|
this.trackBarDuration.Size = new System.Drawing.Size(128, 30);
|
||||||
|
this.trackBarDuration.TabIndex = 0;
|
||||||
|
this.trackBarDuration.TickFrequency = 5;
|
||||||
|
this.trackBarDuration.Value = 25;
|
||||||
|
//
|
||||||
|
// groupUserInterface
|
||||||
|
//
|
||||||
|
this.groupUserInterface.Controls.Add(this.checkSkipOnLinkClick);
|
||||||
|
this.groupUserInterface.Controls.Add(this.checkColumnName);
|
||||||
|
this.groupUserInterface.Controls.Add(this.labelIdlePause);
|
||||||
|
this.groupUserInterface.Controls.Add(this.comboBoxIdlePause);
|
||||||
|
this.groupUserInterface.Controls.Add(this.checkNonIntrusive);
|
||||||
|
this.groupUserInterface.Controls.Add(this.checkTimerCountDown);
|
||||||
|
this.groupUserInterface.Controls.Add(this.checkNotificationTimer);
|
||||||
|
this.groupUserInterface.Location = new System.Drawing.Point(9, 9);
|
||||||
|
this.groupUserInterface.Name = "groupUserInterface";
|
||||||
|
this.groupUserInterface.Size = new System.Drawing.Size(183, 187);
|
||||||
|
this.groupUserInterface.TabIndex = 0;
|
||||||
|
this.groupUserInterface.TabStop = false;
|
||||||
|
this.groupUserInterface.Text = "General";
|
||||||
|
//
|
||||||
|
// checkSkipOnLinkClick
|
||||||
|
//
|
||||||
|
this.checkSkipOnLinkClick.AutoSize = true;
|
||||||
|
this.checkSkipOnLinkClick.Location = new System.Drawing.Point(9, 90);
|
||||||
|
this.checkSkipOnLinkClick.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkSkipOnLinkClick.Name = "checkSkipOnLinkClick";
|
||||||
|
this.checkSkipOnLinkClick.Size = new System.Drawing.Size(113, 17);
|
||||||
|
this.checkSkipOnLinkClick.TabIndex = 3;
|
||||||
|
this.checkSkipOnLinkClick.Text = "Skip On Link Click";
|
||||||
|
this.toolTip.SetToolTip(this.checkSkipOnLinkClick, "Skips current notification when a link\r\ninside the notification is clicked.");
|
||||||
|
this.checkSkipOnLinkClick.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// checkColumnName
|
||||||
|
//
|
||||||
|
this.checkColumnName.AutoSize = true;
|
||||||
|
this.checkColumnName.Location = new System.Drawing.Point(9, 21);
|
||||||
|
this.checkColumnName.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
|
this.checkColumnName.Name = "checkColumnName";
|
||||||
|
this.checkColumnName.Size = new System.Drawing.Size(129, 17);
|
||||||
|
this.checkColumnName.TabIndex = 0;
|
||||||
|
this.checkColumnName.Text = "Display Column Name";
|
||||||
|
this.toolTip.SetToolTip(this.checkColumnName, "Shows column name each notification originated\r\nfrom in the notification window t" +
|
||||||
|
"itle.");
|
||||||
|
this.checkColumnName.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelIdlePause
|
||||||
|
//
|
||||||
|
this.labelIdlePause.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.labelIdlePause.AutoSize = true;
|
||||||
|
this.labelIdlePause.Location = new System.Drawing.Point(5, 141);
|
||||||
|
this.labelIdlePause.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelIdlePause.Name = "labelIdlePause";
|
||||||
|
this.labelIdlePause.Size = new System.Drawing.Size(89, 13);
|
||||||
|
this.labelIdlePause.TabIndex = 3;
|
||||||
|
this.labelIdlePause.Text = "Pause When Idle";
|
||||||
|
//
|
||||||
|
// comboBoxIdlePause
|
||||||
|
//
|
||||||
|
this.comboBoxIdlePause.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.comboBoxIdlePause.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
|
this.comboBoxIdlePause.FormattingEnabled = true;
|
||||||
|
this.comboBoxIdlePause.Location = new System.Drawing.Point(6, 157);
|
||||||
|
this.comboBoxIdlePause.Name = "comboBoxIdlePause";
|
||||||
|
this.comboBoxIdlePause.Size = new System.Drawing.Size(171, 21);
|
||||||
|
this.comboBoxIdlePause.TabIndex = 4;
|
||||||
|
this.toolTip.SetToolTip(this.comboBoxIdlePause, "Pauses new notifications after going idle for a set amount of time.");
|
||||||
|
//
|
||||||
|
// checkNonIntrusive
|
||||||
|
//
|
||||||
|
this.checkNonIntrusive.AutoSize = true;
|
||||||
|
this.checkNonIntrusive.Location = new System.Drawing.Point(9, 113);
|
||||||
|
this.checkNonIntrusive.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkNonIntrusive.Name = "checkNonIntrusive";
|
||||||
|
this.checkNonIntrusive.Size = new System.Drawing.Size(128, 17);
|
||||||
|
this.checkNonIntrusive.TabIndex = 4;
|
||||||
|
this.checkNonIntrusive.Text = "Non-Intrusive Popups";
|
||||||
|
this.toolTip.SetToolTip(this.checkNonIntrusive, "When not idle and the cursor is within the notification window area,\r\nit will be " +
|
||||||
|
"delayed until the cursor moves away to prevent accidental clicks.");
|
||||||
|
this.checkNonIntrusive.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// checkTimerCountDown
|
||||||
|
//
|
||||||
|
this.checkTimerCountDown.AutoSize = true;
|
||||||
|
this.checkTimerCountDown.Location = new System.Drawing.Point(9, 67);
|
||||||
|
this.checkTimerCountDown.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkTimerCountDown.Name = "checkTimerCountDown";
|
||||||
|
this.checkTimerCountDown.Size = new System.Drawing.Size(119, 17);
|
||||||
|
this.checkTimerCountDown.TabIndex = 2;
|
||||||
|
this.checkTimerCountDown.Text = "Timer Counts Down";
|
||||||
|
this.toolTip.SetToolTip(this.checkTimerCountDown, "The notification timer counts down instead of up.");
|
||||||
|
this.checkTimerCountDown.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// checkNotificationTimer
|
||||||
|
//
|
||||||
|
this.checkNotificationTimer.AutoSize = true;
|
||||||
|
this.checkNotificationTimer.Location = new System.Drawing.Point(9, 44);
|
||||||
|
this.checkNotificationTimer.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkNotificationTimer.Name = "checkNotificationTimer";
|
||||||
|
this.checkNotificationTimer.Size = new System.Drawing.Size(145, 17);
|
||||||
|
this.checkNotificationTimer.TabIndex = 1;
|
||||||
|
this.checkNotificationTimer.Text = "Display Notification Timer";
|
||||||
|
this.checkNotificationTimer.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// TabSettingsNotifications
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.groupUserInterface);
|
||||||
|
this.Controls.Add(this.groupNotificationDuration);
|
||||||
|
this.Controls.Add(this.groupNotificationLocation);
|
||||||
|
this.Name = "TabSettingsNotifications";
|
||||||
|
this.Size = new System.Drawing.Size(478, 300);
|
||||||
|
this.ParentChanged += new System.EventHandler(this.TabSettingsNotifications_ParentChanged);
|
||||||
|
this.groupNotificationLocation.ResumeLayout(false);
|
||||||
|
this.groupNotificationLocation.PerformLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).EndInit();
|
||||||
|
this.groupNotificationDuration.ResumeLayout(false);
|
||||||
|
this.tableLayoutDurationButtons.ResumeLayout(false);
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarDuration)).EndInit();
|
||||||
|
this.groupUserInterface.ResumeLayout(false);
|
||||||
|
this.groupUserInterface.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.GroupBox groupNotificationLocation;
|
||||||
|
private System.Windows.Forms.Label labelDisplay;
|
||||||
|
private System.Windows.Forms.ComboBox comboBoxDisplay;
|
||||||
|
private System.Windows.Forms.Label labelEdgeDistance;
|
||||||
|
private System.Windows.Forms.TrackBar trackBarEdgeDistance;
|
||||||
|
private System.Windows.Forms.RadioButton radioLocCustom;
|
||||||
|
private System.Windows.Forms.RadioButton radioLocBR;
|
||||||
|
private System.Windows.Forms.RadioButton radioLocBL;
|
||||||
|
private System.Windows.Forms.RadioButton radioLocTR;
|
||||||
|
private System.Windows.Forms.RadioButton radioLocTL;
|
||||||
|
private System.Windows.Forms.GroupBox groupNotificationDuration;
|
||||||
|
private System.Windows.Forms.GroupBox groupUserInterface;
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
private System.Windows.Forms.Label labelEdgeDistanceValue;
|
||||||
|
private System.Windows.Forms.Label labelDurationValue;
|
||||||
|
private System.Windows.Forms.TrackBar trackBarDuration;
|
||||||
|
private System.Windows.Forms.TableLayoutPanel tableLayoutDurationButtons;
|
||||||
|
private TweetDck.Core.Controls.FlatButton btnDurationMedium;
|
||||||
|
private TweetDck.Core.Controls.FlatButton btnDurationLong;
|
||||||
|
private TweetDck.Core.Controls.FlatButton btnDurationShort;
|
||||||
|
private System.Windows.Forms.CheckBox checkNonIntrusive;
|
||||||
|
private System.Windows.Forms.Label labelIdlePause;
|
||||||
|
private System.Windows.Forms.ComboBox comboBoxIdlePause;
|
||||||
|
private System.Windows.Forms.CheckBox checkColumnName;
|
||||||
|
private System.Windows.Forms.CheckBox checkSkipOnLinkClick;
|
||||||
|
private System.Windows.Forms.CheckBox checkTimerCountDown;
|
||||||
|
private System.Windows.Forms.CheckBox checkNotificationTimer;
|
||||||
|
}
|
||||||
|
}
|
||||||
201
Core/Other/Settings/TabSettingsNotifications.cs
Normal file
201
Core/Other/Settings/TabSettingsNotifications.cs
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Notification;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings{
|
||||||
|
partial class TabSettingsNotifications : BaseTabSettings{
|
||||||
|
private static readonly int[] IdlePauseSeconds = { 0, 30, 60, 120, 300 };
|
||||||
|
|
||||||
|
private readonly FormNotificationMain notification;
|
||||||
|
|
||||||
|
public TabSettingsNotifications(FormNotificationMain notification){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.notification = notification;
|
||||||
|
this.notification.CanMoveWindow = () => radioLocCustom.Checked;
|
||||||
|
|
||||||
|
this.notification.Move += (sender, args) => {
|
||||||
|
if (radioLocCustom.Checked && this.notification.Location != ControlExtensions.InvisibleLocation){
|
||||||
|
Config.CustomNotificationPosition = this.notification.Location;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.notification.Initialized += (sender, args) => {
|
||||||
|
this.InvokeAsyncSafe(() => this.notification.ShowNotificationForSettings(true));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.notification.Activated += notification_Activated;
|
||||||
|
this.notification.Show();
|
||||||
|
|
||||||
|
switch(Config.NotificationPosition){
|
||||||
|
case TweetNotification.Position.TopLeft: radioLocTL.Checked = true; break;
|
||||||
|
case TweetNotification.Position.TopRight: radioLocTR.Checked = true; break;
|
||||||
|
case TweetNotification.Position.BottomLeft: radioLocBL.Checked = true; break;
|
||||||
|
case TweetNotification.Position.BottomRight: radioLocBR.Checked = true; break;
|
||||||
|
case TweetNotification.Position.Custom: radioLocCustom.Checked = true; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = !radioLocCustom.Checked;
|
||||||
|
|
||||||
|
toolTip.SetToolTip(trackBarDuration, toolTip.GetToolTip(labelDurationValue));
|
||||||
|
trackBarDuration.SetValueSafe(Config.NotificationDurationValue);
|
||||||
|
labelDurationValue.Text = Config.NotificationDurationValue+" ms/c";
|
||||||
|
|
||||||
|
comboBoxIdlePause.Items.Add("Disabled");
|
||||||
|
comboBoxIdlePause.Items.Add("30 seconds");
|
||||||
|
comboBoxIdlePause.Items.Add("1 minute");
|
||||||
|
comboBoxIdlePause.Items.Add("2 minutes");
|
||||||
|
comboBoxIdlePause.Items.Add("5 minutes");
|
||||||
|
comboBoxIdlePause.SelectedIndex = Math.Max(0, Array.FindIndex(IdlePauseSeconds, val => val == Config.NotificationIdlePauseSeconds));
|
||||||
|
|
||||||
|
comboBoxDisplay.Items.Add("(Same As "+Program.BrandName+")");
|
||||||
|
|
||||||
|
foreach(Screen screen in Screen.AllScreens){
|
||||||
|
comboBoxDisplay.Items.Add(screen.DeviceName+" ("+screen.Bounds.Width+"x"+screen.Bounds.Height+")");
|
||||||
|
}
|
||||||
|
|
||||||
|
comboBoxDisplay.SelectedIndex = Math.Min(comboBoxDisplay.Items.Count-1, Config.NotificationDisplay);
|
||||||
|
|
||||||
|
checkColumnName.Checked = Config.DisplayNotificationColumn;
|
||||||
|
checkNotificationTimer.Checked = Config.DisplayNotificationTimer;
|
||||||
|
checkTimerCountDown.Enabled = checkNotificationTimer.Checked;
|
||||||
|
checkTimerCountDown.Checked = Config.NotificationTimerCountDown;
|
||||||
|
checkSkipOnLinkClick.Checked = Config.NotificationSkipOnLinkClick;
|
||||||
|
checkNonIntrusive.Checked = Config.NotificationNonIntrusiveMode;
|
||||||
|
|
||||||
|
trackBarEdgeDistance.SetValueSafe(Config.NotificationEdgeDistance);
|
||||||
|
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value.ToString(CultureInfo.InvariantCulture)+" px";
|
||||||
|
|
||||||
|
Disposed += (sender, args) => this.notification.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReady(){
|
||||||
|
radioLocTL.CheckedChanged += radioLoc_CheckedChanged;
|
||||||
|
radioLocTR.CheckedChanged += radioLoc_CheckedChanged;
|
||||||
|
radioLocBL.CheckedChanged += radioLoc_CheckedChanged;
|
||||||
|
radioLocBR.CheckedChanged += radioLoc_CheckedChanged;
|
||||||
|
radioLocCustom.Click += radioLocCustom_Click;
|
||||||
|
|
||||||
|
trackBarDuration.ValueChanged += trackBarDuration_ValueChanged;
|
||||||
|
btnDurationShort.Click += btnDurationShort_Click;
|
||||||
|
btnDurationMedium.Click += btnDurationMedium_Click;
|
||||||
|
btnDurationLong.Click += btnDurationLong_Click;
|
||||||
|
|
||||||
|
checkColumnName.CheckedChanged += checkColumnName_CheckedChanged;
|
||||||
|
checkNotificationTimer.CheckedChanged += checkNotificationTimer_CheckedChanged;
|
||||||
|
checkTimerCountDown.CheckedChanged += checkTimerCountDown_CheckedChanged;
|
||||||
|
checkSkipOnLinkClick.CheckedChanged += checkSkipOnLinkClick_CheckedChanged;
|
||||||
|
checkNonIntrusive.CheckedChanged += checkNonIntrusive_CheckedChanged;
|
||||||
|
|
||||||
|
comboBoxIdlePause.SelectedValueChanged += comboBoxIdlePause_SelectedValueChanged;
|
||||||
|
|
||||||
|
comboBoxDisplay.SelectedValueChanged += comboBoxDisplay_SelectedValueChanged;
|
||||||
|
trackBarEdgeDistance.ValueChanged += trackBarEdgeDistance_ValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TabSettingsNotifications_ParentChanged(object sender, EventArgs e){
|
||||||
|
if (Parent == null){
|
||||||
|
notification.HideNotification(false);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
notification.ShowNotificationForSettings(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notification_Activated(object sender, EventArgs e){
|
||||||
|
notification.Hide();
|
||||||
|
notification.Activated -= notification_Activated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void radioLoc_CheckedChanged(object sender, EventArgs e){
|
||||||
|
if (radioLocTL.Checked)Config.NotificationPosition = TweetNotification.Position.TopLeft;
|
||||||
|
else if (radioLocTR.Checked)Config.NotificationPosition = TweetNotification.Position.TopRight;
|
||||||
|
else if (radioLocBL.Checked)Config.NotificationPosition = TweetNotification.Position.BottomLeft;
|
||||||
|
else if (radioLocBR.Checked)Config.NotificationPosition = TweetNotification.Position.BottomRight;
|
||||||
|
|
||||||
|
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = true;
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void radioLocCustom_Click(object sender, EventArgs e){
|
||||||
|
if (!Config.IsCustomNotificationPositionSet){
|
||||||
|
Config.CustomNotificationPosition = notification.Location;
|
||||||
|
}
|
||||||
|
|
||||||
|
Config.NotificationPosition = TweetNotification.Position.Custom;
|
||||||
|
|
||||||
|
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = false;
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
|
||||||
|
if (notification.IsFullyOutsideView() && MessageBox.Show("The notification seems to be outside of view, would you like to reset its position?", "Notification is outside view", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
|
||||||
|
Config.NotificationPosition = TweetNotification.Position.TopRight;
|
||||||
|
notification.MoveToVisibleLocation();
|
||||||
|
|
||||||
|
Config.CustomNotificationPosition = notification.Location;
|
||||||
|
|
||||||
|
Config.NotificationPosition = TweetNotification.Position.Custom;
|
||||||
|
notification.MoveToVisibleLocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trackBarDuration_ValueChanged(object sender, EventArgs e){
|
||||||
|
Config.NotificationDurationValue = trackBarDuration.Value;
|
||||||
|
labelDurationValue.Text = Config.NotificationDurationValue+" ms/c";
|
||||||
|
|
||||||
|
notification.ShowNotificationForSettings(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnDurationShort_Click(object sender, EventArgs e){
|
||||||
|
trackBarDuration.Value = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnDurationMedium_Click(object sender, EventArgs e){
|
||||||
|
trackBarDuration.Value = 25;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnDurationLong_Click(object sender, EventArgs e){
|
||||||
|
trackBarDuration.Value = 35;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkColumnName_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.DisplayNotificationColumn = checkColumnName.Checked;
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNotificationTimer_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.DisplayNotificationTimer = checkNotificationTimer.Checked;
|
||||||
|
checkTimerCountDown.Enabled = checkNotificationTimer.Checked;
|
||||||
|
notification.ShowNotificationForSettings(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkTimerCountDown_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.NotificationTimerCountDown = checkTimerCountDown.Checked;
|
||||||
|
notification.ShowNotificationForSettings(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSkipOnLinkClick_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.NotificationSkipOnLinkClick = checkSkipOnLinkClick.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNonIntrusive_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.NotificationNonIntrusiveMode = checkNonIntrusive.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void comboBoxIdlePause_SelectedValueChanged(object sender, EventArgs e){
|
||||||
|
Config.NotificationIdlePauseSeconds = IdlePauseSeconds[comboBoxIdlePause.SelectedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void comboBoxDisplay_SelectedValueChanged(object sender, EventArgs e){
|
||||||
|
Config.NotificationDisplay = comboBoxDisplay.SelectedIndex;
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trackBarEdgeDistance_ValueChanged(object sender, EventArgs e){
|
||||||
|
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value.ToString(CultureInfo.InvariantCulture)+" px";
|
||||||
|
Config.NotificationEdgeDistance = trackBarEdgeDistance.Value;
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
111
Core/Other/Settings/TabSettingsSounds.Designer.cs
generated
Normal file
111
Core/Other/Settings/TabSettingsSounds.Designer.cs
generated
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
namespace TweetDck.Core.Other.Settings {
|
||||||
|
partial class TabSettingsSounds {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.groupCustomSound = new System.Windows.Forms.GroupBox();
|
||||||
|
this.btnPlaySound = new System.Windows.Forms.Button();
|
||||||
|
this.btnResetSound = new System.Windows.Forms.Button();
|
||||||
|
this.btnBrowseSound = new System.Windows.Forms.Button();
|
||||||
|
this.tbCustomSound = new System.Windows.Forms.TextBox();
|
||||||
|
this.groupCustomSound.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// groupCustomSound
|
||||||
|
//
|
||||||
|
this.groupCustomSound.Controls.Add(this.btnPlaySound);
|
||||||
|
this.groupCustomSound.Controls.Add(this.btnResetSound);
|
||||||
|
this.groupCustomSound.Controls.Add(this.btnBrowseSound);
|
||||||
|
this.groupCustomSound.Controls.Add(this.tbCustomSound);
|
||||||
|
this.groupCustomSound.Location = new System.Drawing.Point(9, 9);
|
||||||
|
this.groupCustomSound.Name = "groupCustomSound";
|
||||||
|
this.groupCustomSound.Size = new System.Drawing.Size(372, 75);
|
||||||
|
this.groupCustomSound.TabIndex = 0;
|
||||||
|
this.groupCustomSound.TabStop = false;
|
||||||
|
this.groupCustomSound.Text = "Custom Sound Notification";
|
||||||
|
//
|
||||||
|
// btnPlaySound
|
||||||
|
//
|
||||||
|
this.btnPlaySound.AutoSize = true;
|
||||||
|
this.btnPlaySound.Location = new System.Drawing.Point(250, 45);
|
||||||
|
this.btnPlaySound.Name = "btnPlaySound";
|
||||||
|
this.btnPlaySound.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnPlaySound.Size = new System.Drawing.Size(43, 23);
|
||||||
|
this.btnPlaySound.TabIndex = 2;
|
||||||
|
this.btnPlaySound.Text = "Play";
|
||||||
|
this.btnPlaySound.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnResetSound
|
||||||
|
//
|
||||||
|
this.btnResetSound.AutoSize = true;
|
||||||
|
this.btnResetSound.Location = new System.Drawing.Point(6, 45);
|
||||||
|
this.btnResetSound.Name = "btnResetSound";
|
||||||
|
this.btnResetSound.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnResetSound.Size = new System.Drawing.Size(51, 23);
|
||||||
|
this.btnResetSound.TabIndex = 3;
|
||||||
|
this.btnResetSound.Text = "Reset";
|
||||||
|
this.btnResetSound.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnBrowseSound
|
||||||
|
//
|
||||||
|
this.btnBrowseSound.AutoSize = true;
|
||||||
|
this.btnBrowseSound.Location = new System.Drawing.Point(299, 45);
|
||||||
|
this.btnBrowseSound.Name = "btnBrowseSound";
|
||||||
|
this.btnBrowseSound.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnBrowseSound.Size = new System.Drawing.Size(67, 23);
|
||||||
|
this.btnBrowseSound.TabIndex = 1;
|
||||||
|
this.btnBrowseSound.Text = "Browse...";
|
||||||
|
this.btnBrowseSound.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// tbCustomSound
|
||||||
|
//
|
||||||
|
this.tbCustomSound.Location = new System.Drawing.Point(6, 19);
|
||||||
|
this.tbCustomSound.Name = "tbCustomSound";
|
||||||
|
this.tbCustomSound.Size = new System.Drawing.Size(360, 20);
|
||||||
|
this.tbCustomSound.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// TabSettingsSounds
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.groupCustomSound);
|
||||||
|
this.Name = "TabSettingsSounds";
|
||||||
|
this.Size = new System.Drawing.Size(478, 300);
|
||||||
|
this.groupCustomSound.ResumeLayout(false);
|
||||||
|
this.groupCustomSound.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
private System.Windows.Forms.GroupBox groupCustomSound;
|
||||||
|
private System.Windows.Forms.Button btnResetSound;
|
||||||
|
private System.Windows.Forms.Button btnBrowseSound;
|
||||||
|
private System.Windows.Forms.TextBox tbCustomSound;
|
||||||
|
private System.Windows.Forms.Button btnPlaySound;
|
||||||
|
}
|
||||||
|
}
|
||||||
67
Core/Other/Settings/TabSettingsSounds.cs
Normal file
67
Core/Other/Settings/TabSettingsSounds.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Notification;
|
||||||
|
using TweetDck.Core.Notification.Sound;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other.Settings{
|
||||||
|
partial class TabSettingsSounds : BaseTabSettings{
|
||||||
|
private readonly ISoundNotificationPlayer soundNotification;
|
||||||
|
|
||||||
|
public TabSettingsSounds(){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
soundNotification = SoundNotification.New();
|
||||||
|
soundNotification.PlaybackError += sound_PlaybackError;
|
||||||
|
|
||||||
|
tbCustomSound.Text = Config.NotificationSoundPath;
|
||||||
|
tbCustomSound_TextChanged(tbCustomSound, new EventArgs());
|
||||||
|
|
||||||
|
Disposed += (sender, args) => soundNotification.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReady(){
|
||||||
|
tbCustomSound.TextChanged += tbCustomSound_TextChanged;
|
||||||
|
btnPlaySound.Click += btnPlaySound_Click;
|
||||||
|
btnBrowseSound.Click += btnBrowseSound_Click;
|
||||||
|
btnResetSound.Click += btnResetSound_Click;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnClosing(){
|
||||||
|
Config.NotificationSoundPath = tbCustomSound.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tbCustomSound_TextChanged(object sender, EventArgs e){
|
||||||
|
bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text);
|
||||||
|
tbCustomSound.ForeColor = isEmpty || File.Exists(tbCustomSound.Text) ? SystemColors.WindowText : Color.Maroon;
|
||||||
|
btnPlaySound.Enabled = !isEmpty;
|
||||||
|
btnResetSound.Enabled = !isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnPlaySound_Click(object sender, EventArgs e){
|
||||||
|
soundNotification.Play(tbCustomSound.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sound_PlaybackError(object sender, PlaybackErrorEventArgs e){
|
||||||
|
MessageBox.Show("Could not play custom notification sound."+Environment.NewLine+e.Message, "Notification Sound Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnBrowseSound_Click(object sender, EventArgs e){
|
||||||
|
using(OpenFileDialog dialog = new OpenFileDialog{
|
||||||
|
AutoUpgradeEnabled = true,
|
||||||
|
DereferenceLinks = true,
|
||||||
|
Title = "Custom Notification Sound",
|
||||||
|
Filter = "Sound file ("+soundNotification.SupportedFormats+")|"+soundNotification.SupportedFormats+"|All files (*.*)|*.*"
|
||||||
|
}){
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK){
|
||||||
|
tbCustomSound.Text = dialog.FileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnResetSound_Click(object sender, EventArgs e){
|
||||||
|
tbCustomSound.Text = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
Core/TrayIcon.Designer.cs
generated
50
Core/TrayIcon.Designer.cs
generated
@@ -25,65 +25,17 @@
|
|||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
||||||
this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
|
|
||||||
this.restoreToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.muteNotificationsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.closeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.contextMenu.SuspendLayout();
|
|
||||||
//
|
//
|
||||||
// trayIcon
|
// notifyIcon
|
||||||
//
|
//
|
||||||
this.notifyIcon.ContextMenuStrip = this.contextMenu;
|
|
||||||
this.notifyIcon.Icon = global::TweetDck.Properties.Resources.icon;
|
|
||||||
this.notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(this.trayIcon_MouseClick);
|
this.notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(this.trayIcon_MouseClick);
|
||||||
//
|
//
|
||||||
// contextMenuTray
|
|
||||||
//
|
|
||||||
this.contextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
|
||||||
this.restoreToolStripMenuItem,
|
|
||||||
this.muteNotificationsToolStripMenuItem,
|
|
||||||
this.closeToolStripMenuItem});
|
|
||||||
this.contextMenu.Name = "contextMenuTray";
|
|
||||||
this.contextMenu.ShowCheckMargin = true;
|
|
||||||
this.contextMenu.ShowImageMargin = false;
|
|
||||||
this.contextMenu.ShowItemToolTips = false;
|
|
||||||
this.contextMenu.Size = new System.Drawing.Size(174, 92);
|
|
||||||
this.contextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuTray_Opening);
|
|
||||||
this.contextMenu.Opened += new System.EventHandler(this.contextMenuTray_Opened);
|
|
||||||
//
|
|
||||||
// restoreToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.restoreToolStripMenuItem.Name = "restoreToolStripMenuItem";
|
|
||||||
this.restoreToolStripMenuItem.Size = new System.Drawing.Size(173, 22);
|
|
||||||
this.restoreToolStripMenuItem.Text = "Restore";
|
|
||||||
this.restoreToolStripMenuItem.Click += new System.EventHandler(this.restoreToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// muteNotificationsToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.muteNotificationsToolStripMenuItem.CheckOnClick = true;
|
|
||||||
this.muteNotificationsToolStripMenuItem.Name = "muteNotificationsToolStripMenuItem";
|
|
||||||
this.muteNotificationsToolStripMenuItem.Size = new System.Drawing.Size(173, 22);
|
|
||||||
this.muteNotificationsToolStripMenuItem.Text = "Mute Notifications";
|
|
||||||
this.muteNotificationsToolStripMenuItem.CheckedChanged += new System.EventHandler(this.muteNotificationsToolStripMenuItem_CheckedChanged);
|
|
||||||
//
|
|
||||||
// closeToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.closeToolStripMenuItem.Name = "closeToolStripMenuItem";
|
|
||||||
this.closeToolStripMenuItem.Size = new System.Drawing.Size(173, 22);
|
|
||||||
this.closeToolStripMenuItem.Text = "Close";
|
|
||||||
this.closeToolStripMenuItem.Click += new System.EventHandler(this.closeToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// TrayIcon
|
// TrayIcon
|
||||||
//
|
//
|
||||||
this.contextMenu.ResumeLayout(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.NotifyIcon notifyIcon;
|
private System.Windows.Forms.NotifyIcon notifyIcon;
|
||||||
private System.Windows.Forms.ContextMenuStrip contextMenu;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem restoreToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem muteNotificationsToolStripMenuItem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,59 +5,95 @@ using System.Windows.Forms;
|
|||||||
namespace TweetDck.Core{
|
namespace TweetDck.Core{
|
||||||
partial class TrayIcon : Component{
|
partial class TrayIcon : Component{
|
||||||
public enum Behavior{ // keep order
|
public enum Behavior{ // keep order
|
||||||
Disabled, DisplayOnly, MinimizeToTray, CloseToTray
|
Disabled, DisplayOnly, MinimizeToTray, CloseToTray, Combined
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler ClickRestore;
|
public event EventHandler ClickRestore;
|
||||||
public event EventHandler ClickClose;
|
public event EventHandler ClickClose;
|
||||||
|
|
||||||
public bool Visible{
|
public bool Visible{
|
||||||
|
get => notifyIcon.Visible;
|
||||||
|
|
||||||
|
set{
|
||||||
|
if (value){
|
||||||
|
notifyIcon.Icon = Properties.Resources.icon_tray;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyIcon.Visible = value;
|
||||||
|
hasNotifications = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasNotifications{
|
||||||
get{
|
get{
|
||||||
return notifyIcon.Visible;
|
return hasNotifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
set{
|
set{
|
||||||
notifyIcon.Visible = value;
|
if (hasNotifications != value && Visible){
|
||||||
|
notifyIcon.Icon = value ? Properties.Resources.icon_tray_new : Properties.Resources.icon_tray;
|
||||||
|
hasNotifications = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly ContextMenu contextMenu;
|
||||||
|
private bool hasNotifications;
|
||||||
|
|
||||||
public TrayIcon(){
|
public TrayIcon(){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
notifyIcon.Text = Program.BrandName;
|
|
||||||
|
this.contextMenu = new ContextMenu();
|
||||||
|
this.contextMenu.MenuItems.Add("Restore", menuItemRestore_Click);
|
||||||
|
this.contextMenu.MenuItems.Add("Mute notifications", menuItemMuteNotifications_Click);
|
||||||
|
this.contextMenu.MenuItems.Add("Close", menuItemClose_Click);
|
||||||
|
this.contextMenu.Popup += contextMenu_Popup;
|
||||||
|
|
||||||
|
this.notifyIcon.ContextMenu = contextMenu;
|
||||||
|
this.notifyIcon.Text = Program.BrandName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrayIcon(IContainer container) : this(){
|
||||||
|
container.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// event handlers
|
// event handlers
|
||||||
|
|
||||||
private void trayIcon_MouseClick(object sender, MouseEventArgs e){
|
private void trayIcon_MouseClick(object sender, MouseEventArgs e){
|
||||||
if (e.Button == MouseButtons.Left){
|
if (e.Button == MouseButtons.Left){
|
||||||
restoreToolStripMenuItem_Click(sender,e);
|
menuItemRestore_Click(sender, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void contextMenuTray_Opening(object sender, CancelEventArgs e){
|
private void contextMenu_Popup(object sender, EventArgs e){
|
||||||
muteNotificationsToolStripMenuItem.CheckedChanged -= muteNotificationsToolStripMenuItem_CheckedChanged;
|
contextMenu.MenuItems[1].Checked = Program.UserConfig.MuteNotifications;
|
||||||
muteNotificationsToolStripMenuItem.Checked = Program.UserConfig.MuteNotifications;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void contextMenuTray_Opened(object sender, EventArgs e){
|
private void menuItemRestore_Click(object sender, EventArgs e){
|
||||||
muteNotificationsToolStripMenuItem.CheckedChanged += muteNotificationsToolStripMenuItem_CheckedChanged;
|
ClickRestore?.Invoke(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restoreToolStripMenuItem_Click(object sender, EventArgs e){
|
private void menuItemMuteNotifications_Click(object sender, EventArgs e){
|
||||||
if (ClickRestore != null){
|
Program.UserConfig.MuteNotifications = !contextMenu.MenuItems[1].Checked;
|
||||||
ClickRestore(this,e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void muteNotificationsToolStripMenuItem_CheckedChanged(object sender, EventArgs e){
|
|
||||||
Program.UserConfig.MuteNotifications = muteNotificationsToolStripMenuItem.Checked;
|
|
||||||
Program.UserConfig.Save();
|
Program.UserConfig.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeToolStripMenuItem_Click(object sender, EventArgs e){
|
private void menuItemClose_Click(object sender, EventArgs e){
|
||||||
if (ClickClose != null){
|
ClickClose?.Invoke(this, e);
|
||||||
ClickClose(this,e);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class BehaviorExtensions{
|
||||||
|
public static bool ShouldDisplayIcon(this TrayIcon.Behavior behavior){
|
||||||
|
return behavior != TrayIcon.Behavior.Disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ShouldHideOnMinimize(this TrayIcon.Behavior behavior){
|
||||||
|
return behavior == TrayIcon.Behavior.MinimizeToTray || behavior == TrayIcon.Behavior.Combined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ShouldHideOnClose(this TrayIcon.Behavior behavior){
|
||||||
|
return behavior == TrayIcon.Behavior.CloseToTray || behavior == TrayIcon.Behavior.Combined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
50
Core/Utils/BrowserCache.cs
Normal file
50
Core/Utils/BrowserCache.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
static class BrowserCache{
|
||||||
|
private static bool ClearOnExit { get; set; }
|
||||||
|
|
||||||
|
private static readonly string CacheFolder = Path.Combine(Program.StoragePath, "Cache");
|
||||||
|
|
||||||
|
private static IEnumerable<string> CacheFiles{
|
||||||
|
get{
|
||||||
|
return Directory.EnumerateFiles(CacheFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CalculateCacheSize(Action<long> callbackBytes){
|
||||||
|
Task<long> task = new Task<long>(() => {
|
||||||
|
return CacheFiles.Select(file => {
|
||||||
|
try{
|
||||||
|
return new FileInfo(file).Length;
|
||||||
|
}catch{
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}).Sum();
|
||||||
|
});
|
||||||
|
|
||||||
|
task.ContinueWith(originalTask => callbackBytes(originalTask.Exception == null ? originalTask.Result : -1L), TaskContinuationOptions.ExecuteSynchronously);
|
||||||
|
task.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetClearOnExit(){
|
||||||
|
ClearOnExit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Exit(){
|
||||||
|
if (ClearOnExit){
|
||||||
|
foreach(string file in CacheFiles){
|
||||||
|
try{
|
||||||
|
File.Delete(file);
|
||||||
|
}catch{
|
||||||
|
// welp, too bad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
using System;
|
using CefSharp;
|
||||||
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDck.Core.Utils{
|
namespace TweetDck.Core.Utils{
|
||||||
@@ -20,14 +23,37 @@ namespace TweetDck.Core.Utils{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string HeaderUserAgent{
|
public static string HeaderUserAgent => Program.BrandName+" "+Application.ProductVersion;
|
||||||
get{
|
|
||||||
return Program.BrandName+" "+Application.ProductVersion;
|
public static readonly Color BackgroundColor = Color.FromArgb(28, 99, 153);
|
||||||
|
public const string BackgroundColorFix = "let e=document.createElement('style');document.head.appendChild(e);e.innerHTML='body::before{background:#1c6399!important}'";
|
||||||
|
|
||||||
|
public static readonly string[] DictionaryWords = {
|
||||||
|
"tweetdeck", "TweetDeck", "tweetduck", "TweetDuck", "TD"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static bool IsValidUrl(string url){
|
||||||
|
if (Uri.TryCreate(url, UriKind.Absolute, out Uri uri)){
|
||||||
|
string scheme = uri.Scheme;
|
||||||
|
return scheme == Uri.UriSchemeHttp || scheme == Uri.UriSchemeHttps || scheme == Uri.UriSchemeFtp || scheme == Uri.UriSchemeMailto;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenExternalBrowser(string url){
|
||||||
|
if (string.IsNullOrWhiteSpace(url))return;
|
||||||
|
|
||||||
|
if (IsValidUrl(url)){
|
||||||
|
OpenExternalBrowserUnsafe(url);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
MessageBox.Show("A potentially malicious URL was blocked from opening:"+Environment.NewLine+url, "Blocked URL", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void OpenExternalBrowser(string url){ // TODO implement mailto
|
public static void OpenExternalBrowserUnsafe(string url){
|
||||||
Process.Start(url);
|
using(Process.Start(url)){}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetFileNameFromUrl(string url){
|
public static string GetFileNameFromUrl(string url){
|
||||||
@@ -35,6 +61,14 @@ namespace TweetDck.Core.Utils{
|
|||||||
return string.IsNullOrEmpty(file) ? null : file;
|
return string.IsNullOrEmpty(file) ? null : file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string ConvertPascalCaseToScreamingSnakeCase(string str){
|
||||||
|
return Regex.Replace(str, @"(\p{Ll})(\P{Ll})|(\P{Ll})(\P{Ll}\p{Ll})", "$1$3_$2$4").ToUpperInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetErrorName(CefErrorCode code){
|
||||||
|
return ConvertPascalCaseToScreamingSnakeCase(Enum.GetName(typeof(CefErrorCode), code) ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
public static void DownloadFileAsync(string url, string target, Action<Exception> onFailure){
|
public static void DownloadFileAsync(string url, string target, Action<Exception> onFailure){
|
||||||
WebClient client = new WebClient{ Proxy = null };
|
WebClient client = new WebClient{ Proxy = null };
|
||||||
client.Headers[HttpRequestHeader.UserAgent] = HeaderUserAgent;
|
client.Headers[HttpRequestHeader.UserAgent] = HeaderUserAgent;
|
||||||
@@ -47,5 +81,23 @@ namespace TweetDck.Core.Utils{
|
|||||||
|
|
||||||
client.DownloadFileAsync(new Uri(url), target);
|
client.DownloadFileAsync(new Uri(url), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetZoomLevel(IBrowser browser, int percentage){
|
||||||
|
browser.GetHost().SetZoomLevel(Math.Log(percentage/100.0, 1.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsTweetDeckWebsite(IFrame frame){
|
||||||
|
return frame.Url.Contains("//tweetdeck.twitter.com/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsTwitterWebsite(IFrame frame){
|
||||||
|
return frame.Url.Contains("//twitter.com/");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
public static void HandleConsoleMessage(object sender, ConsoleMessageEventArgs e){
|
||||||
|
Debug.WriteLine("[Console] {0} ({1}:{2})", e.Message, e.Source, e.Line);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
106
Core/Utils/CommandLineArgs.cs
Normal file
106
Core/Utils/CommandLineArgs.cs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
class CommandLineArgs{
|
||||||
|
public static CommandLineArgs FromStringArray(char entryChar, string[] array){
|
||||||
|
CommandLineArgs args = new CommandLineArgs();
|
||||||
|
ReadStringArray(entryChar, array, args);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ReadStringArray(char entryChar, string[] array, CommandLineArgs targetArgs){
|
||||||
|
for(int index = 0; index < array.Length; index++){
|
||||||
|
string entry = array[index];
|
||||||
|
|
||||||
|
if (entry.Length > 0 && entry[0] == entryChar){
|
||||||
|
if (index < array.Length-1){
|
||||||
|
string potentialValue = array[index+1];
|
||||||
|
|
||||||
|
if (potentialValue.Length > 0 && potentialValue[0] == entryChar){
|
||||||
|
targetArgs.AddFlag(entry);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
targetArgs.SetValue(entry, potentialValue);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
targetArgs.AddFlag(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly HashSet<string> flags = new HashSet<string>();
|
||||||
|
private readonly Dictionary<string, string> values = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
public int Count => flags.Count+values.Count;
|
||||||
|
|
||||||
|
public void AddFlag(string flag){
|
||||||
|
flags.Add(flag.ToLowerInvariant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasFlag(string flag){
|
||||||
|
return flags.Contains(flag.ToLowerInvariant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveFlag(string flag){
|
||||||
|
flags.Remove(flag.ToLowerInvariant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetValue(string key, string value){
|
||||||
|
values[key.ToLowerInvariant()] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasValue(string key){
|
||||||
|
return values.ContainsKey(key.ToLowerInvariant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetValue(string key, string defaultValue){
|
||||||
|
return values.TryGetValue(key.ToLowerInvariant(), out string val) ? val : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveValue(string key){
|
||||||
|
values.Remove(key.ToLowerInvariant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandLineArgs Clone(){
|
||||||
|
CommandLineArgs copy = new CommandLineArgs();
|
||||||
|
|
||||||
|
foreach(string flag in flags){
|
||||||
|
copy.AddFlag(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(KeyValuePair<string, string> kvp in values){
|
||||||
|
copy.SetValue(kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToDictionary(IDictionary<string, string> target){
|
||||||
|
foreach(string flag in flags){
|
||||||
|
target[flag] = "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(KeyValuePair<string, string> kvp in values){
|
||||||
|
target[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString(){
|
||||||
|
StringBuilder build = new StringBuilder();
|
||||||
|
|
||||||
|
foreach(string flag in flags){
|
||||||
|
build.Append(flag).Append(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(KeyValuePair<string, string> kvp in values){
|
||||||
|
build.Append(kvp.Key).Append(" \"").Append(kvp.Value).Append("\" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return build.Length == 0 ? string.Empty : build.Remove(build.Length-1, 1).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Core/Utils/CommandLineArgsParser.cs
Normal file
39
Core/Utils/CommandLineArgsParser.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
static class CommandLineArgsParser{
|
||||||
|
private static Regex splitRegex;
|
||||||
|
|
||||||
|
private static Regex SplitRegex => splitRegex ?? (splitRegex = new Regex(@"([^=\s]+(?:=(?:[^ ]*""[^""]*?""[^ ]*|[^ ]*))?)", RegexOptions.Compiled));
|
||||||
|
|
||||||
|
public static CommandLineArgs ReadCefArguments(string argumentString){
|
||||||
|
CommandLineArgs args = new CommandLineArgs();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(argumentString)){
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(Match match in SplitRegex.Matches(argumentString)){
|
||||||
|
string matchValue = match.Value;
|
||||||
|
|
||||||
|
int indexEquals = matchValue.IndexOf('=');
|
||||||
|
string key, value;
|
||||||
|
|
||||||
|
if (indexEquals == -1){
|
||||||
|
key = matchValue.TrimStart('-');
|
||||||
|
value = "1";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
key = matchValue.Substring(0, indexEquals).TrimStart('-');
|
||||||
|
value = matchValue.Substring(indexEquals+1).Trim('"');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.Length != 0){
|
||||||
|
args.SetValue(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
Core/Utils/HardwareAcceleration.cs
Normal file
51
Core/Utils/HardwareAcceleration.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
static class HardwareAcceleration{
|
||||||
|
private static readonly string LibEGL = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libEGL.dll");
|
||||||
|
private static readonly string LibGLES = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libGLESv2.dll");
|
||||||
|
|
||||||
|
private static readonly string DisabledLibEGL = LibEGL+".bak";
|
||||||
|
private static readonly string DisabledLibGLES = LibGLES+".bak";
|
||||||
|
|
||||||
|
public static bool IsEnabled => File.Exists(LibEGL) && File.Exists(LibGLES);
|
||||||
|
public static bool CanEnable => File.Exists(DisabledLibEGL) && File.Exists(DisabledLibGLES);
|
||||||
|
|
||||||
|
public static bool Enable(){
|
||||||
|
if (IsEnabled)return false;
|
||||||
|
|
||||||
|
try{
|
||||||
|
File.Move(DisabledLibEGL, LibEGL);
|
||||||
|
File.Move(DisabledLibGLES, LibGLES);
|
||||||
|
return true;
|
||||||
|
}catch{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Disable(){
|
||||||
|
if (!IsEnabled)return false;
|
||||||
|
|
||||||
|
try{
|
||||||
|
if (File.Exists(DisabledLibEGL)){
|
||||||
|
File.Delete(DisabledLibEGL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(DisabledLibGLES)){
|
||||||
|
File.Delete(DisabledLibGLES);
|
||||||
|
}
|
||||||
|
}catch{
|
||||||
|
// woops
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
File.Move(LibEGL, DisabledLibEGL);
|
||||||
|
File.Move(LibGLES, DisabledLibGLES);
|
||||||
|
return true;
|
||||||
|
}catch{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
Core/Utils/InjectedHTML.cs
Normal file
37
Core/Utils/InjectedHTML.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
class InjectedHTML{
|
||||||
|
public enum Position{
|
||||||
|
Before, After
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Position position;
|
||||||
|
private readonly string search;
|
||||||
|
private readonly string html;
|
||||||
|
|
||||||
|
public InjectedHTML(Position position, string search, string html){
|
||||||
|
this.position = position;
|
||||||
|
this.search = search;
|
||||||
|
this.html = html;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Inject(string targetHTML){
|
||||||
|
int index = targetHTML.IndexOf(search, StringComparison.Ordinal);
|
||||||
|
|
||||||
|
if (index == -1){
|
||||||
|
return targetHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cutIndex;
|
||||||
|
|
||||||
|
switch(position){
|
||||||
|
case Position.Before: cutIndex = index; break;
|
||||||
|
case Position.After: cutIndex = index+search.Length; break;
|
||||||
|
default: return targetHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetHTML.Insert(cutIndex, html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
129
Core/Utils/NativeCoreAudio.cs
Normal file
129
Core/Utils/NativeCoreAudio.cs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
static class NativeCoreAudio{
|
||||||
|
private const int EDATAFLOW_RENDER = 0;
|
||||||
|
private const int EROLE_MULTIMEDIA = 1;
|
||||||
|
|
||||||
|
[ComImport]
|
||||||
|
[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
|
||||||
|
private class MMDeviceEnumerator{}
|
||||||
|
|
||||||
|
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
private interface IMMDeviceEnumerator{
|
||||||
|
int Unimpl_EnumAudioEndpoints();
|
||||||
|
IMMDevice GetDefaultAudioEndpoint(int dataFlow, int role);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("D666063F-1587-4E43-81F1-B948E807363F")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
private interface IMMDevice{
|
||||||
|
[return:MarshalAs(UnmanagedType.IUnknown)]
|
||||||
|
object Activate(ref Guid id, int clsCtx, IntPtr activationParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
private interface IAudioSessionManager2{
|
||||||
|
int Unimpl_FindWillToLive();
|
||||||
|
int Unimpl_HelloDarknessMyOldFriend();
|
||||||
|
IAudioSessionEnumerator GetSessionEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
private interface IAudioSessionEnumerator{
|
||||||
|
int GetCount();
|
||||||
|
IAudioSessionControl GetSession(int sessionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("F4B1A599-7266-4319-A8CA-E70ACB11E8CD")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
private interface IAudioSessionControl{}
|
||||||
|
|
||||||
|
[Guid("BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
private interface IAudioSessionControl2{
|
||||||
|
int Unimpl_GetState();
|
||||||
|
int Unimpl_GetDisplayName();
|
||||||
|
int Unimpl_SetDisplayName();
|
||||||
|
int Unimpl_GetIconPath();
|
||||||
|
int Unimpl_SetIconPath();
|
||||||
|
int Unimpl_GetGroupingParam();
|
||||||
|
int Unimpl_SetGroupingParam();
|
||||||
|
int Unimpl_RegisterAudioSessionNotification();
|
||||||
|
int Unimpl_UnregisterAudioSessionNotification();
|
||||||
|
|
||||||
|
[return:MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
string GetSessionIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
private interface ISimpleAudioVolume{
|
||||||
|
void SetMasterVolume(float level, ref Guid eventContext);
|
||||||
|
float GetMasterVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "SuspiciousTypeConversion.Global")]
|
||||||
|
private static ISimpleAudioVolume GetVolumeObject(string name){
|
||||||
|
IMMDeviceEnumerator devices = (IMMDeviceEnumerator)new MMDeviceEnumerator();
|
||||||
|
IMMDevice device = devices.GetDefaultAudioEndpoint(EDATAFLOW_RENDER, EROLE_MULTIMEDIA);
|
||||||
|
|
||||||
|
Guid sessionManagerGUID = typeof(IAudioSessionManager2).GUID;
|
||||||
|
IAudioSessionManager2 manager = (IAudioSessionManager2)device.Activate(ref sessionManagerGUID, 0, IntPtr.Zero);
|
||||||
|
IAudioSessionEnumerator sessions = manager.GetSessionEnumerator();
|
||||||
|
|
||||||
|
ISimpleAudioVolume volumeObj = null;
|
||||||
|
|
||||||
|
for(int index = sessions.GetCount()-1; index >= 0; index--){
|
||||||
|
IAudioSessionControl2 ctl = sessions.GetSession(index) as IAudioSessionControl2;
|
||||||
|
|
||||||
|
if (ctl != null){
|
||||||
|
string identifier = ctl.GetSessionIdentifier();
|
||||||
|
|
||||||
|
if (identifier != null && identifier.Contains(name)){
|
||||||
|
volumeObj = ctl as ISimpleAudioVolume;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Marshal.ReleaseComObject(ctl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Marshal.ReleaseComObject(devices);
|
||||||
|
Marshal.ReleaseComObject(device);
|
||||||
|
Marshal.ReleaseComObject(manager);
|
||||||
|
Marshal.ReleaseComObject(sessions);
|
||||||
|
return volumeObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double GetMixerVolume(string appPath){
|
||||||
|
ISimpleAudioVolume obj = GetVolumeObject(appPath);
|
||||||
|
float level = 1F;
|
||||||
|
|
||||||
|
if (obj != null){
|
||||||
|
level = obj.GetMasterVolume();
|
||||||
|
Marshal.ReleaseComObject(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.Round(level, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double GetMixerVolumeForCurrentProcess(){
|
||||||
|
string path;
|
||||||
|
|
||||||
|
using(Process process = Process.GetCurrentProcess()){
|
||||||
|
path = process.MainModule.FileName;
|
||||||
|
path = path.Substring(Path.GetPathRoot(path).Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetMixerVolume(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
124
Core/Utils/NativeMethods.cs
Normal file
124
Core/Utils/NativeMethods.cs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
|
||||||
|
[SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
|
||||||
|
static class NativeMethods{
|
||||||
|
public static readonly IntPtr HWND_BROADCAST = new IntPtr(0xFFFF);
|
||||||
|
public static readonly IntPtr HOOK_HANDLED = new IntPtr(-1);
|
||||||
|
|
||||||
|
public const int HWND_TOPMOST = -1;
|
||||||
|
public const uint SWP_NOACTIVATE = 0x0010;
|
||||||
|
|
||||||
|
public const int SB_HORZ = 0;
|
||||||
|
public const int BCM_SETSHIELD = 0x160C;
|
||||||
|
|
||||||
|
public const int WM_MOUSE_LL = 14;
|
||||||
|
public const int WM_MOUSEWHEEL = 0x020A;
|
||||||
|
public const int WM_XBUTTONDOWN = 0x020B;
|
||||||
|
public const int WM_XBUTTONUP = 0x020C;
|
||||||
|
public const int WM_PARENTNOTIFY = 0x0210;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct LASTINPUTINFO{
|
||||||
|
public static readonly uint Size = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
|
||||||
|
|
||||||
|
public uint cbSize;
|
||||||
|
public uint dwTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct POINT{
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct MSLLHOOKSTRUCT{
|
||||||
|
public POINT pt;
|
||||||
|
public int mouseData;
|
||||||
|
public int flags;
|
||||||
|
public int time;
|
||||||
|
public UIntPtr dwExtraInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
|
||||||
|
private static extern bool SetWindowPos(int hWnd, int hWndOrder, int x, int y, int width, int height, uint flags);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern bool GetLastInputInfo(ref LASTINPUTINFO info);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern IntPtr GetDC(IntPtr hWnd);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
|
||||||
|
|
||||||
|
[DllImport("gdi32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern uint RegisterWindowMessage(string messageName);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool ShowScrollBar(IntPtr hWnd, int wBar, bool bShow);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool UnhookWindowsHookEx(IntPtr idHook);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
|
public static void SetFormPos(Form form, int hWndOrder, uint flags){
|
||||||
|
SetWindowPos(form.Handle.ToInt32(), hWndOrder, form.Left, form.Top, form.Width, form.Height, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetMouseHookData(IntPtr ptr){
|
||||||
|
return Marshal.PtrToStructure<MSLLHOOKSTRUCT>(ptr).mouseData >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetIdleSeconds(){
|
||||||
|
LASTINPUTINFO info = new LASTINPUTINFO();
|
||||||
|
info.cbSize = LASTINPUTINFO.Size;
|
||||||
|
|
||||||
|
if (!GetLastInputInfo(ref info)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ticks;
|
||||||
|
|
||||||
|
unchecked{
|
||||||
|
ticks = (uint)Environment.TickCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int seconds = (int)Math.Floor(TimeSpan.FromMilliseconds(ticks-info.dwTime).TotalSeconds);
|
||||||
|
return Math.Max(0, seconds); // ignore rollover after several weeks of uptime
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RenderSourceIntoBitmap(IntPtr source, Bitmap target){
|
||||||
|
using(Graphics graphics = Graphics.FromImage(target)){
|
||||||
|
IntPtr graphicsHandle = graphics.GetHdc();
|
||||||
|
|
||||||
|
try{
|
||||||
|
BitBlt(graphicsHandle, 0, 0, target.Width, target.Height, source, 0, 0, 0x00CC0020);
|
||||||
|
}finally{
|
||||||
|
graphics.ReleaseHdc(graphicsHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
102
Core/Utils/TwoKeyDictionary.cs
Normal file
102
Core/Utils/TwoKeyDictionary.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
class TwoKeyDictionary<K1, K2, V>{
|
||||||
|
private readonly Dictionary<K1, Dictionary<K2, V>> dict;
|
||||||
|
private readonly int innerCapacity;
|
||||||
|
|
||||||
|
public TwoKeyDictionary() : this(16, 16){}
|
||||||
|
|
||||||
|
public TwoKeyDictionary(int outerCapacity, int innerCapacity){
|
||||||
|
this.dict = new Dictionary<K1, Dictionary<K2, V>>(outerCapacity);
|
||||||
|
this.innerCapacity = innerCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
|
||||||
|
public V this[K1 outerKey, K2 innerKey]{
|
||||||
|
get{ // throws on missing key
|
||||||
|
return dict[outerKey][innerKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
set{
|
||||||
|
if (!dict.TryGetValue(outerKey, out Dictionary<K2, V> innerDict)){
|
||||||
|
dict.Add(outerKey, innerDict = new Dictionary<K2, V>(innerCapacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
innerDict[innerKey] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<V> InnerValues{
|
||||||
|
get{
|
||||||
|
foreach(Dictionary<K2, V> innerDict in dict.Values){
|
||||||
|
foreach(V value in innerDict.Values){
|
||||||
|
yield return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Members
|
||||||
|
|
||||||
|
public void Add(K1 outerKey, K2 innerKey, V value){ // throws on duplicate
|
||||||
|
if (!dict.TryGetValue(outerKey, out Dictionary<K2, V> innerDict)){
|
||||||
|
dict.Add(outerKey, innerDict = new Dictionary<K2, V>(innerCapacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
innerDict.Add(innerKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear(){
|
||||||
|
dict.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear(K1 outerKey){ // throws on missing key, but keeps the key unlike Remove(K1)
|
||||||
|
dict[outerKey].Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(K1 outerKey){
|
||||||
|
return dict.ContainsKey(outerKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(K1 outerKey, K2 innerKey){
|
||||||
|
Dictionary<K2, V> innerDict;
|
||||||
|
return dict.TryGetValue(outerKey, out innerDict) && innerDict.ContainsKey(innerKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count(){
|
||||||
|
return dict.Values.Sum(d => d.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count(K1 outerKey){ // throws on missing key
|
||||||
|
return dict[outerKey].Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(K1 outerKey){
|
||||||
|
return dict.Remove(outerKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(K1 outerKey, K2 innerKey){
|
||||||
|
if (dict.TryGetValue(outerKey, out Dictionary<K2, V> innerDict) && innerDict.Remove(innerKey)){
|
||||||
|
if (innerDict.Count == 0) {
|
||||||
|
dict.Remove(outerKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue(K1 outerKey, K2 innerKey, out V value){
|
||||||
|
if (dict.TryGetValue(outerKey, out Dictionary<K2, V> innerDict)){
|
||||||
|
return innerDict.TryGetValue(innerKey, out value);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
value = default(V);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Core/Utils/WindowState.cs
Normal file
30
Core/Utils/WindowState.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
[Serializable]
|
||||||
|
class WindowState{
|
||||||
|
private Rectangle rect;
|
||||||
|
private bool isMaximized;
|
||||||
|
|
||||||
|
public void Save(Form form){
|
||||||
|
rect = form.WindowState == FormWindowState.Normal ? form.DesktopBounds : form.RestoreBounds;
|
||||||
|
isMaximized = form.WindowState == FormWindowState.Maximized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Restore(Form form, bool firstTimeFullscreen){
|
||||||
|
if (rect != Rectangle.Empty){
|
||||||
|
form.DesktopBounds = rect;
|
||||||
|
form.WindowState = isMaximized ? FormWindowState.Maximized : FormWindowState.Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rect == Rectangle.Empty && firstTimeFullscreen) || form.IsFullyOutsideView()){
|
||||||
|
form.DesktopBounds = Screen.PrimaryScreen.WorkingArea;
|
||||||
|
form.WindowState = FormWindowState.Maximized;
|
||||||
|
Save(form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
99
Core/Utils/WindowsUtils.cs
Normal file
99
Core/Utils/WindowsUtils.cs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
static class WindowsUtils{
|
||||||
|
public static bool ShouldAvoidToolWindow { get; }
|
||||||
|
|
||||||
|
static WindowsUtils(){
|
||||||
|
Version ver = Environment.OSVersion.Version;
|
||||||
|
ShouldAvoidToolWindow = ver.Major == 6 && ver.Minor == 2; // windows 8/10
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CheckFolderWritePermission(string path){
|
||||||
|
string testFile = Path.Combine(path, ".test");
|
||||||
|
|
||||||
|
try{
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
|
||||||
|
using(File.Create(testFile)){}
|
||||||
|
File.Delete(testFile);
|
||||||
|
return true;
|
||||||
|
}catch{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Process StartProcess(string file, string arguments, bool runElevated){
|
||||||
|
ProcessStartInfo processInfo = new ProcessStartInfo{
|
||||||
|
FileName = file,
|
||||||
|
Arguments = arguments
|
||||||
|
};
|
||||||
|
|
||||||
|
if (runElevated){
|
||||||
|
processInfo.Verb = "runas";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Process.Start(processInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TrySleepUntil(Func<bool> test, int timeoutMillis, int timeStepMillis){
|
||||||
|
for(int waited = 0; waited < timeoutMillis; waited += timeStepMillis){
|
||||||
|
if (test()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(timeStepMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ClipboardStripHtmlStyles(){
|
||||||
|
if (!Clipboard.ContainsText(TextDataFormat.Html)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string originalText = Clipboard.GetText(TextDataFormat.UnicodeText);
|
||||||
|
string originalHtml = Clipboard.GetText(TextDataFormat.Html);
|
||||||
|
|
||||||
|
string updatedHtml = ClipboardRegexes.RegexStripHtmlStyles.Replace(originalHtml, string.Empty);
|
||||||
|
|
||||||
|
int removed = originalHtml.Length-updatedHtml.Length;
|
||||||
|
updatedHtml = ClipboardRegexes.RegexOffsetClipboardHtml.Replace(updatedHtml, match => (int.Parse(match.Value)-removed).ToString().PadLeft(match.Value.Length, '0'));
|
||||||
|
|
||||||
|
DataObject obj = new DataObject();
|
||||||
|
obj.SetText(originalText, TextDataFormat.UnicodeText);
|
||||||
|
obj.SetText(updatedHtml, TextDataFormat.Html);
|
||||||
|
SetClipboardData(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetClipboard(string text, TextDataFormat format){
|
||||||
|
if (string.IsNullOrEmpty(text)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataObject obj = new DataObject();
|
||||||
|
obj.SetText(text, format);
|
||||||
|
SetClipboardData(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetClipboardData(DataObject obj){
|
||||||
|
try{
|
||||||
|
Clipboard.SetDataObject(obj);
|
||||||
|
}catch(ExternalException e){
|
||||||
|
Program.Reporter.HandleException("Clipboard Error", Program.BrandName+" could not access the clipboard as it is currently used by another process.", true, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ClipboardRegexes{ // delays construction of regular expressions until needed
|
||||||
|
public static readonly Regex RegexStripHtmlStyles = new Regex(@"\s?(?:style|class)="".*?""");
|
||||||
|
public static readonly Regex RegexOffsetClipboardHtml = new Regex(@"(?<=EndHTML:|EndFragment:)(\d+)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
168
Migration/FormMigrationQuestion.Designer.cs
generated
168
Migration/FormMigrationQuestion.Designer.cs
generated
@@ -1,168 +0,0 @@
|
|||||||
using TweetDck.Core.Controls;
|
|
||||||
|
|
||||||
namespace TweetDck.Migration {
|
|
||||||
partial class FormMigrationQuestion {
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing) {
|
|
||||||
if (disposing && (components != null)) {
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Windows Form Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent() {
|
|
||||||
this.btnIgnore = new System.Windows.Forms.Button();
|
|
||||||
this.panelButtons = new System.Windows.Forms.FlowLayoutPanel();
|
|
||||||
this.btnAskLater = new System.Windows.Forms.Button();
|
|
||||||
this.btnCopy = new System.Windows.Forms.Button();
|
|
||||||
this.btnMigrate = new System.Windows.Forms.Button();
|
|
||||||
this.btnMigrateUninstall = new System.Windows.Forms.Button();
|
|
||||||
this.labelQuestion = new RichTextLabel();
|
|
||||||
this.panelButtons.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// btnIgnore
|
|
||||||
//
|
|
||||||
this.btnIgnore.AutoSize = true;
|
|
||||||
this.btnIgnore.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
|
||||||
this.btnIgnore.Location = new System.Drawing.Point(356, 0);
|
|
||||||
this.btnIgnore.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
|
|
||||||
this.btnIgnore.Name = "btnIgnore";
|
|
||||||
this.btnIgnore.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnIgnore.Size = new System.Drawing.Size(53, 23);
|
|
||||||
this.btnIgnore.TabIndex = 1;
|
|
||||||
this.btnIgnore.Text = "Ignore";
|
|
||||||
this.btnIgnore.UseVisualStyleBackColor = true;
|
|
||||||
this.btnIgnore.Click += new System.EventHandler(this.btnIgnore_Click);
|
|
||||||
//
|
|
||||||
// panelButtons
|
|
||||||
//
|
|
||||||
this.panelButtons.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.panelButtons.Controls.Add(this.btnAskLater);
|
|
||||||
this.panelButtons.Controls.Add(this.btnIgnore);
|
|
||||||
this.panelButtons.Controls.Add(this.btnCopy);
|
|
||||||
this.panelButtons.Controls.Add(this.btnMigrate);
|
|
||||||
this.panelButtons.Controls.Add(this.btnMigrateUninstall);
|
|
||||||
this.panelButtons.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
|
|
||||||
this.panelButtons.Location = new System.Drawing.Point(12, 87);
|
|
||||||
this.panelButtons.Name = "panelButtons";
|
|
||||||
this.panelButtons.Size = new System.Drawing.Size(480, 23);
|
|
||||||
this.panelButtons.TabIndex = 0;
|
|
||||||
//
|
|
||||||
// btnAskLater
|
|
||||||
//
|
|
||||||
this.btnAskLater.AutoSize = true;
|
|
||||||
this.btnAskLater.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
|
||||||
this.btnAskLater.Location = new System.Drawing.Point(412, 0);
|
|
||||||
this.btnAskLater.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
|
|
||||||
this.btnAskLater.Name = "btnAskLater";
|
|
||||||
this.btnAskLater.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnAskLater.Size = new System.Drawing.Size(68, 23);
|
|
||||||
this.btnAskLater.TabIndex = 0;
|
|
||||||
this.btnAskLater.Text = "Ask Later";
|
|
||||||
this.btnAskLater.UseVisualStyleBackColor = true;
|
|
||||||
this.btnAskLater.Click += new System.EventHandler(this.btnAskLater_Click);
|
|
||||||
//
|
|
||||||
// btnCopy
|
|
||||||
//
|
|
||||||
this.btnCopy.AutoSize = true;
|
|
||||||
this.btnCopy.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
|
||||||
this.btnCopy.Location = new System.Drawing.Point(303, 0);
|
|
||||||
this.btnCopy.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnCopy.Name = "btnCopy";
|
|
||||||
this.btnCopy.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnCopy.Size = new System.Drawing.Size(47, 23);
|
|
||||||
this.btnCopy.TabIndex = 2;
|
|
||||||
this.btnCopy.Text = "Copy";
|
|
||||||
this.btnCopy.UseVisualStyleBackColor = true;
|
|
||||||
this.btnCopy.Click += new System.EventHandler(this.btnCopy_Click);
|
|
||||||
//
|
|
||||||
// btnMigrate
|
|
||||||
//
|
|
||||||
this.btnMigrate.AutoSize = true;
|
|
||||||
this.btnMigrate.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
|
||||||
this.btnMigrate.Location = new System.Drawing.Point(239, 0);
|
|
||||||
this.btnMigrate.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnMigrate.Name = "btnMigrate";
|
|
||||||
this.btnMigrate.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnMigrate.Size = new System.Drawing.Size(58, 23);
|
|
||||||
this.btnMigrate.TabIndex = 3;
|
|
||||||
this.btnMigrate.Text = "Migrate";
|
|
||||||
this.btnMigrate.UseVisualStyleBackColor = true;
|
|
||||||
this.btnMigrate.Click += new System.EventHandler(this.btnMigrate_Click);
|
|
||||||
//
|
|
||||||
// btnMigrateUninstall
|
|
||||||
//
|
|
||||||
this.btnMigrateUninstall.AutoSize = true;
|
|
||||||
this.btnMigrateUninstall.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
|
||||||
this.btnMigrateUninstall.Location = new System.Drawing.Point(135, 0);
|
|
||||||
this.btnMigrateUninstall.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
|
||||||
this.btnMigrateUninstall.Name = "btnMigrateUninstall";
|
|
||||||
this.btnMigrateUninstall.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnMigrateUninstall.Size = new System.Drawing.Size(98, 23);
|
|
||||||
this.btnMigrateUninstall.TabIndex = 4;
|
|
||||||
this.btnMigrateUninstall.Text = "Migrate && Purge";
|
|
||||||
this.btnMigrateUninstall.UseVisualStyleBackColor = true;
|
|
||||||
this.btnMigrateUninstall.Click += new System.EventHandler(this.btnMigrateUninstall_Click);
|
|
||||||
//
|
|
||||||
// labelQuestion
|
|
||||||
//
|
|
||||||
this.labelQuestion.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.labelQuestion.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
|
||||||
this.labelQuestion.Location = new System.Drawing.Point(49, 9);
|
|
||||||
this.labelQuestion.Margin = new System.Windows.Forms.Padding(40, 3, 3, 3);
|
|
||||||
this.labelQuestion.Name = "labelQuestion";
|
|
||||||
this.labelQuestion.ReadOnly = true;
|
|
||||||
this.labelQuestion.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
|
|
||||||
this.labelQuestion.Size = new System.Drawing.Size(443, 72);
|
|
||||||
this.labelQuestion.TabIndex = 2;
|
|
||||||
this.labelQuestion.TabStop = false;
|
|
||||||
this.labelQuestion.Text = "";
|
|
||||||
//
|
|
||||||
// FormMigrationQuestion
|
|
||||||
//
|
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
|
||||||
this.ClientSize = new System.Drawing.Size(504, 122);
|
|
||||||
this.Controls.Add(this.labelQuestion);
|
|
||||||
this.Controls.Add(this.panelButtons);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
|
||||||
this.MaximizeBox = false;
|
|
||||||
this.MinimizeBox = false;
|
|
||||||
this.Name = "FormMigrationQuestion";
|
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
|
||||||
this.Text = "TweetDeck Migration";
|
|
||||||
this.panelButtons.ResumeLayout(false);
|
|
||||||
this.panelButtons.PerformLayout();
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private System.Windows.Forms.Button btnIgnore;
|
|
||||||
private System.Windows.Forms.FlowLayoutPanel panelButtons;
|
|
||||||
private System.Windows.Forms.Button btnCopy;
|
|
||||||
private System.Windows.Forms.Button btnMigrate;
|
|
||||||
private RichTextLabel labelQuestion;
|
|
||||||
private System.Windows.Forms.Button btnAskLater;
|
|
||||||
private System.Windows.Forms.Button btnMigrateUninstall;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using TweetDck.Core.Controls;
|
|
||||||
|
|
||||||
namespace TweetDck.Migration{
|
|
||||||
partial class FormMigrationQuestion : Form{
|
|
||||||
public MigrationDecision Decision { get; private set; }
|
|
||||||
|
|
||||||
public FormMigrationQuestion(){
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
labelQuestion.Rtf = RichTextLabel.Wrap(@"Hey there, I found some TweetDeck data! Do you want to \b Migrate\b0 it and delete the old data folder, \b Copy\b0 it and keep the folder, \b Ignore\b0 the request forever, or do you need some more time for the decision?\par You may also \b Migrate & Purge\b0 which uninstalls TweetDeck too!");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnPaint(PaintEventArgs e){
|
|
||||||
e.Graphics.DrawIcon(SystemIcons.Question,10,10);
|
|
||||||
base.OnPaint(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnMigrateUninstall_Click(object sender, EventArgs e){
|
|
||||||
Close(MigrationDecision.MigratePurge);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnMigrate_Click(object sender, EventArgs e){
|
|
||||||
Close(MigrationDecision.Migrate);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnCopy_Click(object sender, EventArgs e){
|
|
||||||
Close(MigrationDecision.Copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnIgnore_Click(object sender, EventArgs e){
|
|
||||||
Close(MigrationDecision.Ignore);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnAskLater_Click(object sender, EventArgs e){
|
|
||||||
Close(MigrationDecision.AskLater);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Close(MigrationDecision decision){
|
|
||||||
Decision = decision;
|
|
||||||
DialogResult = DialogResult.OK;
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using Shell32;
|
|
||||||
|
|
||||||
namespace TweetDck.Migration.Helpers{
|
|
||||||
sealed class LnkEditor{
|
|
||||||
private readonly ShellLinkObject obj;
|
|
||||||
|
|
||||||
public LnkEditor(string file){
|
|
||||||
try{
|
|
||||||
Shell shell = new Shell();
|
|
||||||
Folder folder = shell.NameSpace(Path.GetDirectoryName(file));
|
|
||||||
FolderItem item = folder.Items().Item(Path.GetFileName(file));
|
|
||||||
|
|
||||||
obj = item.GetLink as ShellLinkObject;
|
|
||||||
}catch(Exception){
|
|
||||||
obj = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetComment(string newComment){
|
|
||||||
if (obj == null)return;
|
|
||||||
obj.Description = newComment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetPath(string newPath){
|
|
||||||
if (obj == null)return;
|
|
||||||
obj.Path = newPath;
|
|
||||||
obj.SetIconLocation(newPath,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetWorkingDirectory(string newWorkingDirectory){
|
|
||||||
if (obj == null)return;
|
|
||||||
obj.WorkingDirectory = newWorkingDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Save(){
|
|
||||||
if (obj == null)return;
|
|
||||||
obj.Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace TweetDck.Migration.Helpers{
|
|
||||||
static class ProgramProcessSearch{
|
|
||||||
public static Process FindProcessWithWindowByName(string name){
|
|
||||||
try{
|
|
||||||
return Process.GetProcessesByName(name).FirstOrDefault(process => process.MainWindowHandle != IntPtr.Zero);
|
|
||||||
}catch(Exception){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
|
|
||||||
namespace TweetDck.Migration.Helpers{
|
|
||||||
static class ProgramRegistrySearch{
|
|
||||||
public static string FindByDisplayName(string displayName){
|
|
||||||
Predicate<RegistryKey> predicate = key => displayName.Equals(key.GetValue("DisplayName") as string,StringComparison.OrdinalIgnoreCase);
|
|
||||||
string guid;
|
|
||||||
|
|
||||||
return FindMatchingSubKey(Registry.LocalMachine,@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall",predicate,out guid) ||
|
|
||||||
FindMatchingSubKey(Registry.LocalMachine,@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",predicate,out guid) ||
|
|
||||||
FindMatchingSubKey(Registry.CurrentUser,@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",predicate,out guid)
|
|
||||||
? guid : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool FindMatchingSubKey(RegistryKey keyHandle, string path, Predicate<RegistryKey> predicate, out string guid){
|
|
||||||
string outputId = null;
|
|
||||||
|
|
||||||
try{
|
|
||||||
RegistryKey parentKey = keyHandle.OpenSubKey(path,false);
|
|
||||||
if (parentKey == null)throw new InvalidOperationException();
|
|
||||||
|
|
||||||
foreach(RegistryKey subKey in parentKey.GetSubKeyNames().Select(subName => parentKey.OpenSubKey(subName,false)).Where(subKey => subKey != null)){
|
|
||||||
if (predicate(subKey)){
|
|
||||||
outputId = subKey.Name.Substring(subKey.Name.LastIndexOf('\\')+1);
|
|
||||||
subKey.Close();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
subKey.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
parentKey.Close();
|
|
||||||
}catch(Exception){
|
|
||||||
guid = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (guid = outputId) != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
namespace TweetDck.Migration{
|
|
||||||
enum MigrationDecision{
|
|
||||||
/// <summary>
|
|
||||||
/// Copies the important files and then deletes the TweetDeck folder.
|
|
||||||
/// </summary>
|
|
||||||
Migrate,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Does exactly what <see cref="Migrate"/> does, but also silently uninstalls TweetDeck.
|
|
||||||
/// </summary>
|
|
||||||
MigratePurge,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies the important files without deleting the TweetDeck folder.
|
|
||||||
/// </summary>
|
|
||||||
Copy,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Does not copy any files and does not ask the user about data migration again.
|
|
||||||
/// </summary>
|
|
||||||
Ignore,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Does not copy any files but asks the user again when the program is re-ran.
|
|
||||||
/// </summary>
|
|
||||||
AskLater
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,212 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using TweetDck.Core.Other;
|
|
||||||
using TweetDck.Migration.Helpers;
|
|
||||||
|
|
||||||
namespace TweetDck.Migration{
|
|
||||||
static class MigrationManager{
|
|
||||||
private static readonly string TweetDeckPathParent = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),"twitter");
|
|
||||||
private static readonly string TweetDeckPath = Path.Combine(TweetDeckPathParent,"TweetDeck");
|
|
||||||
|
|
||||||
public static void Run(){
|
|
||||||
if (!Program.UserConfig.IgnoreMigration && Directory.Exists(TweetDeckPath)){
|
|
||||||
MigrationDecision decision;
|
|
||||||
|
|
||||||
using(FormMigrationQuestion formQuestion = new FormMigrationQuestion()){
|
|
||||||
decision = formQuestion.ShowDialog() == DialogResult.OK ? formQuestion.Decision : MigrationDecision.AskLater;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(decision){
|
|
||||||
case MigrationDecision.MigratePurge:
|
|
||||||
case MigrationDecision.Migrate:
|
|
||||||
case MigrationDecision.Copy:
|
|
||||||
FormBackgroundWork formWait = new FormBackgroundWork();
|
|
||||||
|
|
||||||
formWait.ShowWorkDialog(() => {
|
|
||||||
if (!BeginMigration(decision,ex => formWait.Invoke(new Action(() => {
|
|
||||||
formWait.Close();
|
|
||||||
|
|
||||||
if (ex != null){
|
|
||||||
Program.HandleException("An unexpected exception has occurred during the migration process.",ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Program.UserConfig.IgnoreMigration = true;
|
|
||||||
Program.UserConfig.Save();
|
|
||||||
})))){
|
|
||||||
formWait.Close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MigrationDecision.Ignore:
|
|
||||||
Program.UserConfig.IgnoreMigration = true;
|
|
||||||
Program.UserConfig.Save();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!Program.UserConfig.IgnoreUninstallCheck){
|
|
||||||
string guid = ProgramRegistrySearch.FindByDisplayName("TweetDeck");
|
|
||||||
|
|
||||||
if (guid != null && MessageBox.Show("TweetDeck is still installed on your computer, do you want to uninstall it?","Uninstall TweetDeck",MessageBoxButtons.YesNo,MessageBoxIcon.Question,MessageBoxDefaultButton.Button2) == DialogResult.Yes){
|
|
||||||
RunUninstaller(guid,0);
|
|
||||||
CleanupTweetDeck();
|
|
||||||
}
|
|
||||||
|
|
||||||
Program.UserConfig.IgnoreUninstallCheck = true;
|
|
||||||
Program.UserConfig.Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool BeginMigration(MigrationDecision decision, Action<Exception> onFinished){
|
|
||||||
if (decision != MigrationDecision.MigratePurge && decision != MigrationDecision.Migrate && decision != MigrationDecision.Copy){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Task task = new Task(() => {
|
|
||||||
Directory.CreateDirectory(Program.StoragePath);
|
|
||||||
Directory.CreateDirectory(Path.Combine(Program.StoragePath,"localStorage"));
|
|
||||||
Directory.CreateDirectory(Path.Combine(Program.StoragePath,"Local Storage"));
|
|
||||||
|
|
||||||
CopyFile("Cookies");
|
|
||||||
CopyFile("Cookies-journal");
|
|
||||||
CopyFile("localStorage"+Path.DirectorySeparatorChar+"qrc__0.localstorage");
|
|
||||||
CopyFile("Local Storage"+Path.DirectorySeparatorChar+"https_tweetdeck.twitter.com_0.localstorage");
|
|
||||||
CopyFile("Local Storage"+Path.DirectorySeparatorChar+"https_tweetdeck.twitter.com_0.localstorage-journal");
|
|
||||||
|
|
||||||
if (decision == MigrationDecision.Migrate || decision == MigrationDecision.MigratePurge){
|
|
||||||
// kill process if running
|
|
||||||
Process runningProcess = ProgramProcessSearch.FindProcessWithWindowByName("TweetDeck");
|
|
||||||
|
|
||||||
if (runningProcess != null){
|
|
||||||
runningProcess.CloseMainWindow();
|
|
||||||
|
|
||||||
for(int wait = 0; wait < 100 && !runningProcess.HasExited; wait++){ // 10 seconds
|
|
||||||
runningProcess.Refresh();
|
|
||||||
Thread.Sleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
runningProcess.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete folders
|
|
||||||
for(int wait = 0; wait < 50; wait++){
|
|
||||||
try{
|
|
||||||
Directory.Delete(TweetDeckPath,true);
|
|
||||||
break;
|
|
||||||
}catch(Exception){
|
|
||||||
// browser subprocess not ended yet, wait
|
|
||||||
Thread.Sleep(300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try{
|
|
||||||
Directory.Delete(TweetDeckPathParent,false);
|
|
||||||
}catch(IOException){
|
|
||||||
// most likely not empty, ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decision == MigrationDecision.MigratePurge){
|
|
||||||
// update the lnk files wherever possible (desktop icons, pinned taskbar, start menu)
|
|
||||||
foreach(string location in GetLnkDirectories()){
|
|
||||||
if (location == string.Empty)continue;
|
|
||||||
|
|
||||||
string linkFile = Path.Combine(location,"TweetDeck.lnk");
|
|
||||||
|
|
||||||
if (File.Exists(linkFile)){
|
|
||||||
LnkEditor lnk = new LnkEditor(linkFile);
|
|
||||||
lnk.SetPath(Application.ExecutablePath);
|
|
||||||
lnk.SetWorkingDirectory(Environment.CurrentDirectory);
|
|
||||||
lnk.SetComment(Program.BrandName); // TODO add a tagline
|
|
||||||
lnk.Save();
|
|
||||||
|
|
||||||
string renamed = Path.Combine(location,Program.BrandName+".lnk");
|
|
||||||
|
|
||||||
try{
|
|
||||||
if (!File.Exists(renamed)){
|
|
||||||
File.Move(linkFile,renamed);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
File.Delete(linkFile);
|
|
||||||
}
|
|
||||||
}catch{
|
|
||||||
// eh, too bad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Program.SHChangeNotify(0x8000000,0x1000,IntPtr.Zero,IntPtr.Zero); // refreshes desktop
|
|
||||||
|
|
||||||
// uninstall in the background
|
|
||||||
string guid = ProgramRegistrySearch.FindByDisplayName("TweetDeck");
|
|
||||||
|
|
||||||
if (guid != null){
|
|
||||||
RunUninstaller(guid,5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// registry cleanup
|
|
||||||
CleanupTweetDeck();
|
|
||||||
|
|
||||||
// migration finished like a boss
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
task.ContinueWith(originalTask => onFinished(originalTask.Exception),TaskContinuationOptions.ExecuteSynchronously);
|
|
||||||
task.Start();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CopyFile(string relativePath){
|
|
||||||
try{
|
|
||||||
File.Copy(Path.Combine(TweetDeckPath,relativePath),Path.Combine(Program.StoragePath,relativePath),true);
|
|
||||||
}catch(FileNotFoundException){
|
|
||||||
}catch(DirectoryNotFoundException){
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<string> GetLnkDirectories(){
|
|
||||||
yield return Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
|
|
||||||
yield return Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory);
|
|
||||||
yield return Environment.ExpandEnvironmentVariables(@"%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar");
|
|
||||||
|
|
||||||
/* already handled by the installer
|
|
||||||
string startMenu = Environment.GetFolderPath(Environment.SpecialFolder.StartMenu);
|
|
||||||
string[] sub = Directory.GetDirectories(startMenu);
|
|
||||||
|
|
||||||
if (sub.Length > 0){
|
|
||||||
yield return Path.Combine(startMenu,sub[0],"TweetDeck");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RunUninstaller(string guid, int timeout){
|
|
||||||
Process uninstaller = Process.Start("msiexec.exe","/x "+guid+" /quiet /qn");
|
|
||||||
|
|
||||||
if (uninstaller != null){
|
|
||||||
if (timeout > 0){
|
|
||||||
uninstaller.WaitForExit(timeout); // it appears that the process is restarted or something that triggers this, but it shouldn't be a problem
|
|
||||||
}
|
|
||||||
|
|
||||||
uninstaller.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CleanupTweetDeck(){
|
|
||||||
try{
|
|
||||||
Registry.CurrentUser.DeleteSubKeyTree(@"Software\Twitter\TweetDeck",true);
|
|
||||||
Registry.CurrentUser.DeleteSubKey(@"Software\Twitter"); // only if empty
|
|
||||||
}catch(Exception){
|
|
||||||
// not found or too bad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
184
Plugins/Controls/PluginControl.Designer.cs
generated
Normal file
184
Plugins/Controls/PluginControl.Designer.cs
generated
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
namespace TweetDck.Plugins.Controls {
|
||||||
|
partial class PluginControl {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.btnToggleState = new System.Windows.Forms.Button();
|
||||||
|
this.labelName = new System.Windows.Forms.Label();
|
||||||
|
this.panelDescription = new System.Windows.Forms.Panel();
|
||||||
|
this.labelDescription = new System.Windows.Forms.Label();
|
||||||
|
this.labelAuthor = new System.Windows.Forms.Label();
|
||||||
|
this.flowLayoutInfo = new System.Windows.Forms.FlowLayoutPanel();
|
||||||
|
this.labelWebsite = new System.Windows.Forms.Label();
|
||||||
|
this.labelVersion = new System.Windows.Forms.Label();
|
||||||
|
this.btnOpenConfig = new System.Windows.Forms.Button();
|
||||||
|
this.panelDescription.SuspendLayout();
|
||||||
|
this.flowLayoutInfo.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// btnToggleState
|
||||||
|
//
|
||||||
|
this.btnToggleState.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnToggleState.Location = new System.Drawing.Point(459, 80);
|
||||||
|
this.btnToggleState.Name = "btnToggleState";
|
||||||
|
this.btnToggleState.Size = new System.Drawing.Size(65, 23);
|
||||||
|
this.btnToggleState.TabIndex = 5;
|
||||||
|
this.btnToggleState.Text = "Disable";
|
||||||
|
this.btnToggleState.UseVisualStyleBackColor = true;
|
||||||
|
this.btnToggleState.Click += new System.EventHandler(this.btnToggleState_Click);
|
||||||
|
//
|
||||||
|
// labelName
|
||||||
|
//
|
||||||
|
this.labelName.AutoSize = true;
|
||||||
|
this.labelName.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelName.Location = new System.Drawing.Point(7, 7);
|
||||||
|
this.labelName.Name = "labelName";
|
||||||
|
this.labelName.Size = new System.Drawing.Size(61, 24);
|
||||||
|
this.labelName.TabIndex = 0;
|
||||||
|
this.labelName.Text = "Name";
|
||||||
|
this.labelName.UseMnemonic = false;
|
||||||
|
//
|
||||||
|
// panelDescription
|
||||||
|
//
|
||||||
|
this.panelDescription.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelDescription.AutoScroll = true;
|
||||||
|
this.panelDescription.Controls.Add(this.labelDescription);
|
||||||
|
this.panelDescription.Location = new System.Drawing.Point(11, 35);
|
||||||
|
this.panelDescription.Name = "panelDescription";
|
||||||
|
this.panelDescription.Size = new System.Drawing.Size(513, 39);
|
||||||
|
this.panelDescription.TabIndex = 2;
|
||||||
|
this.panelDescription.Resize += new System.EventHandler(this.panelDescription_Resize);
|
||||||
|
//
|
||||||
|
// labelDescription
|
||||||
|
//
|
||||||
|
this.labelDescription.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.labelDescription.AutoSize = true;
|
||||||
|
this.labelDescription.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.labelDescription.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.labelDescription.Name = "labelDescription";
|
||||||
|
this.labelDescription.Size = new System.Drawing.Size(13, 39);
|
||||||
|
this.labelDescription.TabIndex = 0;
|
||||||
|
this.labelDescription.Text = "a\r\nb\r\nc";
|
||||||
|
this.labelDescription.UseMnemonic = false;
|
||||||
|
//
|
||||||
|
// labelAuthor
|
||||||
|
//
|
||||||
|
this.labelAuthor.AutoSize = true;
|
||||||
|
this.labelAuthor.Location = new System.Drawing.Point(3, 0);
|
||||||
|
this.labelAuthor.Margin = new System.Windows.Forms.Padding(3, 0, 32, 0);
|
||||||
|
this.labelAuthor.Name = "labelAuthor";
|
||||||
|
this.labelAuthor.Size = new System.Drawing.Size(38, 13);
|
||||||
|
this.labelAuthor.TabIndex = 0;
|
||||||
|
this.labelAuthor.Text = "Author";
|
||||||
|
this.labelAuthor.UseMnemonic = false;
|
||||||
|
//
|
||||||
|
// flowLayoutInfo
|
||||||
|
//
|
||||||
|
this.flowLayoutInfo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.flowLayoutInfo.Controls.Add(this.labelAuthor);
|
||||||
|
this.flowLayoutInfo.Controls.Add(this.labelWebsite);
|
||||||
|
this.flowLayoutInfo.Location = new System.Drawing.Point(11, 85);
|
||||||
|
this.flowLayoutInfo.Name = "flowLayoutInfo";
|
||||||
|
this.flowLayoutInfo.Size = new System.Drawing.Size(368, 18);
|
||||||
|
this.flowLayoutInfo.TabIndex = 3;
|
||||||
|
this.flowLayoutInfo.WrapContents = false;
|
||||||
|
//
|
||||||
|
// labelWebsite
|
||||||
|
//
|
||||||
|
this.labelWebsite.AutoSize = true;
|
||||||
|
this.labelWebsite.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.labelWebsite.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelWebsite.ForeColor = System.Drawing.Color.Blue;
|
||||||
|
this.labelWebsite.Location = new System.Drawing.Point(76, 0);
|
||||||
|
this.labelWebsite.Name = "labelWebsite";
|
||||||
|
this.labelWebsite.Size = new System.Drawing.Size(46, 13);
|
||||||
|
this.labelWebsite.TabIndex = 1;
|
||||||
|
this.labelWebsite.Text = "Website";
|
||||||
|
this.labelWebsite.UseMnemonic = false;
|
||||||
|
this.labelWebsite.Click += new System.EventHandler(this.labelWebsite_Click);
|
||||||
|
//
|
||||||
|
// labelVersion
|
||||||
|
//
|
||||||
|
this.labelVersion.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.labelVersion.Location = new System.Drawing.Point(14, 12);
|
||||||
|
this.labelVersion.Margin = new System.Windows.Forms.Padding(3, 9, 3, 0);
|
||||||
|
this.labelVersion.Name = "labelVersion";
|
||||||
|
this.labelVersion.Size = new System.Drawing.Size(513, 13);
|
||||||
|
this.labelVersion.TabIndex = 1;
|
||||||
|
this.labelVersion.Text = "Version";
|
||||||
|
this.labelVersion.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||||
|
this.labelVersion.UseMnemonic = false;
|
||||||
|
//
|
||||||
|
// btnOpenConfig
|
||||||
|
//
|
||||||
|
this.btnOpenConfig.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnOpenConfig.Location = new System.Drawing.Point(385, 80);
|
||||||
|
this.btnOpenConfig.Name = "btnOpenConfig";
|
||||||
|
this.btnOpenConfig.Size = new System.Drawing.Size(68, 23);
|
||||||
|
this.btnOpenConfig.TabIndex = 4;
|
||||||
|
this.btnOpenConfig.Text = "Configure";
|
||||||
|
this.btnOpenConfig.UseVisualStyleBackColor = true;
|
||||||
|
this.btnOpenConfig.Click += new System.EventHandler(this.btnOpenConfig_Click);
|
||||||
|
//
|
||||||
|
// PluginControl
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.btnOpenConfig);
|
||||||
|
this.Controls.Add(this.flowLayoutInfo);
|
||||||
|
this.Controls.Add(this.panelDescription);
|
||||||
|
this.Controls.Add(this.labelName);
|
||||||
|
this.Controls.Add(this.btnToggleState);
|
||||||
|
this.Controls.Add(this.labelVersion);
|
||||||
|
this.MaximumSize = new System.Drawing.Size(65535, 109);
|
||||||
|
this.MinimumSize = new System.Drawing.Size(0, 61);
|
||||||
|
this.Name = "PluginControl";
|
||||||
|
this.Padding = new System.Windows.Forms.Padding(3);
|
||||||
|
this.Size = new System.Drawing.Size(530, 109);
|
||||||
|
this.panelDescription.ResumeLayout(false);
|
||||||
|
this.panelDescription.PerformLayout();
|
||||||
|
this.flowLayoutInfo.ResumeLayout(false);
|
||||||
|
this.flowLayoutInfo.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Button btnToggleState;
|
||||||
|
private System.Windows.Forms.Label labelName;
|
||||||
|
private System.Windows.Forms.Panel panelDescription;
|
||||||
|
private System.Windows.Forms.Label labelDescription;
|
||||||
|
private System.Windows.Forms.Label labelAuthor;
|
||||||
|
private System.Windows.Forms.FlowLayoutPanel flowLayoutInfo;
|
||||||
|
private System.Windows.Forms.Label labelWebsite;
|
||||||
|
private System.Windows.Forms.Label labelVersion;
|
||||||
|
private System.Windows.Forms.Button btnOpenConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
86
Plugins/Controls/PluginControl.cs
Normal file
86
Plugins/Controls/PluginControl.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Plugins.Controls{
|
||||||
|
partial class PluginControl : UserControl{
|
||||||
|
private readonly PluginManager pluginManager;
|
||||||
|
private readonly Plugin plugin;
|
||||||
|
|
||||||
|
public PluginControl(){
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginControl(PluginManager pluginManager, Plugin plugin) : this(){
|
||||||
|
this.pluginManager = pluginManager;
|
||||||
|
this.plugin = plugin;
|
||||||
|
|
||||||
|
this.labelName.Text = plugin.Name;
|
||||||
|
this.labelDescription.Text = plugin.CanRun ? plugin.Description : "This plugin requires "+Program.BrandName+" "+plugin.RequiredVersion+" or newer.";
|
||||||
|
this.labelVersion.Text = plugin.Version;
|
||||||
|
this.labelAuthor.Text = plugin.Author;
|
||||||
|
this.labelWebsite.Text = plugin.Website;
|
||||||
|
|
||||||
|
UpdatePluginState();
|
||||||
|
|
||||||
|
if (labelDescription.Text.Length == 0){
|
||||||
|
labelDescription.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
panelDescription_Resize(panelDescription, new EventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void panelDescription_Resize(object sender, EventArgs e){
|
||||||
|
if (labelDescription.Text.Length == 0){
|
||||||
|
Height = MinimumSize.Height;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
labelDescription.MaximumSize = new Size(panelDescription.Width-SystemInformation.VerticalScrollBarWidth, 0);
|
||||||
|
Height = Math.Min(MinimumSize.Height+9+labelDescription.Height, MaximumSize.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void labelWebsite_Click(object sender, EventArgs e){
|
||||||
|
if (labelWebsite.Text.Length > 0){
|
||||||
|
BrowserUtils.OpenExternalBrowser(labelWebsite.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnOpenConfig_Click(object sender, EventArgs e){
|
||||||
|
using(Process.Start("explorer.exe", "/select,\""+plugin.ConfigPath.Replace('/', '\\')+"\"")){}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnToggleState_Click(object sender, EventArgs e){
|
||||||
|
bool newState = !pluginManager.Config.IsEnabled(plugin);
|
||||||
|
pluginManager.Config.SetEnabled(plugin, newState);
|
||||||
|
|
||||||
|
UpdatePluginState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePluginState(){
|
||||||
|
bool isEnabled = pluginManager.Config.IsEnabled(plugin) && plugin.CanRun;
|
||||||
|
Color textColor = isEnabled ? Color.Black : Color.FromArgb(90, 90, 90);
|
||||||
|
|
||||||
|
labelVersion.ForeColor = textColor;
|
||||||
|
labelAuthor.ForeColor = textColor;
|
||||||
|
labelWebsite.ForeColor = isEnabled ? Color.Blue : Color.FromArgb(90, 90, 249);
|
||||||
|
|
||||||
|
if (plugin.CanRun){
|
||||||
|
labelName.ForeColor = textColor;
|
||||||
|
labelDescription.ForeColor = textColor;
|
||||||
|
btnToggleState.Text = isEnabled ? "Disable" : "Enable";
|
||||||
|
btnOpenConfig.Visible = plugin.HasConfig;
|
||||||
|
btnOpenConfig.Enabled = btnOpenConfig.Visible && File.Exists(plugin.ConfigPath);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
labelName.ForeColor = Color.DarkRed;
|
||||||
|
labelDescription.ForeColor = Color.DarkRed;
|
||||||
|
btnToggleState.Visible = false;
|
||||||
|
btnOpenConfig.Visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user