Compare commits
631 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 59f308850e | |||
| e775a7581a | |||
| ec99e10b31 | |||
| 240d7921ba | |||
| 9ac006b114 | |||
| c3fef1cae2 | |||
| ca1c99a0d1 | |||
| 06ae7a20df | |||
| f536ecdc00 | |||
| a4bdd38367 | |||
| 6fb6d3e444 | |||
| a3952c37bf | |||
| c24ee72fe3 | |||
| f988b807c4 | |||
| cb1a596b10 | |||
| c41cd75b62 | |||
| 0df48f3002 | |||
| 2d58184080 | |||
| 1ef6e69d83 | |||
| dbd4af16c6 | |||
| 2263535d3a | |||
| 3ce4a5bf7f | |||
| f62c3431ff | |||
| a652084922 | |||
| ed30599db8 | |||
| d8752970e9 | |||
| 57a4c93cf5 | |||
| a116f5783d | |||
| 2730098c42 | |||
| 836d17359f | |||
| a4406bb137 | |||
| bbb67b415a | |||
| 0842360dbb | |||
| e58b23a54b | |||
| 72342bd8a5 | |||
| fa77fc3310 | |||
| 53fe2a7203 | |||
| 480dfafb4f | |||
| f5e13c5ceb | |||
| eadc902f84 | |||
| b461a3b64d | |||
| 75c758e5f4 | |||
| 05912b0381 | |||
| fb387a2c09 | |||
| 1380feef72 | |||
| 6c91a3022e | |||
| e55989120e | |||
| 14f12ccf51 | |||
| 82a1b02b4a | |||
| e99a2fbc56 | |||
| d3d23d18fb | |||
| cbf1b2af47 | |||
| 4f5fca4e67 | |||
| e0158a8ed7 | |||
| 40e7ba67d1 | |||
| e664605c90 | |||
| 5a51a6b179 | |||
| eb7929ccb6 | |||
| e85eec2e6b | |||
| 121394c0c0 | |||
| 5ad74d58f8 | |||
| afe2516d57 | |||
| ccf6e78cd5 | |||
| fef91fc8b9 | |||
| 4156587abe | |||
| 629eccaf09 | |||
| f89803eb64 | |||
| da12746a3a | |||
| b023019b0d | |||
| 1fdaa1083e | |||
| 2f8e846b9e | |||
| e42db52d14 | |||
| d4ec455ce0 | |||
| 0547c7ba91 | |||
| 8f4b809599 | |||
| 8432fb4fea | |||
| 84df2c86ae | |||
| 49ced23ba8 | |||
| 00bf2ca36f | |||
| b92861c7e3 | |||
| a189102628 | |||
| 58a6eb653b | |||
| 9159f5a004 | |||
| f1c570d793 | |||
| 832af39f34 | |||
| 9260f58803 | |||
| 1a5c515e45 | |||
| 87c8688f70 | |||
| d13179f9e4 | |||
| 75de21314c | |||
| 239f8e0905 | |||
| f4ac624bb3 | |||
| 2be0b98135 | |||
| 36c5719535 | |||
| 1f870bf76c | |||
| d5cc334e20 | |||
| fd98188ee4 | |||
| c3446f9c2d | |||
| e6e29b6c4c | |||
| 6096b5c4d8 | |||
| 838eadd47f | |||
| afb43531e8 | |||
| 3533e8b119 | |||
| 0e6ad13db8 | |||
| 0d725fcc2c | |||
| 7e747085d3 | |||
| f1376396c2 | |||
| 4eb9281f4d | |||
| c895816cb0 | |||
| 9f814c0f6a | |||
| e14aef9bd5 | |||
| 2b106a2b34 | |||
| f6494d2980 | |||
| 78a6c1a909 | |||
| c858643100 | |||
| 17b0bdc9fe | |||
| 2e0cdebb0c | |||
| a5f8955d78 | |||
| 0eca698a39 | |||
| 16f259da81 | |||
| c3ee477a1b | |||
| 33da35db04 | |||
| 533be1ec70 | |||
| b64573f5d4 | |||
| 1d6caa9a35 | |||
| c74b0943f3 | |||
| bb579294a0 | |||
| ad9f5f4dd7 | |||
| bf2e34f32e | |||
| bd57957df7 | |||
| 093db600ff | |||
| 131013f291 | |||
| 909d199379 | |||
| 5f16f4ab99 | |||
| fff95fa4e6 | |||
| a38327a39c | |||
| 686048dcce | |||
| 330c0f86de | |||
| 83317f1b80 | |||
| a416eb2cf6 | |||
| 2959c94bd3 | |||
| 063d9c8305 | |||
| 5e97608fa5 | |||
| 50dca2d02b | |||
| cd3785744c | |||
| 357810a5d5 | |||
| 1b71bc115d | |||
| de40286e81 | |||
| 8d0ff95760 | |||
| ffddf9fec3 | |||
| 3a35d96130 | |||
| 8add678d87 | |||
| a8bcf8c9e4 | |||
| 090374a1dc | |||
| e7aa95d53d | |||
| f6ccf18cf5 | |||
| 4542ce8c70 | |||
| f80287bc27 | |||
| e10ab74917 | |||
| 23ddb99026 | |||
| efbac9e128 | |||
| 62044c2731 | |||
| 7d1a38d46f | |||
| d885bc14e1 | |||
| 886937a3ea | |||
| 99eff43ab4 | |||
| 880269780d | |||
| 7f1b891679 | |||
| ceced2a9a4 | |||
| d3a8cb84a6 | |||
| 6b43bb8fe3 | |||
| a74cffac39 | |||
| 83d2891cef | |||
| 0faad370f9 | |||
| 23fab89131 | |||
| 48189172ea | |||
| 0c9eda44d4 | |||
| f0a9ce3ab4 | |||
| ea5878a0c9 | |||
| f67382612d | |||
| 3fe7ae07ed | |||
| 8bcfa81bea | |||
| c17918d9c1 | |||
| f752df0595 | |||
| 0836b5b661 | |||
| 2cefccf7bf | |||
| 3dc86c5a4f | |||
| 05ae712e77 | |||
| 04db374326 | |||
| e3558b7dcf | |||
| 99e10c6112 | |||
| 537934339e | |||
| ee343e1263 | |||
| 6eeca9aa90 | |||
| 86beb339b7 | |||
| 67b5af23aa | |||
| 88f65f4e47 | |||
| af5b6b0eba | |||
| 57ef739404 | |||
| 584eb9f531 | |||
| 36a4d5a511 | |||
| 72737b20cd | |||
| d05093e6f7 | |||
| a7e6928f4e | |||
| 951fd2d693 | |||
| be991cfcd6 | |||
| aab36d9b85 | |||
| 3cd6935acb | |||
| 6daef080e3 | |||
| 6ee909b958 | |||
| c11ae8bd02 | |||
| c7a4ea97c3 | |||
| 81ebb1030a | |||
| 86ec36d183 | |||
| 207f2e568b | |||
| 19753719cb | |||
| 5f025dcd73 | |||
| c796eeaf8b | |||
| bdbd7f0c9c | |||
| b0e09327db | |||
| 96a3621b8e | |||
| 8f259211e7 | |||
| 0d9d8c28f1 | |||
| 058a0bbf93 | |||
| 4d46e0ceb7 | |||
| 123ff326d4 | |||
| 14d4c38979 | |||
| 9c87a52b6e | |||
| 30c2028852 | |||
| 95e6be0e81 | |||
| 955313e97d | |||
| 32c2135047 | |||
| 702e08b083 | |||
| 8f58e1a9e0 | |||
| 0cc25f10c6 | |||
| 61ef88a0ac | |||
| 02a95b958d | |||
| 5cd88dbd20 | |||
| ec53ed6a37 | |||
| 242413a334 | |||
| f88dce1627 | |||
| 5c456370d9 | |||
| 93fdd35b31 | |||
| 70d5fccb54 | |||
| 6ca7c3a3a1 | |||
| 88448ce746 | |||
| 1fee2c626b | |||
| 480a9ac77d | |||
| 889689e31a | |||
| c8e49599ce | |||
| 351cb7e104 | |||
| 5c5e41500a | |||
| 2e739e743d | |||
| 1eee3d350b | |||
| d2d7e630bd | |||
| d11cd173dc | |||
| 12e0427038 | |||
| 9bcb6f0adf | |||
| 09490e1f46 | |||
| f33120c540 | |||
| 82ed223b02 | |||
| bfdbf969c2 | |||
| 7d409b9404 | |||
| 7673f220a9 | |||
| 75daa1afec | |||
| 27657e00fe | |||
| 26b8812f15 | |||
| 07e13c51d1 | |||
| f9b59b4fdf | |||
| 76a3b3db97 | |||
| 4b0416e92a | |||
| 5d6bb4b04f | |||
| 2764f292cb | |||
| 7ca59e24c6 | |||
| e1a2d60672 | |||
| 9672390104 | |||
| 33c2005c18 | |||
| 3e1309110e | |||
| aae7d94ffd | |||
| 5b0d752e0c | |||
| 0f93752f14 | |||
| 049ecc43e3 | |||
| 2209f5e93b | |||
| a17cd9d054 | |||
| 4497aaa3fa | |||
| 00226ae40a | |||
| 45963a3443 | |||
| 4aa1a881f3 | |||
| f3dd5b73f8 | |||
| fd049ef510 | |||
| 7d389f8024 | |||
| df63f47deb | |||
| c521efa35d | |||
| af1561b848 | |||
| 691931f74d | |||
| da5e1de1c8 | |||
| 043892bdc6 | |||
| 34d2aeaac3 | |||
| 4481e89046 | |||
| 8120e47bfd | |||
| db526e581c | |||
| 246be732a1 | |||
| 27a0bd2535 | |||
| 8f57fd82a0 | |||
| 1ef90c898e | |||
| cf133975c1 | |||
| c468b68c5a | |||
| acbddc904b | |||
| 83624acfd2 | |||
| d915ddc647 | |||
| 61b741c34e | |||
| aa1910a834 | |||
| dba36c07fe | |||
| 8451e6dcf1 | |||
| 88dfe6eb9c | |||
| 800b697d06 | |||
| 2176a654cd | |||
| 2176788d1c | |||
| 6389fa2d81 | |||
| 8a0b64dd00 | |||
| 79ac207532 | |||
| c33e12b66f | |||
| 5d0dfb80d4 | |||
| 7ebab92f16 | |||
| 1a851f7c33 | |||
| 74ee8bea5d | |||
| dec1748978 | |||
| 4ef47e1040 | |||
| 42f242ce42 | |||
| c4914a64bb | |||
| 4aa05dfcf2 | |||
| 255ff5d789 | |||
| 75f5186dec | |||
| 0cf6d80705 | |||
| 2d96c6ad22 | |||
| ef7ec13861 | |||
| 8008e09918 | |||
| 75ace76c6a | |||
| 9de58a29e3 | |||
| 56aff41b7e | |||
| a8417a7e23 | |||
| 582c9b7f08 | |||
| 2eb6ca75a8 | |||
| 4918ac6307 | |||
| acc03e91f3 | |||
| 8e1466a35a | |||
| 5b73af668f | |||
| deb035c7fe | |||
| 2075a99c9b | |||
| 74b1f603df | |||
| ed1eb1c018 | |||
| 4bed2e57cb | |||
| 0629f502b5 | |||
| fd93873cc1 | |||
| dbd58dbbc6 | |||
| b2edf61588 | |||
| 96b6975deb | |||
| 9449dab0b7 | |||
| 6da9dbcc53 | |||
| d1bdea21b4 | |||
| 5ea0f3253f | |||
| b1e5c02e0c | |||
| f48d97ab04 | |||
| 8f85e04d61 | |||
| 1eab9b34fe | |||
| 13a3c44b61 | |||
| f6b106598c | |||
| f6aed13605 | |||
| 62dd8e67df | |||
| ba7620e0ee | |||
| 931f6a35dd | |||
| d3394733b1 | |||
| 0f5d175b09 | |||
| c93111bf4b | |||
| adb0f0a46f | |||
| 60454c0c39 | |||
| de35de9e00 | |||
| d5d91ae592 | |||
| 9c852af5b7 | |||
| 24fcfd125c | |||
| 1ad42519d6 | |||
| 3052dcc95a | |||
| 17089d8316 | |||
| ce919632be | |||
| f3168c3603 | |||
| a6ca88b5ac | |||
| 8625a59d4c | |||
| cb4289fd19 | |||
| 9ac5f837f7 | |||
| 033ab9ac71 | |||
| 228fe71eb4 | |||
| 80462cf559 | |||
| e5df16ba2b | |||
| b0f4d56de1 | |||
| 7bc0f8731f | |||
| b4b49a4296 | |||
| 507054e9cd | |||
| 342b8b157b | |||
| 74fc8f6db0 | |||
| 04bb3dfe9d | |||
| 7fb15269d1 | |||
| 49772d2539 | |||
| 0f4bd34bce | |||
| 2451cbddec | |||
| b7363225da | |||
| a9c0756da4 | |||
| 2652068933 | |||
| 022105cdba | |||
| 2fa05ed245 | |||
| 124be52411 | |||
| 6f8272718d | |||
| bac1fb18f0 | |||
| 391204ea0d | |||
| 810f3efcbb | |||
| e4a80d887a | |||
| 45d496bd01 | |||
| 20a5b2d4c4 | |||
| cc2637b310 | |||
| 3fc404cd25 | |||
| e016fa913f | |||
| e1c6f4f58f | |||
| c50888fc79 | |||
| 7c0a911e9f | |||
| 0562776b7a | |||
| 9cf79ffb5a | |||
| 63b0ef65e0 | |||
| 62bf6a9d57 | |||
| 4ad6244d8d | |||
| b2f72020bd | |||
| d73f96e3d8 | |||
| f8210e4a2a | |||
| 1ccaf45740 | |||
| d268ccea5b | |||
| 10efb6e55a | |||
| 171c44507a | |||
| 9514f057dc | |||
| e154857aca | |||
| 59c06bcaf1 | |||
| 17f02b2ff0 | |||
| 6316b78a5e | |||
| e53269c37f | |||
| a43adf7d4f | |||
| 16d24d4b43 | |||
| 4a3ae82748 | |||
| 60fe2ce30e | |||
| b294530716 | |||
| 0652267d00 | |||
| b857374aa2 | |||
| 480ce08d39 | |||
| 63f33a42e3 | |||
| f6d1baa50a | |||
| 0df1ec8765 | |||
| 19e128041b | |||
| 76f8b3df22 | |||
| e1e791fc75 | |||
| bbf59a731d | |||
| 803bcbbea0 | |||
| 6f384c8802 | |||
| d6eb66c738 | |||
| 7078381175 | |||
| 0ffef66cb6 | |||
| dfc17244d4 | |||
| ecb9f607ed | |||
| 35126ba22c | |||
| 5cdf03ff6d | |||
| d128b30279 | |||
| cadea90109 | |||
| 90d1695bbc | |||
| 713cb032b5 | |||
| 24ed144200 | |||
| ebc584b2a7 | |||
| dcef21676d | |||
| ff2da496af | |||
| 9d5f85634c | |||
| 7efda5fbbd | |||
| 60696a895c | |||
| 8b26f50003 | |||
| bf78ac7a6c | |||
| f9e9ed53f9 | |||
| d727063036 | |||
| 26f69bccef | |||
| 95f991b5de | |||
| 2a4b72246b | |||
| e62c9d89b1 | |||
| 3926173dfe | |||
| 9098a7c128 | |||
| d77de385f0 | |||
| 7bcd3e2262 | |||
| 2f35d97b27 | |||
| 152dc56df4 | |||
| 32930319ea | |||
| 2e54232181 | |||
| 8648017b42 | |||
| f974c8259e | |||
| f6f99e45b9 | |||
| 414fca0664 | |||
| 2641a0d98e | |||
| 53e8d68878 | |||
| 7a6d0c3432 | |||
| b049902925 | |||
| a8289c3223 | |||
| e46d742d6c | |||
| 24d996c8c4 | |||
| 8b2cdc434b | |||
| a7c4f15fea | |||
| 05b0cc9e76 | |||
| 495aaa4c56 | |||
| b57ba269a6 | |||
| 4948eb0d45 | |||
| e5e6b9e820 | |||
| 1c2b236c86 | |||
| 6ca66a04da | |||
| 2595be63a1 | |||
| c31b36975d | |||
| 73a2fcd301 | |||
| 00b0a7c811 | |||
| 2ef93cad44 | |||
| d3aa304556 | |||
| 228927b4e9 | |||
| 6fc393c7db | |||
| 361fdcce1b | |||
| 12cf696097 | |||
| e7ae6cd190 | |||
| 61dfe4ef07 | |||
| d3099ecf75 | |||
| c183e3f342 | |||
| a5ded3341a | |||
| bb15c56a2d | |||
| c61931996a | |||
| cb6c91be06 | |||
| bfcdec47c1 | |||
| c0445ed857 | |||
| 4e79d1ecdd | |||
| 4306af3ef3 | |||
| a01f9f99f4 | |||
| 08186f4131 | |||
| bdc9807dee | |||
| d77180d9b5 | |||
| b0bcaa971e | |||
| 4294202074 | |||
| 1e013274c2 | |||
| 39c7024f12 | |||
| 375f3a7164 | |||
| 370bdef8d0 | |||
| 7b1e75e6ed | |||
| 5c1a089981 | |||
| cfb59094fe | |||
| 7d30a2bc54 | |||
| 472879e95a | |||
| 7027d02f94 | |||
| 561441b48a | |||
| fe5c7a60ab | |||
| 1a3dc72af8 | |||
| c919694f37 | |||
| 6fbdf8f0e2 | |||
| 4060ec3038 | |||
| 32626970a0 | |||
| bc0a53a226 | |||
| b6a044111b | |||
| 3c4286c98b | |||
| 6d996e31b8 | |||
| ec4faad589 | |||
| 13820bc002 | |||
| 6ad9f25e7d | |||
| a348fde7d1 | |||
| d25017dd5b | |||
| 9b965f367a | |||
| adca34ac6a | |||
| 51a4a92ec4 | |||
| ae8ea3b938 | |||
| b57d77dd0b | |||
| d5cbb56160 | |||
| e97c2a6864 | |||
| 41447e9b44 | |||
| 7aa368c2c5 | |||
| 6a00eaa4a3 | |||
| 9240566167 | |||
| 9eaa5f90e0 | |||
| 214f785c97 | |||
| ae0534cbb4 | |||
| f3c5c458c6 | |||
| d6fd5598ab | |||
| c41b334f0a | |||
| c3a6bf3d40 | |||
| cb7aa5143b | |||
| 8942abfc64 | |||
| e5ef973d52 | |||
| 0bd45f691e | |||
| 117c70ed7d | |||
| d09f88d53b | |||
| 06f17d9415 | |||
| c1d8e979f3 | |||
| 16f286735d | |||
| 45c7490180 | |||
| 1566b357cb | |||
| 7d9222926a | |||
| b957d5176e | |||
| e76a520c19 | |||
| f0d205fed9 | |||
| 42811d0602 | |||
| b54c03f89e | |||
| 5596790a6e | |||
| e55263be00 | |||
| 441c2b50b9 | |||
| 0a3f5b65bf | |||
| 93c29ad15e | |||
| 8f565ef7f0 | |||
| d97de297af | |||
| 18ac4c2288 | |||
| 0c6eb6dec3 | |||
| 4a274709e7 | |||
| c6e4f18d99 | |||
| 0e5155ae2f | |||
| aa78abc649 | |||
| 1c62fc868d | |||
| f9c2f03a44 | |||
| dfd11b7596 | |||
| 98796f6250 | |||
| b728251bcc | |||
| d894faaeaa | |||
| 8b114c81c5 | |||
| 97ffb60f23 | |||
| 41b7182661 | |||
| 19e5a231a7 | |||
| 01fcb2276b | |||
| 19b4e98ee7 | |||
| 77c76bbc8a | |||
| 00bb1636da | |||
| 50ec496c54 | |||
| 2b8ad1b65c | |||
| 5c5f077a4a |
+4
-2
@@ -23,8 +23,10 @@ test_formatting:
|
||||
allow_failure: true
|
||||
before_script:
|
||||
# We must manually add the KiCad remote to ensure it is named sensibly
|
||||
- git remote add product https://gitlab.com/kicad/code/kicad.git
|
||||
- git remote add source ${CI_MERGE_REQUEST_SOURCE_PROJECT_URL}.git
|
||||
- git remote add product https://gitlab.com/kicad/code/kicad.git ||
|
||||
git remote set-url product https://gitlab.com/kicad/code/kicad.git
|
||||
- git remote add source ${CI_MERGE_REQUEST_SOURCE_PROJECT_URL}.git ||
|
||||
git remote set-url source ${CI_MERGE_REQUEST_SOURCE_PROJECT_URL}.git
|
||||
- git fetch -n product
|
||||
- git fetch -n source
|
||||
# Get the SHAs of the commits
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -294,6 +294,16 @@ void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
++bl;
|
||||
}
|
||||
|
||||
// prevent loading non-plugin dlls
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
if( !path.GetName().StartsWith( "s3d_plugin" )
|
||||
&& !path.GetName().StartsWith( "libs3d_plugin" ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
aPluginList.push_back( wxpath );
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * [INFO] found 3D plugin '%s'\n" ), wxpath.GetData() );
|
||||
|
||||
@@ -657,11 +657,6 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
|
||||
}
|
||||
|
||||
|
||||
extern bool BuildFootprintPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
|
||||
int aErrorMax, int aChainingEpsilon,
|
||||
OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
|
||||
|
||||
|
||||
bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
|
||||
{
|
||||
m_board_poly.RemoveAllContours();
|
||||
|
||||
@@ -348,7 +348,7 @@ private:
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
void addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aDstContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
const BOARD_ITEM* aItem );
|
||||
|
||||
void addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
|
||||
void BOARD_ADAPTER::addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner )
|
||||
const BOARD_ITEM* aItem )
|
||||
{
|
||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||
TEXT_ATTRIBUTES attrs = aText->GetAttributes();
|
||||
@@ -74,34 +74,25 @@ void BOARD_ADAPTER::addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aContaine
|
||||
if( !font )
|
||||
font = KIFONT::FONT::GetFont( wxEmptyString, aText->IsBold(), aText->IsItalic() );
|
||||
|
||||
if( aOwner && aOwner->IsKnockout() )
|
||||
if( aItem && aItem->IsKnockout() )
|
||||
{
|
||||
SHAPE_POLY_SET knockouts;
|
||||
|
||||
CALLBACK_GAL callback_gal( empty_opts,
|
||||
// Polygon callback
|
||||
[&]( const SHAPE_LINE_CHAIN& aPoly )
|
||||
{
|
||||
knockouts.AddOutline( aPoly );
|
||||
} );
|
||||
|
||||
attrs.m_StrokeWidth = aText->GetEffectiveTextPenWidth();
|
||||
attrs.m_Angle = aText->GetDrawRotation();
|
||||
|
||||
callback_gal.SetIsFill( font->IsOutline() );
|
||||
callback_gal.SetIsStroke( font->IsStroke() );
|
||||
callback_gal.SetLineWidth( attrs.m_StrokeWidth );
|
||||
font->Draw( &callback_gal, aText->GetShownText( true ), aText->GetDrawPos(), attrs );
|
||||
|
||||
int maxError = m_board->GetDesignSettings().m_MaxError;
|
||||
SHAPE_POLY_SET finalPoly;
|
||||
int margin = attrs.m_StrokeWidth * 1.5 +
|
||||
GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth );
|
||||
|
||||
aText->TransformBoundingBoxToPolygon( &finalPoly, margin );
|
||||
finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST );
|
||||
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
||||
if( aItem->Type() == PCB_FP_TEXT_T )
|
||||
{
|
||||
static_cast<const FP_TEXT*>( aItem )->TransformTextToPolySet( finalPoly, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
else if( aItem->Type() == PCB_TEXT_T )
|
||||
{
|
||||
static_cast<const PCB_TEXT*>( aItem )->TransformTextToPolySet( finalPoly, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
|
||||
ConvertPolygonToTriangles( finalPoly, *aContainer, m_biuTo3Dunits, *aOwner );
|
||||
// Do not call finalPoly.Fracture() here: ConvertPolygonToTriangles() call it
|
||||
// if needed, and Fracture() called twice can create bad results and is useless
|
||||
ConvertPolygonToTriangles( finalPoly, *aContainer, m_biuTo3Dunits, *aItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -120,19 +111,19 @@ void BOARD_ADAPTER::addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aContaine
|
||||
{
|
||||
// Cannot add segments that have the same start and end point
|
||||
aContainer->Add( new FILLED_CIRCLE_2D( pt1_3DU, penWidth_3DU / 2,
|
||||
*aOwner ) );
|
||||
*aItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aContainer->Add( new ROUND_SEGMENT_2D( pt1_3DU, pt2_3DU, penWidth_3DU,
|
||||
*aOwner ) );
|
||||
*aItem ) );
|
||||
}
|
||||
},
|
||||
// Triangulation callback
|
||||
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
|
||||
{
|
||||
aContainer->Add( new TRIANGLE_2D( TO_SFVEC2F( aPt1 ), TO_SFVEC2F( aPt2 ),
|
||||
TO_SFVEC2F( aPt3 ), *aOwner ) );
|
||||
TO_SFVEC2F( aPt3 ), *aItem ) );
|
||||
} );
|
||||
|
||||
attrs.m_Angle = aText->GetDrawRotation();
|
||||
@@ -210,7 +201,8 @@ void BOARD_ADAPTER::addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2
|
||||
|
||||
if( textbox->GetLayer() == aLayerId )
|
||||
{
|
||||
addShape( textbox, aContainer, aFootprint );
|
||||
if( textbox->IsBorderEnabled() )
|
||||
addShape( textbox, aContainer, aFootprint );
|
||||
addText( textbox, aContainer, aFootprint );
|
||||
}
|
||||
|
||||
@@ -269,6 +261,19 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
|
||||
{
|
||||
const PCB_ARC* arc = static_cast<const PCB_ARC*>( aTrack );
|
||||
|
||||
if( arc->IsDegenerated() )
|
||||
{
|
||||
// Draw this very small arc like a track segment (a PCB_TRACE_T)
|
||||
PCB_TRACK track( arc->GetParent() );
|
||||
track.SetStart( arc->GetStart() );
|
||||
track.SetEnd( arc->GetEnd() );
|
||||
track.SetWidth( arc->GetWidth() );
|
||||
track.SetLayer( arc->GetLayer() );
|
||||
|
||||
createTrack( &track, aDstContainer );
|
||||
return;
|
||||
}
|
||||
|
||||
VECTOR2D center( arc->GetCenter() );
|
||||
EDA_ANGLE arc_angle = arc->GetAngle();
|
||||
double radius = arc->GetRadius();
|
||||
@@ -634,16 +639,12 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
||||
if( inner_radius3DU < 0 )
|
||||
inner_radius3DU = 0.0;
|
||||
|
||||
if( outer_radius3DU == 0.0 )
|
||||
{
|
||||
// Don't attempt to render degenerate shapes
|
||||
}
|
||||
else if( aShape->IsFilled() )
|
||||
if( aShape->IsFilled() )
|
||||
{
|
||||
aContainer->Add( new FILLED_CIRCLE_2D( center3DU, outer_radius3DU,
|
||||
*aOwner ) );
|
||||
}
|
||||
else
|
||||
else if( outer_radius3DU > inner_radius3DU )
|
||||
{
|
||||
aContainer->Add( new RING_2D( center3DU, inner_radius3DU, outer_radius3DU,
|
||||
*aOwner ) );
|
||||
@@ -791,7 +792,7 @@ void BOARD_ADAPTER::buildPadOutlineAsSegments( const PAD* aPad, CONTAINER_2D_BAS
|
||||
}
|
||||
|
||||
// For other shapes, add outlines as thick segments in polygon buffer
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon();
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon( ERROR_INSIDE );
|
||||
const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
|
||||
|
||||
for( int j = 0; j < path.PointCount(); j++ )
|
||||
|
||||
@@ -605,7 +605,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
|
||||
case PCB_TEXTBOX_T:
|
||||
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
|
||||
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
case PCB_DIM_ALIGNED_T:
|
||||
@@ -649,7 +650,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
{
|
||||
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
|
||||
|
||||
text->TransformTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -657,7 +658,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
{
|
||||
PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
|
||||
|
||||
textbox->TransformTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -958,7 +959,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
{
|
||||
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
|
||||
|
||||
text->TransformTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -966,7 +967,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
{
|
||||
PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
|
||||
|
||||
textbox->TransformTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ void BOARD_ADAPTER::buildPadOutlineAsPolygon( const PAD* aPad, SHAPE_POLY_SET& a
|
||||
}
|
||||
|
||||
// For other shapes, add outlines as thick segments in polygon buffer
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon();
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon( ERROR_INSIDE );
|
||||
const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
|
||||
|
||||
for( int ii = 0; ii < path.PointCount(); ++ii )
|
||||
|
||||
@@ -483,23 +483,21 @@ void MODEL_3D::Draw( bool aTransparent, float aOpacity, bool aUseSelectedMateria
|
||||
|
||||
// Sort from back to front
|
||||
std::sort( materialsSorted.begin(), materialsSorted.end(),
|
||||
[&]( std::pair<const MODEL_3D::MATERIAL*, float>& a,
|
||||
std::pair<const MODEL_3D::MATERIAL*, float>& b ) {
|
||||
// If A is inside B, then A is rendered first
|
||||
if( b.first->m_bbox.Inside( a.first->m_bbox ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( a.first->m_bbox.Inside( b.first->m_bbox ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
[&]( std::pair<const MODEL_3D::MATERIAL*, float>& a,
|
||||
std::pair<const MODEL_3D::MATERIAL*, float>& b )
|
||||
{
|
||||
bool aInsideB = a.first->m_bbox.Inside( b.first->m_bbox );
|
||||
bool bInsideA = b.first->m_bbox.Inside( a.first->m_bbox );
|
||||
|
||||
return a.second > b.second;
|
||||
} );
|
||||
// If A is inside B, then A is rendered first
|
||||
if( aInsideB != bInsideA )
|
||||
return bInsideA;
|
||||
|
||||
if( a.second != b.second )
|
||||
return a.second > b.second;
|
||||
|
||||
return a.first > b.first; // compare pointers as a last resort
|
||||
} );
|
||||
|
||||
for( const std::pair<const MODEL_3D::MATERIAL*, float>& mat : materialsSorted )
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <board.h>
|
||||
#include <footprint.h>
|
||||
#include "../../3d_math.h"
|
||||
#include "convert_basic_shapes_to_polygon.h"
|
||||
#include <trigo.h>
|
||||
#include <project.h>
|
||||
#include <profile.h> // To use GetRunningMicroSecs or another profiling utility
|
||||
@@ -775,6 +776,9 @@ void RENDER_3D_OPENGL::generateViasAndPads()
|
||||
{
|
||||
const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
|
||||
|
||||
if( via->GetViaType() == VIATYPE::THROUGH )
|
||||
continue; // handle with pad holes so castellation is taken into account
|
||||
|
||||
const float holediameter = via->GetDrillValue() * m_boardAdapter.BiuTo3dUnits();
|
||||
const int nrSegments = m_boardAdapter.GetCircleSegmentCount( via->GetDrillValue() );
|
||||
const float hole_inner_radius = holediameter / 2.0f;
|
||||
@@ -804,14 +808,33 @@ void RENDER_3D_OPENGL::generateViasAndPads()
|
||||
}
|
||||
|
||||
|
||||
if( m_boardAdapter.GetHoleCount() > 0 )
|
||||
if( m_boardAdapter.GetHoleCount() > 0 || m_boardAdapter.GetViaCount() > 0 )
|
||||
{
|
||||
SHAPE_POLY_SET tht_outer_holes_poly; // Stores the outer poly of the copper holes (the pad)
|
||||
SHAPE_POLY_SET tht_inner_holes_poly; // Stores the inner poly of the copper holes (the hole)
|
||||
SHAPE_POLY_SET tht_outer_holes_poly; // Stores the outer poly of the copper holes
|
||||
SHAPE_POLY_SET tht_inner_holes_poly; // Stores the inner poly of the copper holes
|
||||
|
||||
tht_outer_holes_poly.RemoveAllContours();
|
||||
tht_inner_holes_poly.RemoveAllContours();
|
||||
|
||||
// Insert through-via holes (vertical cylinders)
|
||||
for( const PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T )
|
||||
{
|
||||
const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
|
||||
|
||||
if( via->GetViaType() == VIATYPE::THROUGH )
|
||||
{
|
||||
TransformCircleToPolygon( tht_outer_holes_poly, via->GetPosition(),
|
||||
via->GetDrill() / 2 + platingThickness,
|
||||
ARC_HIGH_DEF, ERROR_INSIDE );
|
||||
|
||||
TransformCircleToPolygon( tht_inner_holes_poly, via->GetPosition(),
|
||||
via->GetDrill() / 2, ARC_HIGH_DEF, ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert pads holes (vertical cylinders)
|
||||
for( const FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
|
||||
{
|
||||
@@ -903,7 +926,9 @@ void RENDER_3D_OPENGL::Load3dModelsIfNeeded()
|
||||
load3dModels( &activityReporter );
|
||||
}
|
||||
else
|
||||
{
|
||||
load3dModels( nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -802,11 +802,14 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
{
|
||||
setLayerMaterial( layer_id );
|
||||
|
||||
OPENGL_RENDER_LIST* throughHolesOuter =
|
||||
m_boardAdapter.m_Cfg->m_Render.clip_silk_on_via_annulus
|
||||
&& m_boardAdapter.m_Cfg->m_Render.realistic
|
||||
&& ( layer_id == B_SilkS || layer_id == F_SilkS ) ? m_outerThroughHoleRings
|
||||
: m_outerThroughHoles;
|
||||
OPENGL_RENDER_LIST* throughHolesOuter = m_outerThroughHoles;
|
||||
|
||||
if( m_boardAdapter.m_Cfg->m_Render.clip_silk_on_via_annulus
|
||||
&& m_boardAdapter.m_Cfg->m_Render.realistic
|
||||
&& ( layer_id == B_SilkS || layer_id == F_SilkS ) )
|
||||
{
|
||||
throughHolesOuter = m_outerThroughHoleRings;
|
||||
}
|
||||
|
||||
if( throughHolesOuter )
|
||||
{
|
||||
@@ -824,11 +827,20 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
- pLayerDispList->GetZBot() );
|
||||
}
|
||||
|
||||
if( !skipRenderHoles
|
||||
&& m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk
|
||||
&& m_boardAdapter.m_Cfg->m_Render.realistic
|
||||
&& ( ( layer_id == B_SilkS && m_layers.find( B_Mask ) != m_layers.end() )
|
||||
|| ( layer_id == F_SilkS && m_layers.find( F_Mask ) != m_layers.end() ) ) )
|
||||
if( skipRenderHoles )
|
||||
{
|
||||
// Do not render Paste layers when skipRenderHoles is enabled
|
||||
// otherwise it will cause z-fight issues
|
||||
if( layer_id != B_Paste && layer_id != F_Paste )
|
||||
{
|
||||
pLayerDispList->DrawAllCameraCulledSubtractLayer( drawMiddleSegments,
|
||||
anti_board );
|
||||
}
|
||||
}
|
||||
else if( m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk
|
||||
&& m_boardAdapter.m_Cfg->m_Render.realistic
|
||||
&& ( ( layer_id == B_SilkS && m_layers.find( B_Mask ) != m_layers.end() )
|
||||
|| ( layer_id == F_SilkS && m_layers.find( F_Mask ) != m_layers.end() ) ) )
|
||||
{
|
||||
const PCB_LAYER_ID layerMask_id = (layer_id == B_SilkS) ? B_Mask : F_Mask;
|
||||
|
||||
@@ -838,25 +850,16 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
pLayerDispListMask,
|
||||
throughHolesOuter, anti_board );
|
||||
}
|
||||
else if( throughHolesOuter )
|
||||
{
|
||||
pLayerDispList->DrawAllCameraCulledSubtractLayer( drawMiddleSegments, nullptr,
|
||||
throughHolesOuter,
|
||||
anti_board );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !skipRenderHoles && throughHolesOuter
|
||||
&& ( layer_id == B_SilkS || layer_id == F_SilkS ) )
|
||||
{
|
||||
pLayerDispList->DrawAllCameraCulledSubtractLayer( drawMiddleSegments, nullptr,
|
||||
throughHolesOuter,
|
||||
anti_board );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not render Paste layers when skipRenderHoles is enabled
|
||||
// otherwise it will cause z-fight issues
|
||||
if( !( skipRenderHoles && ( layer_id == B_Paste || layer_id == F_Paste ) ) )
|
||||
{
|
||||
pLayerDispList->DrawAllCameraCulledSubtractLayer( drawMiddleSegments,
|
||||
anti_board );
|
||||
}
|
||||
}
|
||||
pLayerDispList->DrawAllCameraCulledSubtractLayer( drawMiddleSegments,
|
||||
anti_board );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1385,10 +1388,14 @@ void RENDER_3D_OPENGL::renderTransparentModels( const glm::mat4 &aCameraViewMatr
|
||||
|
||||
// Sort from back to front
|
||||
std::sort( transparentModelList.begin(), transparentModelList.end(),
|
||||
[&]( std::pair<const MODELTORENDER *, float>& a,
|
||||
std::pair<const MODELTORENDER *, float>& b ) {
|
||||
return a.second > b.second;
|
||||
} );
|
||||
[&]( std::pair<const MODELTORENDER *, float>& a,
|
||||
std::pair<const MODELTORENDER *, float>& b )
|
||||
{
|
||||
if( a.second != b.second )
|
||||
return a.second > b.second;
|
||||
|
||||
return a.first > b.first; // use pointers as a last resort
|
||||
} );
|
||||
|
||||
// Start rendering calls
|
||||
glPushMatrix();
|
||||
|
||||
@@ -931,10 +931,33 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
|
||||
{
|
||||
float ratio =
|
||||
std::max( 1.0f, m_objectContainer.GetBBox().GetMaxDimension() / RANGE_SCALE_3D );
|
||||
m_camera.SetMaxZoom( CAMERA::DEFAULT_MAX_ZOOM * ratio );
|
||||
|
||||
m_camera.SetMinZoom( static_cast<float>( MIN_DISTANCE_IU * m_boardAdapter.BiuTo3dUnits()
|
||||
/ -m_camera.GetCameraInitPos().z ) );
|
||||
float max_zoom = CAMERA::DEFAULT_MAX_ZOOM * ratio;
|
||||
float min_zoom = static_cast<float>( MIN_DISTANCE_IU * m_boardAdapter.BiuTo3dUnits()
|
||||
/ -m_camera.GetCameraInitPos().z );
|
||||
|
||||
if( min_zoom > max_zoom )
|
||||
std::swap( min_zoom, max_zoom );
|
||||
|
||||
float zoom_ratio = max_zoom / min_zoom;
|
||||
|
||||
// Set the minimum number of zoom 'steps' between max and min.
|
||||
int steps = 3 * 3;
|
||||
steps -= static_cast<int>( ceil( log( zoom_ratio ) / log( 1.26f ) ) );
|
||||
steps = std::max( steps, 0 );
|
||||
|
||||
// Resize max and min zoom to accomplish the number of steps.
|
||||
float increased_zoom = pow( 1.26f, steps / 2 );
|
||||
max_zoom *= increased_zoom;
|
||||
min_zoom /= increased_zoom;
|
||||
|
||||
if( steps & 1 )
|
||||
min_zoom /= 1.26f;
|
||||
|
||||
min_zoom = std::min( min_zoom, 1.0f );
|
||||
|
||||
m_camera.SetMaxZoom( max_zoom );
|
||||
m_camera.SetMinZoom( min_zoom );
|
||||
}
|
||||
|
||||
// Create an accelerator
|
||||
|
||||
@@ -1911,9 +1911,19 @@ void RENDER_3D_RAYTRACE::initializeBlockPositions()
|
||||
|
||||
const SFVEC2UI center( m_realBufferSize.x / 2, m_realBufferSize.y / 2 );
|
||||
std::sort( m_blockPositions.begin(), m_blockPositions.end(),
|
||||
[&]( const SFVEC2UI& a, const SFVEC2UI& b ) {
|
||||
[&]( const SFVEC2UI& a, const SFVEC2UI& b )
|
||||
{
|
||||
// Sort order: inside out.
|
||||
return distance( a, center ) < distance( b, center );
|
||||
float distanceA = distance( a, center );
|
||||
float distanceB = distance( b, center );
|
||||
|
||||
if( distanceA != distanceB )
|
||||
return distanceA < distanceB;
|
||||
|
||||
if( a[0] != b[0] )
|
||||
return a[0] < b[0];
|
||||
|
||||
return a[1] < b[1];
|
||||
} );
|
||||
|
||||
// Create m_shader buffer
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -26,7 +26,7 @@ PANEL_3D_RAYTRACING_OPTIONS_BASE::PANEL_3D_RAYTRACING_OPTIONS_BASE( wxWindow* pa
|
||||
|
||||
m_cbRaytracing_proceduralTextures = new wxCheckBox( this, wxID_ANY, _("Procedural textures (slow)"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cbRaytracing_proceduralTextures->SetValue(true);
|
||||
gSizer1->Add( m_cbRaytracing_proceduralTextures, 0, wxALL, 5 );
|
||||
gSizer1->Add( m_cbRaytracing_proceduralTextures, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_cbRaytracing_addFloor = new wxCheckBox( this, wxID_ANY, _("Add floor (slow)"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cbRaytracing_addFloor->SetValue(true);
|
||||
@@ -347,6 +347,7 @@ PANEL_3D_RAYTRACING_OPTIONS_BASE::PANEL_3D_RAYTRACING_OPTIONS_BASE( wxWindow* pa
|
||||
|
||||
this->SetSizer( bSizerMain );
|
||||
this->Layout();
|
||||
bSizerMain->Fit( this );
|
||||
}
|
||||
|
||||
PANEL_3D_RAYTRACING_OPTIONS_BASE::~PANEL_3D_RAYTRACING_OPTIONS_BASE()
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">PANEL_3D_RAYTRACING_OPTIONS_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">834,514</property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; forward_declare</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
@@ -190,7 +190,7 @@
|
||||
<property name="vgap">0</property>
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="0">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -103,7 +103,7 @@ class PANEL_3D_RAYTRACING_OPTIONS_BASE : public RESETTABLE_PANEL
|
||||
|
||||
public:
|
||||
|
||||
PANEL_3D_RAYTRACING_OPTIONS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 834,514 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
PANEL_3D_RAYTRACING_OPTIONS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_3D_RAYTRACING_OPTIONS_BASE();
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "panel_preview_3d_model.h"
|
||||
#include <dialogs/dialog_unit_entry.h>
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tool/tool_dispatcher.h>
|
||||
@@ -46,14 +47,14 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
FOOTPRINT* aFootprint,
|
||||
std::vector<FP_3DMODEL>* aParentModelList ) :
|
||||
PANEL_PREVIEW_3D_MODEL_BASE( aParent, wxID_ANY ),
|
||||
m_parentFrame( aFrame ),
|
||||
m_previewPane( nullptr ),
|
||||
m_infobar( nullptr ),
|
||||
m_boardAdapter(),
|
||||
m_currentCamera( m_trackBallCamera ),
|
||||
m_trackBallCamera( 2 * RANGE_SCALE_3D ),
|
||||
m_boardThickness( aFrame, nullptr, m_boardThicknessCtrl, m_boardThicknessUnits )
|
||||
m_trackBallCamera( 2 * RANGE_SCALE_3D )
|
||||
{
|
||||
m_userUnits = aFrame->GetUserUnits();
|
||||
m_userUnits = m_parentFrame->GetUserUnits();
|
||||
|
||||
m_dummyBoard = new BOARD();
|
||||
|
||||
@@ -83,6 +84,7 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
m_bpvBottom->SetBitmap( KiBitmap( BITMAPS::axis3d_bottom ) );
|
||||
m_bpvISO->SetBitmap( KiBitmap( BITMAPS::ortho ) );
|
||||
m_bpUpdate->SetBitmap( KiBitmap( BITMAPS::reload ) );
|
||||
m_bpSettings->SetBitmap( KiBitmap( BITMAPS::options_3drender ) );
|
||||
|
||||
// Set the min and max values of spin buttons (mandatory on Linux)
|
||||
// They are not used, so they are set to min and max 32 bits int values
|
||||
@@ -103,6 +105,15 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
|
||||
m_dummyFootprint = new FOOTPRINT( *aFootprint );
|
||||
m_dummyFootprint->SetParentGroup( nullptr );
|
||||
|
||||
// Ensure the footprint is shown like in Fp editor: rot 0, not flipped
|
||||
// to avoid mistakes when setting the3D shape position/rotation
|
||||
if( m_dummyFootprint->IsFlipped() )
|
||||
m_dummyFootprint->Flip( m_dummyFootprint->GetPosition(), false );
|
||||
|
||||
m_dummyFootprint->SetOrientation( ANGLE_0 );
|
||||
|
||||
|
||||
m_dummyBoard->Add( m_dummyFootprint );
|
||||
|
||||
// Create the 3D canvas
|
||||
@@ -164,6 +175,7 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
m_bpvBottom->SetMinSize( m_bpvBottom->GetSize() + borderFix );
|
||||
m_bpvISO->SetMinSize( m_bpvISO->GetSize() + borderFix );
|
||||
m_bpUpdate->SetMinSize( m_bpUpdate->GetSize() + borderFix );
|
||||
m_bpSettings->SetMinSize( m_bpSettings->GetSize() + borderFix );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -327,9 +339,6 @@ void PANEL_PREVIEW_3D_MODEL::SetSelectedModel( int idx )
|
||||
|
||||
m_opacity->SetValue( 100 );
|
||||
}
|
||||
|
||||
BOARD_DESIGN_SETTINGS dummy_bds = m_dummyBoard->GetDesignSettings();
|
||||
m_boardThickness.ChangeValue( dummy_bds.GetBoardThickness() );
|
||||
}
|
||||
|
||||
|
||||
@@ -382,16 +391,27 @@ void PANEL_PREVIEW_3D_MODEL::onOpacitySlider( wxCommandEvent& event )
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREVIEW_3D_MODEL::updateBoardThickness( wxCommandEvent& event )
|
||||
void PANEL_PREVIEW_3D_MODEL::View3DSettings( wxCommandEvent& event )
|
||||
{
|
||||
BOARD_DESIGN_SETTINGS dummy_bds = m_dummyBoard->GetDesignSettings();
|
||||
dummy_bds.SetBoardThickness( m_boardThickness.GetValue() );
|
||||
BOARD_DESIGN_SETTINGS bds = m_dummyBoard->GetDesignSettings();
|
||||
int thickness = bds.GetBoardThickness();
|
||||
|
||||
BOARD_STACKUP& dummy_board_stackup = m_dummyBoard->GetDesignSettings().GetStackupDescriptor();
|
||||
dummy_board_stackup.RemoveAll();
|
||||
dummy_board_stackup.BuildDefaultStackupList( &dummy_bds, 2 );
|
||||
WX_UNIT_ENTRY_DIALOG dlg( m_parentFrame, _( "Board Thickness: " ),
|
||||
_( "Preview Settings" ), thickness );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
||||
bds.SetBoardThickness( (int) dlg.GetValue() );
|
||||
|
||||
BOARD_STACKUP& boardStackup = m_dummyBoard->GetDesignSettings().GetStackupDescriptor();
|
||||
boardStackup.RemoveAll();
|
||||
boardStackup.BuildDefaultStackupList( &bds, 2 );
|
||||
|
||||
UpdateDummyFootprint( true );
|
||||
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -135,8 +135,6 @@ private:
|
||||
|
||||
void onOpacitySlider( wxCommandEvent& event ) override;
|
||||
|
||||
void updateBoardThickness( wxCommandEvent& event ) override;
|
||||
|
||||
void doIncrementScale( wxSpinEvent& aEvent, double aSign );
|
||||
void doIncrementRotation( wxSpinEvent& aEvent, double aSign );
|
||||
void doIncrementOffset( wxSpinEvent& aEvent, double aSign );
|
||||
@@ -174,6 +172,8 @@ private:
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
void View3DSettings( wxCommandEvent& event ) override;
|
||||
|
||||
void View3DRight( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( ID_VIEW3D_RIGHT );
|
||||
@@ -190,6 +190,7 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
PCB_BASE_FRAME* m_parentFrame;
|
||||
EDA_3D_CANVAS* m_previewPane;
|
||||
WX_INFOBAR* m_infobar;
|
||||
BOARD_ADAPTER m_boardAdapter;
|
||||
@@ -202,7 +203,6 @@ private:
|
||||
std::vector<FP_3DMODEL>* m_parentModelList;
|
||||
int m_selected; /// Index into m_parentInfoList
|
||||
|
||||
UNIT_BINDER m_boardThickness;
|
||||
EDA_UNITS m_userUnits;
|
||||
};
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
sbSizerScale = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Scale") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerScale;
|
||||
fgSizerScale = new wxFlexGridSizer( 0, 3, 3, 3 );
|
||||
fgSizerScale = new wxFlexGridSizer( 0, 3, 2, 3 );
|
||||
fgSizerScale->AddGrowableCol( 1 );
|
||||
fgSizerScale->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerScale->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
@@ -66,7 +66,7 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
sbSizerRotation = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Rotation") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerRotate;
|
||||
fgSizerRotate = new wxFlexGridSizer( 0, 3, 3, 3 );
|
||||
fgSizerRotate = new wxFlexGridSizer( 0, 3, 2, 3 );
|
||||
fgSizerRotate->AddGrowableCol( 1 );
|
||||
fgSizerRotate->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerRotate->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
@@ -111,7 +111,7 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
sbSizerOffset = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Offset") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerOffset;
|
||||
fgSizerOffset = new wxFlexGridSizer( 0, 3, 3, 3 );
|
||||
fgSizerOffset = new wxFlexGridSizer( 0, 3, 2, 3 );
|
||||
fgSizerOffset->AddGrowableCol( 1 );
|
||||
fgSizerOffset->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerOffset->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
@@ -159,20 +159,7 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
sbSizer4->Add( m_opacity, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bSizerLeft->Add( sbSizer4, 1, wxEXPAND|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbSizerBoardThickness;
|
||||
sbSizerBoardThickness = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Board Thickness") ), wxHORIZONTAL );
|
||||
|
||||
m_boardThicknessCtrl = new wxTextCtrl( sbSizerBoardThickness->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
sbSizerBoardThickness->Add( m_boardThicknessCtrl, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_boardThicknessUnits = new wxStaticText( sbSizerBoardThickness->GetStaticBox(), wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_boardThicknessUnits->Wrap( -1 );
|
||||
sbSizerBoardThickness->Add( m_boardThicknessUnits, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
|
||||
bSizerLeft->Add( sbSizerBoardThickness, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
|
||||
bSizerLeft->Add( sbSizer4, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerLeft, 0, 0, 5 );
|
||||
@@ -195,7 +182,7 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
m_SizerPanelView = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizerRight->Add( m_SizerPanelView, 1, wxEXPAND|wxBOTTOM, 8 );
|
||||
bSizerRight->Add( m_SizerPanelView, 1, wxEXPAND|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerRight, 1, wxRIGHT|wxLEFT|wxEXPAND, 5 );
|
||||
@@ -212,7 +199,7 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
bSizer3DButtons->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_bpvLeft = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvLeft, 0, wxALIGN_LEFT|wxALIGN_RIGHT|wxBOTTOM, 5 );
|
||||
bSizer3DButtons->Add( m_bpvLeft, 0, wxBOTTOM, 5 );
|
||||
|
||||
m_bpvRight = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvRight, 0, wxBOTTOM, 5 );
|
||||
@@ -237,6 +224,9 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
|
||||
bSizer3DButtons->Add( m_bpUpdate, 0, wxBOTTOM, 5 );
|
||||
|
||||
m_bpSettings = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpSettings, 0, 0, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizer3DButtons, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 5 );
|
||||
|
||||
@@ -283,8 +273,6 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::onIncrementOffset ), NULL, this );
|
||||
m_opacity->Connect( wxEVT_SLIDER, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::onOpacitySlider ), NULL, this );
|
||||
m_boardThicknessCtrl->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::onMouseWheelBoardThickness ), NULL, this );
|
||||
m_boardThicknessCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::updateBoardThickness ), NULL, this );
|
||||
m_bpvISO->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DRight ), NULL, this );
|
||||
@@ -293,6 +281,7 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
m_bpvTop->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DTop ), NULL, this );
|
||||
m_bpvBottom->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DBottom ), NULL, this );
|
||||
m_bpUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DUpdate ), NULL, this );
|
||||
m_bpSettings->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DSettings ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_PREVIEW_3D_MODEL_BASE::~PANEL_PREVIEW_3D_MODEL_BASE()
|
||||
@@ -335,8 +324,6 @@ PANEL_PREVIEW_3D_MODEL_BASE::~PANEL_PREVIEW_3D_MODEL_BASE()
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::onIncrementOffset ), NULL, this );
|
||||
m_opacity->Disconnect( wxEVT_SLIDER, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::onOpacitySlider ), NULL, this );
|
||||
m_boardThicknessCtrl->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::onMouseWheelBoardThickness ), NULL, this );
|
||||
m_boardThicknessCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::updateBoardThickness ), NULL, this );
|
||||
m_bpvISO->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DRight ), NULL, this );
|
||||
@@ -345,5 +332,6 @@ PANEL_PREVIEW_3D_MODEL_BASE::~PANEL_PREVIEW_3D_MODEL_BASE()
|
||||
m_bpvTop->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DTop ), NULL, this );
|
||||
m_bpvBottom->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DBottom ), NULL, this );
|
||||
m_bpUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DUpdate ), NULL, this );
|
||||
m_bpSettings->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL_BASE::View3DSettings ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
|
||||
<property name="permission">none</property>
|
||||
<property name="rows">0</property>
|
||||
<property name="vgap">3</property>
|
||||
<property name="vgap">2</property>
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
|
||||
@@ -686,7 +686,7 @@
|
||||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
|
||||
<property name="permission">none</property>
|
||||
<property name="rows">0</property>
|
||||
<property name="vgap">3</property>
|
||||
<property name="vgap">2</property>
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
|
||||
@@ -1279,7 +1279,7 @@
|
||||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
|
||||
<property name="permission">none</property>
|
||||
<property name="rows">0</property>
|
||||
<property name="vgap">3</property>
|
||||
<property name="vgap">2</property>
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
|
||||
@@ -1847,7 +1847,7 @@
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT</property>
|
||||
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxStaticBoxSizer" expanded="1">
|
||||
<property name="id">wxID_ANY</property>
|
||||
@@ -1925,147 +1925,6 @@
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticBoxSizer" expanded="1">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Board Thickness</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizerBoardThickness</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxTextCtrl" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="maxlength"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_boardThicknessCtrl</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="value"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnMouseWheel">onMouseWheelBoardThickness</event>
|
||||
<event name="OnText">updateBoardThickness</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">mm</property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_boardThicknessUnits</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
@@ -2150,7 +2009,7 @@
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">8</property>
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxBOTTOM</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
@@ -2257,7 +2116,7 @@
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_LEFT|wxALIGN_RIGHT|wxBOTTOM</property>
|
||||
<property name="flag">wxBOTTOM</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
@@ -2783,6 +2642,80 @@
|
||||
<event name="OnButtonClick">View3DUpdate</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag"></property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">MyButton</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_bpSettings</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">View3DSettings</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
||||
@@ -66,8 +66,6 @@ class PANEL_PREVIEW_3D_MODEL_BASE : public wxPanel
|
||||
wxTextCtrl* zoff;
|
||||
wxSpinButton* m_spinZoffset;
|
||||
wxSlider* m_opacity;
|
||||
wxTextCtrl* m_boardThicknessCtrl;
|
||||
wxStaticText* m_boardThicknessUnits;
|
||||
wxStaticText* m_previewLabel;
|
||||
wxBoxSizer* m_SizerPanelView;
|
||||
wxBitmapButton* m_bpvISO;
|
||||
@@ -78,6 +76,7 @@ class PANEL_PREVIEW_3D_MODEL_BASE : public wxPanel
|
||||
wxBitmapButton* m_bpvTop;
|
||||
wxBitmapButton* m_bpvBottom;
|
||||
wxBitmapButton* m_bpUpdate;
|
||||
wxBitmapButton* m_bpSettings;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void onMouseWheelScale( wxMouseEvent& event ) { event.Skip(); }
|
||||
@@ -91,8 +90,6 @@ class PANEL_PREVIEW_3D_MODEL_BASE : public wxPanel
|
||||
virtual void onDecrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onOpacitySlider( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onMouseWheelBoardThickness( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void updateBoardThickness( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DISO( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DLeft( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DRight( wxCommandEvent& event ) { event.Skip(); }
|
||||
@@ -101,6 +98,7 @@ class PANEL_PREVIEW_3D_MODEL_BASE : public wxPanel
|
||||
virtual void View3DTop( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DBottom( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DUpdate( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DSettings( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@@ -53,6 +53,13 @@ set( CMAKE_EXPORT_COMPILE_COMMANDS ON )
|
||||
set( KICAD_CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" )
|
||||
set( CMAKE_MODULE_PATH "${KICAD_CMAKE_MODULE_PATH}" )
|
||||
|
||||
# Create a flag to identify the non-Apple unix systems
|
||||
if( UNIX AND NOT APPLE )
|
||||
set( UNIX_NOT_APPLE ON )
|
||||
else()
|
||||
set( UNIX_NOT_APPLE OFF )
|
||||
endif()
|
||||
|
||||
# On Windows, binaries created by link option -g3 are very large (more than 1Gb for pcbnew,
|
||||
# and more than 3Gb for the full kicad suite)
|
||||
# This option create binaries using link option -g1 that create much smaller files, but
|
||||
@@ -93,6 +100,17 @@ option( KICAD_I18N_UNIX_STRICT_PATH
|
||||
"Use standard Unix locale lookup path (default OFF)."
|
||||
OFF )
|
||||
|
||||
# Options to build with flatpak platform defaults (only on Linux)
|
||||
cmake_dependent_option( KICAD_BUILD_FLATPAK
|
||||
"Build KiCad with metadata, launchers, icons, and MIME info following flatpak conventions"
|
||||
OFF "UNIX_NOT_APPLE"
|
||||
OFF )
|
||||
|
||||
cmake_dependent_option( KICAD_BUILD_NIGHTLY_FLATPAK
|
||||
"Build a Nightly flatpak (requires KICAD_BUILD_FLATPAK=ON)"
|
||||
OFF "UNIX_NOT_APPLE"
|
||||
OFF )
|
||||
|
||||
# Not supported by all platforms (for instance mingw)
|
||||
option( KICAD_SANITIZE_ADDRESS
|
||||
"Build KiCad with sanitizer options. WARNING: Not compatible with gold linker"
|
||||
@@ -483,6 +501,12 @@ if( MSVC )
|
||||
string( APPEND CMAKE_CXX_FLAGS " /EHs" )
|
||||
endif()
|
||||
|
||||
if( KICAD_SANITIZE_ADDRESS )
|
||||
add_definitions( -DKICAD_SANITIZE_ADDRESS )
|
||||
add_definitions( -D_DISABLE_VECTOR_ANNOTATION )
|
||||
string( APPEND CMAKE_CXX_FLAGS " /fsanitize=address" )
|
||||
endif()
|
||||
|
||||
foreach( type EXE SHARED MODULE)
|
||||
# /DEBUG: create PDB
|
||||
string( APPEND CMAKE_${type}_LINKER_FLAGS " /DEBUG /MANIFEST:NO" )
|
||||
|
||||
@@ -147,6 +147,7 @@ END_EVENT_TABLE()
|
||||
BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
BM2CMP_FRAME_BASE( aParent )
|
||||
{
|
||||
m_ident = FRAME_BM2CMP; // Initialized to wxID_ANY by wxFormBuilder
|
||||
SetKiway( this, aKiway );
|
||||
|
||||
for( wxString unit : { _( "mm" ), _( "Inch" ), _( "DPI" ) } )
|
||||
|
||||
@@ -37,7 +37,7 @@ unset(_Python_NAMES)
|
||||
|
||||
set(_PYTHON1_VERSIONS 1.6 1.5)
|
||||
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
||||
set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
||||
set(_PYTHON3_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
||||
|
||||
# Disabling the "search every possible place" code for now
|
||||
# see https://gitlab.com/kicad/code/kicad/-/issues/8553
|
||||
|
||||
@@ -44,7 +44,7 @@ cmake_find_frameworks(Python)
|
||||
|
||||
set(_PYTHON1_VERSIONS 1.6 1.5)
|
||||
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
||||
set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
||||
set(_PYTHON3_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
||||
|
||||
if(PythonLibs_FIND_VERSION)
|
||||
if(PythonLibs_FIND_VERSION MATCHES "^[0-9]+\\.[0-9]+(\\.[0-9]+.*)?$")
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.5" )
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.9" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -176,6 +176,7 @@ set( COMMON_WIDGET_SRCS
|
||||
widgets/footprint_preview_widget.cpp
|
||||
widgets/footprint_select_widget.cpp
|
||||
widgets/gal_options_panel.cpp
|
||||
widgets/gal_options_panel_base.cpp
|
||||
widgets/grid_bitmap_toggle.cpp
|
||||
widgets/grid_color_swatch_helpers.cpp
|
||||
widgets/grid_combobox.cpp
|
||||
@@ -216,6 +217,7 @@ set( COMMON_WIDGET_SRCS
|
||||
widgets/wx_panel.cpp
|
||||
widgets/wx_progress_reporters.cpp
|
||||
widgets/wx_splitter_window.cpp
|
||||
widgets/wx_treebook.cpp
|
||||
)
|
||||
|
||||
set( COMMON_DRAWING_SHEET_SRCS
|
||||
@@ -352,7 +354,6 @@ set( COMMON_SRCS
|
||||
lib_tree_model.cpp
|
||||
lib_tree_model_adapter.cpp
|
||||
locale_io.cpp
|
||||
lockfile.cpp
|
||||
lset.cpp
|
||||
marker_base.cpp
|
||||
markup_parser.cpp
|
||||
|
||||
@@ -49,8 +49,9 @@ void CALLBACK_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal
|
||||
int strokeWidth = GetLineWidth();
|
||||
SHAPE_POLY_SET poly;
|
||||
|
||||
// Use ERROR_INSIDE because it avoids Clipper and is therefore much faster.
|
||||
TransformOvalToPolygon( poly, pointList[ ii - 1 ], pointList[ ii ],
|
||||
strokeWidth, strokeWidth / 48, ERROR_OUTSIDE );
|
||||
strokeWidth, strokeWidth / 180, ERROR_INSIDE );
|
||||
|
||||
m_outlineCallback( poly.Outline( 0 ) );
|
||||
}
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ long KIDIALOG::getStyle( KD_TYPE aType )
|
||||
}
|
||||
|
||||
|
||||
bool OverrideLock( wxWindow* aParent, const wxString& aMessage )
|
||||
bool AskOverrideLock( wxWindow* aParent, const wxString& aMessage )
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// wxMessageDialog gets the button spacing wrong on Mac so we have to use wxRichMessageDialog.
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#include <database/database_connection.h>
|
||||
#include <database/database_cache.h>
|
||||
#include <profile.h>
|
||||
|
||||
|
||||
const char* const traceDatabase = "KICAD_DATABASE";
|
||||
@@ -89,7 +90,7 @@ DATABASE_CONNECTION::DATABASE_CONNECTION( const std::string& aDataSourceName,
|
||||
m_pass = aPassword;
|
||||
m_timeout = aTimeoutSeconds;
|
||||
|
||||
m_cache = std::make_unique<DATABASE_CACHE>( 10, 1 );
|
||||
init();
|
||||
|
||||
if( aConnectNow )
|
||||
Connect();
|
||||
@@ -103,7 +104,7 @@ DATABASE_CONNECTION::DATABASE_CONNECTION( const std::string& aConnectionString,
|
||||
m_connectionString = aConnectionString;
|
||||
m_timeout = aTimeoutSeconds;
|
||||
|
||||
m_cache = std::make_unique<DATABASE_CACHE>( 10, 1 );
|
||||
init();
|
||||
|
||||
if( aConnectNow )
|
||||
Connect();
|
||||
@@ -117,6 +118,12 @@ DATABASE_CONNECTION::~DATABASE_CONNECTION()
|
||||
}
|
||||
|
||||
|
||||
void DATABASE_CONNECTION::init()
|
||||
{
|
||||
m_cache = std::make_unique<DB_CACHE_TYPE>( 10, 1 );
|
||||
}
|
||||
|
||||
|
||||
void DATABASE_CONNECTION::SetCacheParams( int aMaxSize, int aMaxAge )
|
||||
{
|
||||
if( !m_cache )
|
||||
@@ -159,12 +166,10 @@ bool DATABASE_CONNECTION::Connect()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_tables.clear();
|
||||
|
||||
if( IsConnected() )
|
||||
{
|
||||
syncTables();
|
||||
cacheColumns();
|
||||
getQuoteChar();
|
||||
}
|
||||
|
||||
return IsConnected();
|
||||
}
|
||||
@@ -201,65 +206,55 @@ bool DATABASE_CONNECTION::IsConnected() const
|
||||
}
|
||||
|
||||
|
||||
bool DATABASE_CONNECTION::syncTables()
|
||||
bool DATABASE_CONNECTION::CacheTableInfo( const std::string& aTable,
|
||||
const std::set<std::string>& aColumns )
|
||||
{
|
||||
if( !m_conn )
|
||||
return false;
|
||||
|
||||
m_tables.clear();
|
||||
|
||||
try
|
||||
{
|
||||
nanodbc::catalog catalog( *m_conn );
|
||||
nanodbc::catalog::tables tables = catalog.find_tables();
|
||||
nanodbc::catalog::tables tables = catalog.find_tables( fromUTF8( aTable ) );
|
||||
|
||||
while( tables.next() )
|
||||
if( !tables.next() )
|
||||
{
|
||||
std::string key = toUTF8( tables.table_name() );
|
||||
m_tables[key] = toUTF8( tables.table_type() );
|
||||
wxLogTrace( traceDatabase, wxT( "CacheTableInfo: table '%s' not found in catalog" ),
|
||||
aTable );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while syncing tables: %s" ), m_lastError );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
std::string key = toUTF8( tables.table_name() );
|
||||
m_tables[key] = toUTF8( tables.table_type() );
|
||||
|
||||
|
||||
bool DATABASE_CONNECTION::cacheColumns()
|
||||
{
|
||||
if( !m_conn )
|
||||
return false;
|
||||
|
||||
m_columnCache.clear();
|
||||
|
||||
for( const auto& tableIter : m_tables )
|
||||
{
|
||||
try
|
||||
{
|
||||
nanodbc::catalog catalog( *m_conn );
|
||||
nanodbc::catalog::columns columns =
|
||||
catalog.find_columns( NANODBC_TEXT( "" ), fromUTF8( tableIter.first ) );
|
||||
catalog.find_columns( NANODBC_TEXT( "" ), tables.table_name() );
|
||||
|
||||
while( columns.next() )
|
||||
{
|
||||
std::string columnKey = toUTF8( columns.column_name() );
|
||||
m_columnCache[tableIter.first][columnKey] = columns.data_type();
|
||||
|
||||
if( aColumns.count( columnKey ) )
|
||||
m_columnCache[key][columnKey] = columns.data_type();
|
||||
}
|
||||
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while syncing columns for table %s: %s" ),
|
||||
tableIter.first, m_lastError );
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while syncing columns for table '%s': %s" ),
|
||||
key, m_lastError );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while caching table info: %s" ), m_lastError );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -291,6 +286,35 @@ bool DATABASE_CONNECTION::getQuoteChar()
|
||||
}
|
||||
|
||||
|
||||
std::string DATABASE_CONNECTION::columnsFor( const std::string& aTable )
|
||||
{
|
||||
if( !m_columnCache.count( aTable ) )
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "columnsFor: requested table %s missing from cache!" ),
|
||||
aTable );
|
||||
return "*";
|
||||
}
|
||||
|
||||
if( m_columnCache[aTable].empty() )
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "columnsFor: requested table %s has no columns mapped!" ),
|
||||
aTable );
|
||||
return "*";
|
||||
}
|
||||
|
||||
std::string ret;
|
||||
|
||||
for( const auto& [ columnName, columnType ] : m_columnCache[aTable] )
|
||||
ret += fmt::format( "{}{}{}, ", m_quoteChar, columnName, m_quoteChar );
|
||||
|
||||
// strip tailing ', '
|
||||
ret.resize( ret.length() - 2 );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//next step, make SelectOne take from the SelectAll cache if the SelectOne cache is missing.
|
||||
//To do this, need to build a map of PK->ROW for the cache result.
|
||||
bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
const std::pair<std::string, std::string>& aWhere,
|
||||
DATABASE_CONNECTION::ROW& aResult )
|
||||
@@ -311,6 +335,18 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
}
|
||||
|
||||
const std::string& tableName = tableMapIter->first;
|
||||
DB_CACHE_TYPE::CACHE_VALUE cacheEntry;
|
||||
|
||||
if( m_cache->Get( tableName, cacheEntry ) )
|
||||
{
|
||||
if( cacheEntry.count( aWhere.second ) )
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "SelectOne: `%s` with parameter `%s` - cache hit" ),
|
||||
tableName, aWhere.second );
|
||||
aResult = cacheEntry.at( aWhere.second );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_columnCache.count( tableName ) )
|
||||
{
|
||||
@@ -332,19 +368,15 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
|
||||
std::string cacheKey = fmt::format( "{}{}{}", tableName, columnName, aWhere.second );
|
||||
|
||||
std::string queryStr = fmt::format( "SELECT * FROM {}{}{} WHERE {}{}{} = ?",
|
||||
std::string queryStr = fmt::format( "SELECT {} FROM {}{}{} WHERE {}{}{} = ?",
|
||||
columnsFor( tableName ),
|
||||
m_quoteChar, tableName, m_quoteChar,
|
||||
m_quoteChar, columnName, m_quoteChar );
|
||||
|
||||
nanodbc::statement statement( *m_conn );
|
||||
nanodbc::string query = fromUTF8( queryStr );
|
||||
|
||||
if( m_cache->Get( cacheKey, aResult ) )
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "SelectOne: `%s` with parameter `%s` - cache hit" ),
|
||||
toUTF8( query ), aWhere.second );
|
||||
return true;
|
||||
}
|
||||
PROF_TIMER timer;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -384,14 +416,17 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
return false;
|
||||
}
|
||||
|
||||
timer.Stop();
|
||||
|
||||
|
||||
if( !results.first() )
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "SelectOne: no results returned from query" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
wxLogTrace( traceDatabase, wxT( "SelectOne: %ld results returned from query" ),
|
||||
results.rows() );
|
||||
wxLogTrace( traceDatabase, wxT( "SelectOne: %ld results returned from query in %0.1f ms" ),
|
||||
results.rows(), timer.msecs() );
|
||||
|
||||
aResult.clear();
|
||||
|
||||
@@ -400,7 +435,22 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
for( short i = 0; i < results.columns(); ++i )
|
||||
{
|
||||
std::string column = toUTF8( results.column_name( i ) );
|
||||
aResult[ column ] = toUTF8( results.get<nanodbc::string>( i, NANODBC_TEXT( "" ) ) );
|
||||
|
||||
switch( results.column_datatype( i ) )
|
||||
{
|
||||
case SQL_DOUBLE:
|
||||
case SQL_FLOAT:
|
||||
case SQL_REAL:
|
||||
case SQL_DECIMAL:
|
||||
case SQL_NUMERIC:
|
||||
{
|
||||
aResult[column] = fmt::format( "{:G}", results.get<double>( i ) );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
aResult[column] = toUTF8( results.get<nanodbc::string>( i, NANODBC_TEXT( "" ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
@@ -411,13 +461,12 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
return false;
|
||||
}
|
||||
|
||||
m_cache->Put( cacheKey, aResult );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, std::vector<ROW>& aResults )
|
||||
bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, const std::string& aKey,
|
||||
std::vector<ROW>& aResults )
|
||||
{
|
||||
if( !m_conn )
|
||||
{
|
||||
@@ -434,13 +483,27 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, std::vector<ROW>
|
||||
return false;
|
||||
}
|
||||
|
||||
DB_CACHE_TYPE::CACHE_VALUE cacheEntry;
|
||||
|
||||
if( m_cache->Get( aTable, cacheEntry ) )
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "SelectAll: `%s` - cache hit" ), aTable );
|
||||
|
||||
for( auto &[ key, row ] : cacheEntry )
|
||||
aResults.emplace_back( row );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nanodbc::statement statement( *m_conn );
|
||||
|
||||
nanodbc::string query = fromUTF8( fmt::format( "SELECT * FROM {}{}{}", m_quoteChar,
|
||||
tableMapIter->first, m_quoteChar ) );
|
||||
nanodbc::string query = fromUTF8( fmt::format( "SELECT {} FROM {}{}{}", columnsFor( aTable ),
|
||||
m_quoteChar, aTable, m_quoteChar ) );
|
||||
|
||||
wxLogTrace( traceDatabase, wxT( "SelectAll: `%s`" ), toUTF8( query ) );
|
||||
|
||||
PROF_TIMER timer;
|
||||
|
||||
try
|
||||
{
|
||||
statement.prepare( query );
|
||||
@@ -475,6 +538,8 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, std::vector<ROW>
|
||||
return false;
|
||||
}
|
||||
|
||||
timer.Stop();
|
||||
|
||||
try
|
||||
{
|
||||
while( results.next() )
|
||||
@@ -484,7 +549,23 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, std::vector<ROW>
|
||||
for( short j = 0; j < results.columns(); ++j )
|
||||
{
|
||||
std::string column = toUTF8( results.column_name( j ) );
|
||||
result[column] = toUTF8( results.get<nanodbc::string>( j, NANODBC_TEXT( "" ) ) );
|
||||
|
||||
switch( results.column_datatype( j ) )
|
||||
{
|
||||
case SQL_DOUBLE:
|
||||
case SQL_FLOAT:
|
||||
case SQL_REAL:
|
||||
case SQL_DECIMAL:
|
||||
case SQL_NUMERIC:
|
||||
{
|
||||
result[column] = fmt::format( "{:G}", results.get<double>( j ) );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
result[column] = toUTF8( results.get<nanodbc::string>( j,
|
||||
NANODBC_TEXT( "" ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
aResults.emplace_back( std::move( result ) );
|
||||
@@ -498,5 +579,17 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, std::vector<ROW>
|
||||
return false;
|
||||
}
|
||||
|
||||
wxLogTrace( traceDatabase, wxT( "SelectAll from %s completed in %0.1f ms" ), aTable,
|
||||
timer.msecs() );
|
||||
|
||||
for( const ROW& row : aResults )
|
||||
{
|
||||
wxASSERT( row.count( aKey ) );
|
||||
std::string keyStr = std::any_cast<std::string>( row.at( aKey ) );
|
||||
cacheEntry[keyStr] = row;
|
||||
}
|
||||
|
||||
m_cache->Put( aTable, cacheEntry );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,11 @@ DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) :
|
||||
table.symbols_col = entry["symbols"].get<std::string>();
|
||||
table.footprints_col = entry["footprints"].get<std::string>();
|
||||
|
||||
// Sanitize library display names; currently only `/` is removed because we use it
|
||||
// as a separator and allow it in symbol names.
|
||||
table.name.erase( std::remove( table.name.begin(), table.name.end(), '/' ),
|
||||
table.name.end() );
|
||||
|
||||
if( entry.contains( "properties" ) && entry["properties"].is_object() )
|
||||
{
|
||||
const nlohmann::json& pj = entry["properties"];
|
||||
|
||||
+38
-2
@@ -133,12 +133,41 @@ DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& titl
|
||||
Pgm().App().SetTopWindow( (EDA_BASE_FRAME*) kiwayHolder );
|
||||
#endif
|
||||
|
||||
Connect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_SHIM::OnPaint ) );
|
||||
Bind( wxEVT_PAINT, &DIALOG_SHIM::OnPaint, this );
|
||||
}
|
||||
|
||||
|
||||
DIALOG_SHIM::~DIALOG_SHIM()
|
||||
{
|
||||
Unbind( wxEVT_CLOSE_WINDOW, &DIALOG_SHIM::OnCloseWindow, this );
|
||||
Unbind( wxEVT_BUTTON, &DIALOG_SHIM::OnButton, this );
|
||||
Unbind( wxEVT_PAINT, &DIALOG_SHIM::OnPaint, this );
|
||||
|
||||
std::function<void( wxWindowList& )> disconnectFocusHandlers = [&]( wxWindowList& children )
|
||||
{
|
||||
for( wxWindow* child : children )
|
||||
{
|
||||
if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( child ) )
|
||||
{
|
||||
textCtrl->Disconnect( wxEVT_SET_FOCUS,
|
||||
wxFocusEventHandler( DIALOG_SHIM::onChildSetFocus ), nullptr,
|
||||
this );
|
||||
}
|
||||
else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( child ) )
|
||||
{
|
||||
scintilla->Disconnect( wxEVT_SET_FOCUS,
|
||||
wxFocusEventHandler( DIALOG_SHIM::onChildSetFocus ), nullptr,
|
||||
this );
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnectFocusHandlers( child->GetChildren() );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
disconnectFocusHandlers( GetChildren() );
|
||||
|
||||
// if the dialog is quasi-modal, this will end its event loop
|
||||
if( IsQuasiModal() )
|
||||
EndQuasiModal( wxID_CANCEL );
|
||||
@@ -282,6 +311,9 @@ bool DIALOG_SHIM::Show( bool show )
|
||||
ret = wxDialog::Show( show );
|
||||
}
|
||||
|
||||
if( m_parent )
|
||||
m_parent->SetFocus();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -483,6 +515,9 @@ int DIALOG_SHIM::ShowQuasiModal()
|
||||
|
||||
m_qmodal_showing = false;
|
||||
|
||||
if( parent )
|
||||
parent->SetFocus();
|
||||
|
||||
return GetReturnCode();
|
||||
}
|
||||
|
||||
@@ -595,7 +630,8 @@ void DIALOG_SHIM::OnCharHook( wxKeyEvent& aEvt )
|
||||
}
|
||||
}
|
||||
// shift-return (Mac default) or Ctrl-Return (GTK) for OK
|
||||
else if( aEvt.GetKeyCode() == WXK_RETURN && ( aEvt.ShiftDown() || aEvt.ControlDown() ) )
|
||||
else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER )
|
||||
&& ( aEvt.ShiftDown() || aEvt.ControlDown() ) )
|
||||
{
|
||||
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
return;
|
||||
|
||||
@@ -159,6 +159,7 @@ void PANEL_COLOR_SETTINGS::OnThemeChanged( wxCommandEvent& event )
|
||||
m_cbTheme->SetSelection( idx );
|
||||
|
||||
m_optOverrideColors->SetValue( newSettings->GetOverrideSchItemColors() );
|
||||
m_optOverrideColors->Enable( !newSettings->IsReadOnly() );
|
||||
|
||||
*m_currentSettings = *newSettings;
|
||||
updateSwatches();
|
||||
@@ -174,6 +175,7 @@ void PANEL_COLOR_SETTINGS::OnThemeChanged( wxCommandEvent& event )
|
||||
return;
|
||||
|
||||
m_optOverrideColors->SetValue( selected->GetOverrideSchItemColors() );
|
||||
m_optOverrideColors->Enable( !selected->IsReadOnly() );
|
||||
|
||||
*m_currentSettings = *selected;
|
||||
onNewThemeSelected();
|
||||
|
||||
@@ -44,9 +44,8 @@
|
||||
* Ugly as it all is, it does improve our usability on various platforms.
|
||||
*/
|
||||
|
||||
PANEL_COMMON_SETTINGS::PANEL_COMMON_SETTINGS( DIALOG_SHIM* aDialog, wxWindow* aParent )
|
||||
PANEL_COMMON_SETTINGS::PANEL_COMMON_SETTINGS( wxWindow* aParent )
|
||||
: PANEL_COMMON_SETTINGS_BASE( aParent ),
|
||||
m_dialog( aDialog ),
|
||||
m_iconScaleLabel( nullptr ),
|
||||
m_iconScaleSlider( nullptr ),
|
||||
m_iconScaleAuto( nullptr ),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -415,6 +415,7 @@ PANEL_COMMON_SETTINGS_BASE::PANEL_COMMON_SETTINGS_BASE( wxWindow* parent, wxWind
|
||||
|
||||
this->SetSizer( bPanelSizer );
|
||||
this->Layout();
|
||||
bPanelSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_textEditorBtn->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnTextEditorClick ), NULL, this );
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">PANEL_COMMON_SETTINGS_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">676,655</property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -113,7 +113,7 @@ class PANEL_COMMON_SETTINGS_BASE : public RESETTABLE_PANEL
|
||||
|
||||
public:
|
||||
|
||||
PANEL_COMMON_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 676,655 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
PANEL_COMMON_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_COMMON_SETTINGS_BASE();
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
#include <settings/settings_manager.h>
|
||||
|
||||
|
||||
PANEL_DATA_COLLECTION::PANEL_DATA_COLLECTION( PAGED_DIALOG* aDialog, wxWindow* aParent ) :
|
||||
PANEL_DATA_COLLECTION_BASE( aParent ), m_dialog( aDialog )
|
||||
PANEL_DATA_COLLECTION::PANEL_DATA_COLLECTION( wxWindow* aParent ) :
|
||||
PANEL_DATA_COLLECTION_BASE( aParent )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -47,9 +47,9 @@ bool PANEL_DATA_COLLECTION::TransferDataToWindow()
|
||||
{
|
||||
applySettingsToPanel();
|
||||
|
||||
KIPLATFORM::POLICY::STATE policyState =
|
||||
KIPLATFORM::POLICY::GetPolicyState( POLICY_KEY_DATACOLLECTION );
|
||||
if( policyState != KIPLATFORM::POLICY::STATE::NOT_CONFIGURED )
|
||||
KIPLATFORM::POLICY::PBOOL policyState =
|
||||
KIPLATFORM::POLICY::GetPolicyBool( POLICY_KEY_DATACOLLECTION );
|
||||
if( policyState != KIPLATFORM::POLICY::PBOOL::NOT_CONFIGURED )
|
||||
{
|
||||
Disable();
|
||||
}
|
||||
|
||||
@@ -26,9 +26,8 @@
|
||||
#include <wx/defs.h>
|
||||
|
||||
|
||||
PANEL_MOUSE_SETTINGS::PANEL_MOUSE_SETTINGS( PAGED_DIALOG* aDialog, wxWindow* aParent ) :
|
||||
PANEL_MOUSE_SETTINGS::PANEL_MOUSE_SETTINGS( wxWindow* aParent ) :
|
||||
PANEL_MOUSE_SETTINGS_BASE( aParent ),
|
||||
m_dialog( aDialog ),
|
||||
m_currentScrollMod( {} )
|
||||
{
|
||||
#ifdef __WXOSX_MAC__
|
||||
@@ -82,8 +81,9 @@ bool PANEL_MOUSE_SETTINGS::TransferDataFromWindow()
|
||||
|
||||
if( !isScrollModSetValid( m_currentScrollMod ) )
|
||||
{
|
||||
m_dialog->SetError( _( "Only one action can be assigned to each vertical scroll setting" ),
|
||||
this, nullptr );
|
||||
PAGED_DIALOG::GetDialog( this )->SetError( _( "Only one action can be assigned to each "
|
||||
"vertical scroll setting" ),
|
||||
this, nullptr );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -316,6 +316,7 @@ PANEL_MOUSE_SETTINGS_BASE::PANEL_MOUSE_SETTINGS_BASE( wxWindow* parent, wxWindow
|
||||
|
||||
this->SetSizer( bSizer10 );
|
||||
this->Layout();
|
||||
bSizer10->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_rbZoomNone->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( PANEL_MOUSE_SETTINGS_BASE::OnScrollRadioButton ), NULL, this );
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">PANEL_MOUSE_SETTINGS_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">609,523</property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -97,7 +97,7 @@ class PANEL_MOUSE_SETTINGS_BASE : public RESETTABLE_PANEL
|
||||
|
||||
public:
|
||||
|
||||
PANEL_MOUSE_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 609,523 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
PANEL_MOUSE_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_MOUSE_SETTINGS_BASE();
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include <widgets/wx_html_report_box.h>
|
||||
#include <widgets/wx_panel.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
#include <wx/treebook.h>
|
||||
#include <project/net_settings.h>
|
||||
|
||||
|
||||
@@ -70,13 +69,12 @@ std::vector<BITMAPS> g_lineStyleIcons;
|
||||
wxArrayString g_lineStyleNames;
|
||||
|
||||
|
||||
PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_FRAME* aFrame,
|
||||
PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( wxWindow* aParentWindow, EDA_DRAW_FRAME* aFrame,
|
||||
std::shared_ptr<NET_SETTINGS> aNetSettings,
|
||||
const std::set<wxString>& aNetNames,
|
||||
bool aIsEEschema ) :
|
||||
PANEL_SETUP_NETCLASSES_BASE( aParent->GetTreebook() ),
|
||||
PANEL_SETUP_NETCLASSES_BASE( aParentWindow ),
|
||||
m_frame( aFrame ),
|
||||
m_parent( aParent ),
|
||||
m_isEEschema( aIsEEschema ),
|
||||
m_netSettings( aNetSettings ),
|
||||
m_netNames( aNetNames ),
|
||||
@@ -121,10 +119,8 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_
|
||||
// as this initial width is sometimes strange depending on the language (wxGrid bug?)
|
||||
int const min_width = m_netclassGrid->GetVisibleWidth( i, true, true );
|
||||
|
||||
int const weighted_min_best_width =
|
||||
( i == GRID_LINESTYLE )
|
||||
? min_best_width * 3 / 2
|
||||
: min_best_width;
|
||||
int const weighted_min_best_width = ( i == GRID_LINESTYLE ) ? min_best_width * 3 / 2
|
||||
: min_best_width;
|
||||
|
||||
m_netclassGrid->SetColMinimalWidth( i, min_width );
|
||||
|
||||
@@ -158,8 +154,8 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_
|
||||
}
|
||||
|
||||
wxGridCellAttr* attr = new wxGridCellAttr;
|
||||
attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( aParent ) );
|
||||
attr->SetEditor( new GRID_CELL_COLOR_SELECTOR( aParent, m_netclassGrid ) );
|
||||
attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( PAGED_DIALOG::GetDialog( this ) ) );
|
||||
attr->SetEditor( new GRID_CELL_COLOR_SELECTOR( PAGED_DIALOG::GetDialog( this ), m_netclassGrid ) );
|
||||
m_netclassGrid->SetColAttr( GRID_SCHEMATIC_COLOR, attr );
|
||||
|
||||
attr = new wxGridCellAttr;
|
||||
@@ -174,7 +170,6 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_
|
||||
|
||||
m_netclassGrid->SetAutoEvalCols( { GRID_WIREWIDTH,
|
||||
GRID_BUSWIDTH,
|
||||
|
||||
GRID_CLEARANCE,
|
||||
GRID_TRACKSIZE,
|
||||
GRID_VIASIZE,
|
||||
@@ -327,6 +322,8 @@ bool PANEL_SETUP_NETCLASSES::TransferDataToWindow()
|
||||
row++;
|
||||
}
|
||||
|
||||
AdjustAssignmentGridColumns( GetSize().x * 3 / 5 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -428,7 +425,7 @@ bool PANEL_SETUP_NETCLASSES::validateNetclassName( int aRow, const wxString& aNa
|
||||
if( tmp.IsEmpty() )
|
||||
{
|
||||
wxString msg = _( "Netclass must have a name." );
|
||||
m_parent->SetError( msg, this, m_netclassGrid, aRow, GRID_NAME );
|
||||
PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_netclassGrid, aRow, GRID_NAME );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -437,7 +434,8 @@ bool PANEL_SETUP_NETCLASSES::validateNetclassName( int aRow, const wxString& aNa
|
||||
if( ii != aRow && m_netclassGrid->GetCellValue( ii, GRID_NAME ).CmpNoCase( tmp ) == 0 )
|
||||
{
|
||||
wxString msg = _( "Netclass name already in use." );
|
||||
m_parent->SetError( msg, this, m_netclassGrid, focusFirst ? aRow : ii, GRID_NAME );
|
||||
PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_netclassGrid,
|
||||
focusFirst ? aRow : ii, GRID_NAME );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -652,16 +650,15 @@ void PANEL_SETUP_NETCLASSES::AdjustAssignmentGridColumns( int aWidth )
|
||||
// Account for scroll bars
|
||||
aWidth -= ( m_assignmentGrid->GetSize().x - m_assignmentGrid->GetClientSize().x );
|
||||
|
||||
// Set className column width to original className width from netclasses grid
|
||||
int classNameWidth = m_originalColWidths[ 0 ];
|
||||
m_assignmentGrid->SetColSize( 1, m_originalColWidths[ 0 ] );
|
||||
int classNameWidth = 160;
|
||||
m_assignmentGrid->SetColSize( 1, classNameWidth );
|
||||
m_assignmentGrid->SetColSize( 0, std::max( aWidth - classNameWidth, classNameWidth ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_SETUP_NETCLASSES::OnSizeAssignmentGrid( wxSizeEvent& event )
|
||||
{
|
||||
AdjustAssignmentGridColumns( event.GetSize().GetX());
|
||||
AdjustAssignmentGridColumns( event.GetSize().GetX() );
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ PANEL_SETUP_NETCLASSES_BASE::PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWi
|
||||
|
||||
// Cell Defaults
|
||||
m_netclassGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
bUpperSizer->Add( m_netclassGrid, 1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 1 );
|
||||
bUpperSizer->Add( m_netclassGrid, 1, wxEXPAND|wxFIXED_MINSIZE|wxLEFT|wxRIGHT|wxTOP, 1 );
|
||||
|
||||
wxBoxSizer* buttonBoxSizer;
|
||||
buttonBoxSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
@@ -129,7 +129,7 @@ PANEL_SETUP_NETCLASSES_BASE::PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWi
|
||||
m_assignmentGrid->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_assignmentGrid->SetColSize( 0, 400 );
|
||||
m_assignmentGrid->SetColSize( 0, 270 );
|
||||
m_assignmentGrid->SetColSize( 1, 160 );
|
||||
m_assignmentGrid->EnableDragColMove( false );
|
||||
m_assignmentGrid->EnableDragColSize( true );
|
||||
@@ -147,7 +147,7 @@ PANEL_SETUP_NETCLASSES_BASE::PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWi
|
||||
|
||||
// Cell Defaults
|
||||
m_assignmentGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
bSizer14->Add( m_assignmentGrid, 2, wxEXPAND|wxLEFT, 5 );
|
||||
bSizer14->Add( m_assignmentGrid, 2, wxEXPAND|wxFIXED_MINSIZE|wxLEFT, 5 );
|
||||
|
||||
|
||||
bColumns->Add( bSizer14, 3, wxEXPAND, 5 );
|
||||
@@ -186,7 +186,6 @@ PANEL_SETUP_NETCLASSES_BASE::PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWi
|
||||
|
||||
this->SetSizer( bpanelNetClassesSizer );
|
||||
this->Layout();
|
||||
bpanelNetClassesSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_SETUP_NETCLASSES_BASE::OnUpdateUI ) );
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="name">PANEL_SETUP_NETCLASSES_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="size">700,500</property>
|
||||
<property name="subclass">; forward_declare</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
@@ -258,7 +258,7 @@
|
||||
</object>
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">1</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
|
||||
<property name="flag">wxEXPAND|wxFIXED_MINSIZE|wxLEFT|wxRIGHT|wxTOP</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxGrid" expanded="0">
|
||||
<property name="BottomDockable">1</property>
|
||||
@@ -737,7 +737,7 @@
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT</property>
|
||||
<property name="flag">wxEXPAND|wxFIXED_MINSIZE|wxLEFT</property>
|
||||
<property name="proportion">2</property>
|
||||
<object class="wxGrid" expanded="0">
|
||||
<property name="BottomDockable">1</property>
|
||||
@@ -766,7 +766,7 @@
|
||||
<property name="col_label_values">"Pattern" "Net Class"</property>
|
||||
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="cols">2</property>
|
||||
<property name="column_sizes">400,160</property>
|
||||
<property name="column_sizes">270,160</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
|
||||
@@ -69,7 +69,7 @@ class PANEL_SETUP_NETCLASSES_BASE : public wxPanel
|
||||
|
||||
public:
|
||||
|
||||
PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 700,500 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_SETUP_NETCLASSES_BASE();
|
||||
|
||||
|
||||
@@ -28,14 +28,13 @@
|
||||
#include <wx/radiobut.h>
|
||||
#include <wx/scrolwin.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/treebook.h>
|
||||
|
||||
|
||||
PANEL_SETUP_SEVERITIES::PANEL_SETUP_SEVERITIES( PAGED_DIALOG* aParent,
|
||||
PANEL_SETUP_SEVERITIES::PANEL_SETUP_SEVERITIES( wxWindow* aParentWindow,
|
||||
std::vector<std::reference_wrapper<RC_ITEM>> aItems,
|
||||
std::map<int, SEVERITY>& aSeverities,
|
||||
RC_ITEM* aPinMapSpecialCase ) :
|
||||
wxPanel( aParent->GetTreebook() ),
|
||||
wxPanel( aParentWindow ),
|
||||
m_severities( aSeverities ),
|
||||
m_items( aItems ),
|
||||
m_pinMapSpecialCase( aPinMapSpecialCase )
|
||||
@@ -162,16 +161,18 @@ void PANEL_SETUP_SEVERITIES::ImportSettingsFrom( std::map<int, SEVERITY>& aSetti
|
||||
{
|
||||
int errorCode = item.GetErrorCode();
|
||||
|
||||
if(! m_buttonMap[ errorCode ][0] ) // this entry does not actually exist
|
||||
continue;
|
||||
wxRadioButton* button = nullptr;
|
||||
|
||||
switch( aSettings[ errorCode ] )
|
||||
{
|
||||
case RPT_SEVERITY_ERROR: m_buttonMap[ errorCode ][0]->SetValue( true ); break;
|
||||
case RPT_SEVERITY_WARNING: m_buttonMap[ errorCode ][1]->SetValue( true ); break;
|
||||
case RPT_SEVERITY_IGNORE: m_buttonMap[ errorCode ][2]->SetValue( true ); break;
|
||||
default: break;
|
||||
case RPT_SEVERITY_ERROR: button = m_buttonMap[ errorCode ][0]; break;
|
||||
case RPT_SEVERITY_WARNING: button = m_buttonMap[ errorCode ][1]; break;
|
||||
case RPT_SEVERITY_IGNORE: button = m_buttonMap[ errorCode ][2]; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( button ) // this entry must actually exist
|
||||
button->SetValue( true );
|
||||
}
|
||||
|
||||
if( m_pinMapSpecialCase )
|
||||
|
||||
@@ -110,6 +110,7 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
|
||||
|
||||
EnableScrolling( false, false ); // otherwise Zoom Auto disables GAL canvas
|
||||
KIPLATFORM::UI::SetOverlayScrolling( this, false ); // Prevent excessive repaint on GTK
|
||||
KIPLATFORM::UI::ImmControl( this, false ); // Ensure our panel can't suck in IME events
|
||||
|
||||
Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), nullptr, this );
|
||||
Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), nullptr,
|
||||
@@ -365,7 +366,10 @@ void EDA_DRAW_PANEL_GAL::onSize( wxSizeEvent& aEvent )
|
||||
if( m_view )
|
||||
{
|
||||
if( infobar && infobar->IsLocked() )
|
||||
m_view->SetCenter( bottom - m_view->ToWorld( clientSize, false ) / 2.0 );
|
||||
{
|
||||
VECTOR2D halfScreen( std::ceil( 0.5 * clientSize.x ), std::ceil( 0.5 * clientSize.y ) );
|
||||
m_view->SetCenter( bottom - m_view->ToWorld( halfScreen, false ) );
|
||||
}
|
||||
|
||||
m_view->MarkTargetDirty( KIGFX::TARGET_CACHED );
|
||||
m_view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
|
||||
|
||||
@@ -106,13 +106,13 @@ void DS_DATA_ITEM::SyncDrawItems( DS_DRAW_ITEM_LIST* aCollector, KIGFX::VIEW* aV
|
||||
|
||||
for( int j = 0; j < m_RepeatCount; j++ )
|
||||
{
|
||||
if( j && ! IsInsidePage( j ) )
|
||||
if( j > 0 && !IsInsidePage( j ) )
|
||||
continue;
|
||||
|
||||
if( m_type == DS_SEGMENT )
|
||||
item = new DS_DRAW_ITEM_LINE( this, j, GetStartPosUi( j ), GetEndPosUi( j ), pensize );
|
||||
item = new DS_DRAW_ITEM_LINE( this, j, GetStartPosIU( j ), GetEndPosIU( j ), pensize );
|
||||
else if( m_type == DS_RECT )
|
||||
item = new DS_DRAW_ITEM_RECT( this, j, GetStartPosUi( j ), GetEndPosUi( j ), pensize );
|
||||
item = new DS_DRAW_ITEM_RECT( this, j, GetStartPosIU( j ), GetEndPosIU( j ), pensize );
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG( wxS( "Unknown drawing sheet item type" ) );
|
||||
@@ -162,8 +162,8 @@ void DS_DATA_ITEM::MoveTo( const VECTOR2D& aPosition )
|
||||
|
||||
for( DS_DRAW_ITEM_BASE* drawItem : m_drawItems )
|
||||
{
|
||||
drawItem->SetPosition( GetStartPosUi( drawItem->GetIndexInPeer() ) );
|
||||
drawItem->SetEnd( GetEndPosUi( drawItem->GetIndexInPeer() ) );
|
||||
drawItem->SetPosition( GetStartPosIU( drawItem->GetIndexInPeer() ) );
|
||||
drawItem->SetEnd( GetEndPosIU( drawItem->GetIndexInPeer() ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ const VECTOR2D DS_DATA_ITEM::GetStartPos( int ii ) const
|
||||
}
|
||||
|
||||
|
||||
const VECTOR2I DS_DATA_ITEM::GetStartPosUi( int ii ) const
|
||||
const VECTOR2I DS_DATA_ITEM::GetStartPosIU( int ii ) const
|
||||
{
|
||||
VECTOR2D pos = GetStartPos( ii ) * DS_DATA_MODEL::GetTheInstance().m_WSunits2Iu;
|
||||
return VECTOR2I( KiROUND( pos.x ), KiROUND( pos.y ) );
|
||||
@@ -331,7 +331,7 @@ const VECTOR2D DS_DATA_ITEM::GetEndPos( int ii ) const
|
||||
}
|
||||
|
||||
|
||||
const VECTOR2I DS_DATA_ITEM::GetEndPosUi( int ii ) const
|
||||
const VECTOR2I DS_DATA_ITEM::GetEndPosIU( int ii ) const
|
||||
{
|
||||
VECTOR2D pos = GetEndPos( ii );
|
||||
pos = pos * DS_DATA_MODEL::GetTheInstance().m_WSunits2Iu;
|
||||
@@ -343,17 +343,13 @@ bool DS_DATA_ITEM::IsInsidePage( int ii ) const
|
||||
{
|
||||
DS_DATA_MODEL& model = DS_DATA_MODEL::GetTheInstance();
|
||||
|
||||
VECTOR2D pos = GetStartPos( ii );
|
||||
|
||||
for( int kk = 0; kk < 1; kk++ )
|
||||
for( const VECTOR2D& pos : { GetStartPos( ii ), GetEndPos( ii ) } )
|
||||
{
|
||||
if( model.m_RB_Corner.x < pos.x || model.m_LT_Corner.x > pos.x )
|
||||
return false;
|
||||
|
||||
if( model.m_RB_Corner.y < pos.y || model.m_LT_Corner.y > pos.y )
|
||||
return false;
|
||||
|
||||
pos = GetEndPos( ii );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -406,11 +402,11 @@ void DS_DATA_ITEM_POLYGONS::SyncDrawItems( DS_DRAW_ITEM_LIST* aCollector, KIGFX:
|
||||
|
||||
for( int j = 0; j < m_RepeatCount; j++ )
|
||||
{
|
||||
if( j && !IsInsidePage( j ) )
|
||||
if( j > 0 && !IsInsidePage( j ) )
|
||||
continue;
|
||||
|
||||
int pensize = GetPenSizeUi();
|
||||
auto poly_shape = new DS_DRAW_ITEM_POLYPOLYGONS( this, j, GetStartPosUi( j ), pensize );
|
||||
auto poly_shape = new DS_DRAW_ITEM_POLYPOLYGONS( this, j, GetStartPosIU( j ), pensize );
|
||||
poly_shape->SetFlags( itemFlags[ j ] );
|
||||
m_drawItems.push_back( poly_shape );
|
||||
|
||||
@@ -584,7 +580,7 @@ void DS_DATA_ITEM_TEXT::SyncDrawItems( DS_DRAW_ITEM_LIST* aCollector, KIGFX::VIE
|
||||
if( j > 0 && !IsInsidePage( j ) )
|
||||
continue;
|
||||
|
||||
text = new DS_DRAW_ITEM_TEXT( this, j, m_FullText, GetStartPosUi( j ), textsize, pensize,
|
||||
text = new DS_DRAW_ITEM_TEXT( this, j, m_FullText, GetStartPosIU( j ), textsize, pensize,
|
||||
m_Font, m_Italic, m_Bold, m_TextColor );
|
||||
text->SetFlags( itemFlags[ j ] );
|
||||
m_drawItems.push_back( text );
|
||||
@@ -595,14 +591,14 @@ void DS_DATA_ITEM_TEXT::SyncDrawItems( DS_DRAW_ITEM_LIST* aCollector, KIGFX::VIE
|
||||
if( aView )
|
||||
aView->Add( text );
|
||||
|
||||
text->SetHorizJustify( m_Hjustify ) ;
|
||||
text->SetHorizJustify( m_Hjustify );
|
||||
text->SetVertJustify( m_Vjustify );
|
||||
text->SetTextAngle( EDA_ANGLE( m_Orient, DEGREES_T ) );
|
||||
text->SetMultilineAllowed( multilines );
|
||||
|
||||
// Increment label for the next text (has no meaning for multiline texts)
|
||||
if( m_RepeatCount > 1 && !multilines )
|
||||
IncrementLabel(( j + 1 ) * m_IncrementLabel );
|
||||
IncrementLabel( ( j + 1 ) * m_IncrementLabel );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -746,10 +742,10 @@ void DS_DATA_ITEM_BITMAP::SyncDrawItems( DS_DRAW_ITEM_LIST* aCollector, KIGFX::V
|
||||
|
||||
for( int j = 0; j < m_RepeatCount; j++ )
|
||||
{
|
||||
if( j && !IsInsidePage( j ) )
|
||||
if( j > 0 && !IsInsidePage( j ) )
|
||||
continue;
|
||||
|
||||
DS_DRAW_ITEM_BITMAP* bitmap = new DS_DRAW_ITEM_BITMAP( this, j, GetStartPosUi( j ) );
|
||||
DS_DRAW_ITEM_BITMAP* bitmap = new DS_DRAW_ITEM_BITMAP( this, j, GetStartPosIU( j ) );
|
||||
|
||||
bitmap->SetFlags( itemFlags[ j ] );
|
||||
m_drawItems.push_back( bitmap );
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
*
|
||||
@@ -247,13 +247,14 @@ void DS_DATA_MODEL_IO::format( DS_DATA_ITEM_TEXT* aItem, int aNestLevel ) const
|
||||
// Write font info, only if it is not the default setup
|
||||
bool write_size = aItem->m_TextSize.x != 0.0 || aItem->m_TextSize.y != 0.0;
|
||||
bool write_thickness = aItem->m_LineWidth != 0.0;
|
||||
bool write_face = aItem->m_Font && !aItem->m_Font->GetName().IsEmpty();
|
||||
|
||||
if( write_thickness || write_size || aItem->m_Bold
|
||||
|| aItem->m_Italic || aItem->m_TextColor != COLOR4D::UNSPECIFIED )
|
||||
if( write_thickness || write_size || aItem->m_Bold || aItem->m_Italic
|
||||
|| write_face || aItem->m_TextColor != COLOR4D::UNSPECIFIED )
|
||||
{
|
||||
m_out->Print( 0, " (font" );
|
||||
|
||||
if( aItem->m_Font && !aItem->m_Font->GetName().IsEmpty() )
|
||||
if( write_face )
|
||||
m_out->Print( 0, " (face \"%s\")", aItem->m_Font->NameAsToken() );
|
||||
|
||||
if( write_thickness )
|
||||
|
||||
@@ -174,6 +174,37 @@ void DS_DRAW_ITEM_TEXT::PrintWsItem( const RENDER_SETTINGS* aSettings, const VEC
|
||||
}
|
||||
|
||||
|
||||
const BOX2I DS_DRAW_ITEM_TEXT::GetApproxBBox()
|
||||
{
|
||||
// A really dumb over-approximation because doing it for real (even with the stroke font)
|
||||
// shows up large in profiles.
|
||||
|
||||
const TEXT_ATTRIBUTES& attrs = GetAttributes();
|
||||
const wxString text = GetShownText( true );
|
||||
BOX2I bbox( GetTextPos() );
|
||||
|
||||
bbox.SetWidth( (int) text.length() * attrs.m_Size.x * 1.3 );
|
||||
bbox.SetHeight( attrs.m_Size.y );
|
||||
|
||||
switch( attrs.m_Halign )
|
||||
{
|
||||
case GR_TEXT_H_ALIGN_LEFT: break;
|
||||
case GR_TEXT_H_ALIGN_CENTER: bbox.Offset( -bbox.GetWidth() / 2, 0 ); break;
|
||||
case GR_TEXT_H_ALIGN_RIGHT: bbox.Offset( -bbox.GetWidth(), 0 ); break;
|
||||
}
|
||||
|
||||
switch( GetAttributes().m_Valign )
|
||||
{
|
||||
case GR_TEXT_V_ALIGN_TOP: break;
|
||||
case GR_TEXT_V_ALIGN_CENTER: bbox.Offset( 0, -bbox.GetHeight() / 2 ); break;
|
||||
case GR_TEXT_V_ALIGN_BOTTOM: bbox.Offset( 0, -bbox.GetHeight() ); break;
|
||||
}
|
||||
|
||||
bbox.Inflate( attrs.m_Size.x, attrs.m_Size.y / 2 );
|
||||
return bbox;
|
||||
}
|
||||
|
||||
|
||||
const BOX2I DS_DRAW_ITEM_TEXT::GetBoundingBox() const
|
||||
{
|
||||
return EDA_TEXT::GetTextBox();
|
||||
|
||||
@@ -106,14 +106,22 @@ void DS_PROXY_VIEW_ITEM::ViewDraw( int aLayer, VIEW* aView ) const
|
||||
|
||||
buildDrawList( aView, m_properties, &drawList );
|
||||
|
||||
BOX2I viewport( aView->GetViewport().GetOrigin(), aView->GetViewport().GetSize() );
|
||||
|
||||
// Draw the title block normally even if the view is flipped
|
||||
bool flipped = gal->IsFlippedX();
|
||||
|
||||
if( flipped )
|
||||
{
|
||||
int pageWidth = m_pageInfo->GetWidthMils() * m_mils2IUscalefactor;
|
||||
|
||||
gal->Save();
|
||||
gal->Translate( VECTOR2D( m_pageInfo->GetWidthMils() * m_mils2IUscalefactor, 0 ) );
|
||||
gal->Translate( VECTOR2D( pageWidth, 0 ) );
|
||||
gal->Scale( VECTOR2D( -1.0, 1.0 ) );
|
||||
|
||||
int right = pageWidth - viewport.GetLeft();
|
||||
int left = right - viewport.GetWidth();
|
||||
viewport.SetOrigin( left, viewport.GetTop() );
|
||||
}
|
||||
|
||||
DS_PAINTER ws_painter( gal );
|
||||
@@ -127,7 +135,10 @@ void DS_PROXY_VIEW_ITEM::ViewDraw( int aLayer, VIEW* aView ) const
|
||||
|
||||
// Draw all the components that make the drawing sheet
|
||||
for( DS_DRAW_ITEM_BASE* item = drawList.GetFirst(); item; item = drawList.GetNext() )
|
||||
ws_painter.Draw( item, LAYER_DRAWINGSHEET );
|
||||
{
|
||||
if( viewport.Intersects( item->GetApproxBBox() ) )
|
||||
ws_painter.Draw( item, LAYER_DRAWINGSHEET );
|
||||
}
|
||||
|
||||
// Draw gray line that outlines the sheet size
|
||||
if( settings->GetShowPageLimits() )
|
||||
|
||||
+82
-43
@@ -56,13 +56,14 @@
|
||||
#include <widgets/wx_infobar.h>
|
||||
#include <widgets/wx_aui_art_providers.h>
|
||||
#include <widgets/wx_grid.h>
|
||||
#include <widgets/wx_treebook.h>
|
||||
#include <wx/app.h>
|
||||
#include <wx/config.h>
|
||||
#include <wx/display.h>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/treebook.h>
|
||||
#include <kiplatform/app.h>
|
||||
#include <kiplatform/io.h>
|
||||
#include <kiplatform/ui.h>
|
||||
|
||||
#include <functional>
|
||||
@@ -167,15 +168,28 @@ EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType, const wxS
|
||||
}
|
||||
|
||||
|
||||
wxWindow* findQuasiModalDialog( wxWindow* aParent )
|
||||
{
|
||||
for( wxWindow* child : aParent->GetChildren() )
|
||||
{
|
||||
if( DIALOG_SHIM* dlg = dynamic_cast<DIALOG_SHIM*>( child ) )
|
||||
{
|
||||
if( dlg->IsQuasiModal() )
|
||||
return dlg;
|
||||
|
||||
if( wxWindow* nestedDlg = findQuasiModalDialog( child ) )
|
||||
return nestedDlg;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
wxWindow* EDA_BASE_FRAME::findQuasiModalDialog()
|
||||
{
|
||||
for( wxWindow* iter : GetChildren() )
|
||||
{
|
||||
DIALOG_SHIM* dlg = dynamic_cast<DIALOG_SHIM*>( iter );
|
||||
|
||||
if( dlg && dlg->IsQuasiModal() )
|
||||
return dlg;
|
||||
}
|
||||
if( wxWindow* dlg = ::findQuasiModalDialog( this ) )
|
||||
return dlg;
|
||||
|
||||
// FIXME: CvPcb is currently implemented on top of KIWAY_PLAYER rather than DIALOG_SHIM,
|
||||
// so we have to look for it separately.
|
||||
@@ -1008,26 +1022,45 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
|
||||
{
|
||||
wxBeginBusyCursor( wxHOURGLASS_CURSOR );
|
||||
|
||||
PAGED_DIALOG dlg( this, _( "Preferences" ), true );
|
||||
PAGED_DIALOG dlg( this, _( "Preferences" ), true, wxEmptyString, wxSize( 980, 560 ) );
|
||||
|
||||
dlg.SetEvtHandlerEnabled( false );
|
||||
wxTreebook* book = dlg.GetTreebook();
|
||||
|
||||
WX_TREEBOOK* book = dlg.GetTreebook();
|
||||
PANEL_HOTKEYS_EDITOR* hotkeysPanel = new PANEL_HOTKEYS_EDITOR( this, book, false );
|
||||
KIFACE* kiface = nullptr;
|
||||
std::vector<int> expand;
|
||||
|
||||
Kiway().GetActions( hotkeysPanel->ActionsList() );
|
||||
|
||||
book->AddPage( new PANEL_COMMON_SETTINGS( &dlg, book ), _( "Common" ) );
|
||||
book->AddPage( new PANEL_MOUSE_SETTINGS( &dlg, book ), _( "Mouse and Touchpad" ) );
|
||||
book->AddLazyPage(
|
||||
[]( wxWindow* aParent ) -> wxWindow*
|
||||
{
|
||||
return new PANEL_COMMON_SETTINGS( aParent );
|
||||
},
|
||||
_( "Common" ) );
|
||||
|
||||
book->AddLazyPage(
|
||||
[]( wxWindow* aParent ) -> wxWindow*
|
||||
{
|
||||
return new PANEL_MOUSE_SETTINGS( aParent );
|
||||
}, _( "Mouse and Touchpad" ) );
|
||||
|
||||
book->AddPage( hotkeysPanel, _( "Hotkeys" ) );
|
||||
|
||||
#ifdef KICAD_USE_SENTRY
|
||||
book->AddPage( new PANEL_DATA_COLLECTION( &dlg, book ), _( "Data Collection" ) );
|
||||
book->AddLazyPage(
|
||||
[]( wxWindow* aParent ) -> wxWindow*
|
||||
{
|
||||
return new PANEL_DATA_COLLECTION( aParent );
|
||||
}, _( "Data Collection" ) );
|
||||
#endif
|
||||
|
||||
#define CREATE_PANEL( key ) kiface->CreateKiWindow( book, key, &Kiway() )
|
||||
#define LAZY_CTOR( key ) \
|
||||
[=]( wxWindow* aParent ) \
|
||||
{ \
|
||||
return kiface->CreateKiWindow( aParent, key, &Kiway() ); \
|
||||
}
|
||||
|
||||
// If a dll is not loaded, the loader will show an error message.
|
||||
|
||||
@@ -1041,20 +1074,19 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
|
||||
expand.push_back( book->GetPageCount() );
|
||||
|
||||
book->AddPage( new wxPanel( book ), _( "Symbol Editor" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_SYM_DISP_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_SYM_EDIT_OPTIONS ), _( "Editing Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_SYM_COLORS ), _( "Colors" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_DISP_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_EDIT_OPTIONS ), _( "Editing Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_COLORS ), _( "Colors" ) );
|
||||
|
||||
if( GetFrameType() == FRAME_SCH )
|
||||
expand.push_back( book->GetPageCount() );
|
||||
|
||||
book->AddPage( new wxPanel( book ), _( "Schematic Editor" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_SCH_DISP_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_SCH_EDIT_OPTIONS ), _( "Editing Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_SCH_ANNO_OPTIONS ), _( "Annotation Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_SCH_COLORS ), _( "Colors" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_SCH_FIELD_NAME_TEMPLATES ),
|
||||
_( "Field Name Templates" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_DISP_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_EDIT_OPTIONS ), _( "Editing Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_ANNO_OPTIONS ), _( "Annotation Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_COLORS ), _( "Colors" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_FIELD_NAME_TEMPLATES ), _( "Field Name Templates" ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
@@ -1070,29 +1102,29 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
|
||||
expand.push_back( book->GetPageCount() );
|
||||
|
||||
book->AddPage( new wxPanel( book ), _( "Footprint Editor" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_FP_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_FP_EDIT_OPTIONS ), _( "Editing Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_FP_COLORS ), _( "Colors" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_FP_DEFAULT_VALUES ), _( "Default Values" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_FP_EDIT_OPTIONS ), _( "Editing Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_FP_COLORS ), _( "Colors" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DEFAULT_VALUES ), _( "Default Values" ) );
|
||||
|
||||
if( GetFrameType() == FRAME_PCB_EDITOR )
|
||||
expand.push_back( book->GetPageCount() );
|
||||
|
||||
book->AddPage( new wxPanel( book ), _( "PCB Editor" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_PCB_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_PCB_EDIT_OPTIONS ), _( "Editing Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_PCB_COLORS ), _( "Colors" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_PCB_ACTION_PLUGINS ), _( "Action Plugins" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_PCB_ORIGINS_AXES ), _( "Origins & Axes" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_EDIT_OPTIONS ), _( "Editing Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_COLORS ), _( "Colors" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ACTION_PLUGINS ), _( "Action Plugins" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ORIGINS_AXES ), _( "Origins & Axes" ) );
|
||||
|
||||
if( GetFrameType() == FRAME_PCB_DISPLAY3D )
|
||||
expand.push_back( book->GetPageCount() );
|
||||
|
||||
book->AddPage( new wxPanel( book ), _( "3D Viewer" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_3DV_DISPLAY_OPTIONS ), _( "General" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_3DV_OPENGL ), _( "Realtime Renderer" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_3DV_RAYTRACING ), _( "Raytracing Renderer" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_3DV_COLORS ), _( "Colors" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_DISPLAY_OPTIONS ), _( "General" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_OPENGL ), _( "Realtime Renderer" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_RAYTRACING ), _( "Raytracing Renderer" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_COLORS ), _( "Colors" ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
@@ -1108,9 +1140,9 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
|
||||
expand.push_back( book->GetPageCount() );
|
||||
|
||||
book->AddPage( new wxPanel( book ), _( "Gerber Viewer" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_GBR_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_GBR_COLORS ), _( "Colors" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_GBR_EXCELLON_OPTIONS ), _( "Excellon Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_COLORS ), _( "Colors" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_EXCELLON_OPTIONS ), _( "Excellon Options" ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
@@ -1125,10 +1157,14 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
|
||||
expand.push_back( book->GetPageCount() );
|
||||
|
||||
book->AddPage( new wxPanel( book ), _( "Drawing Sheet Editor" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_DS_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_DS_COLORS ), _( "Colors" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_DS_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_DS_COLORS ), _( "Colors" ) );
|
||||
|
||||
book->AddPage( new PANEL_PCM_SETTINGS( book ), _( "Plugin and Content Manager" ) );
|
||||
book->AddLazyPage(
|
||||
[]( wxWindow* aParent ) -> wxWindow*
|
||||
{
|
||||
return new PANEL_PCM_SETTINGS( aParent );
|
||||
}, _( "Plugin and Content Manager" ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
@@ -1156,7 +1192,7 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
|
||||
dlg.Kiway().CommonSettingsChanged( false, false );
|
||||
}
|
||||
|
||||
#undef CREATE_PANEL
|
||||
#undef LAZY_CTOR
|
||||
}
|
||||
|
||||
|
||||
@@ -1268,6 +1304,9 @@ void EDA_BASE_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
|
||||
// the file name.
|
||||
if( response == wxYES )
|
||||
{
|
||||
// Preserve the permissions of the current file
|
||||
KIPLATFORM::IO::DuplicatePermissions( aFileName.GetFullPath(), autoSaveFileName.GetFullPath() );
|
||||
|
||||
if( !wxRenameFile( autoSaveFileName.GetFullPath(), aFileName.GetFullPath() ) )
|
||||
{
|
||||
wxMessageBox( _( "The auto save file could not be renamed to the board file name." ),
|
||||
|
||||
@@ -217,15 +217,31 @@ EDA_DRAW_FRAME::~EDA_DRAW_FRAME()
|
||||
|
||||
void EDA_DRAW_FRAME::ReleaseFile()
|
||||
{
|
||||
m_file_checker = nullptr;
|
||||
if( m_file_checker.get() != nullptr )
|
||||
m_file_checker->UnlockFile();
|
||||
}
|
||||
|
||||
|
||||
bool EDA_DRAW_FRAME::LockFile( const wxString& aFileName )
|
||||
{
|
||||
m_file_checker = ::LockFile( aFileName );
|
||||
// We need to explicitly reset here to get the deletion before
|
||||
// we create a new unique_ptr that may be for the same file
|
||||
m_file_checker.reset();
|
||||
|
||||
return m_file_checker && !m_file_checker->IsAnotherRunning();
|
||||
m_file_checker = std::make_unique<LOCKFILE>( aFileName );
|
||||
|
||||
if( !m_file_checker->Valid() && m_file_checker->IsLockedByMe() )
|
||||
{
|
||||
// If we cannot acquire the lock but we appear to be the one who
|
||||
// locked it, check to see if there is another KiCad instance running.
|
||||
// If there is not, then we can override the lock. This could happen if
|
||||
// KiCad crashed or was interrupted
|
||||
if( !Pgm().SingleInstance()->IsAnotherRunning() )
|
||||
m_file_checker->OverrideLock();
|
||||
}
|
||||
// If the file is valid, return true. This could mean that the file is
|
||||
// locked or it could mean that the file is read-only
|
||||
return m_file_checker->Valid();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+16
-4
@@ -114,6 +114,12 @@ wxString EDA_ITEM::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
|
||||
}
|
||||
|
||||
|
||||
bool isWordChar( const wxUniChar& c )
|
||||
{
|
||||
return wxIsalnum( c ) || c == '_';
|
||||
}
|
||||
|
||||
|
||||
bool EDA_ITEM::Matches( const wxString& aText, const EDA_SEARCH_DATA& aSearchData ) const
|
||||
{
|
||||
wxString text = aText;
|
||||
@@ -129,6 +135,12 @@ bool EDA_ITEM::Matches( const wxString& aText, const EDA_SEARCH_DATA& aSearchDat
|
||||
searchText.MakeUpper();
|
||||
}
|
||||
|
||||
auto isWordChar =
|
||||
[]( const wxUniChar& c )
|
||||
{
|
||||
return wxIsalnum( c ) || c == '_';
|
||||
};
|
||||
|
||||
if( aSearchData.matchMode == EDA_SEARCH_MATCH_MODE::WHOLEWORD )
|
||||
{
|
||||
int ii = 0;
|
||||
@@ -143,8 +155,8 @@ bool EDA_ITEM::Matches( const wxString& aText, const EDA_SEARCH_DATA& aSearchDat
|
||||
ii = next;
|
||||
next += searchText.length();
|
||||
|
||||
bool startOK = ( ii == 0 || !wxIsalnum( text.GetChar( ii - 1 ) ) );
|
||||
bool endOK = ( next == (int) text.length() || !wxIsalnum( text.GetChar( next ) ) );
|
||||
bool startOK = ( ii == 0 || !isWordChar( text.GetChar( ii - 1 ) ) );
|
||||
bool endOK = ( next == (int) text.length() || !isWordChar( text.GetChar( next ) ) );
|
||||
|
||||
if( startOK && endOK )
|
||||
return true;
|
||||
@@ -201,8 +213,8 @@ bool EDA_ITEM::Replace( const EDA_SEARCH_DATA& aSearchData, wxString& aText )
|
||||
|
||||
if( aSearchData.matchMode == EDA_SEARCH_MATCH_MODE::WHOLEWORD )
|
||||
{
|
||||
startOK = ( ii == 0 || !wxIsalnum( text.GetChar( ii - 1 ) ) );
|
||||
endOK = ( next == (int) text.length() || !wxIsalnum( text.GetChar( next ) ) );
|
||||
startOK = ( ii == 0 || !isWordChar( text.GetChar( ii - 1 ) ) );
|
||||
endOK = ( next == (int) text.length() || !isWordChar( text.GetChar( next ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -417,11 +417,11 @@ void EDA_SHAPE::RebuildBezierToSegmentsPointsList( int aMinSegLen )
|
||||
// Ensure last point respects aMinSegLen parameter
|
||||
if( m_bezierPoints.size() > 2 )
|
||||
{
|
||||
int idx = m_bezierPoints.size()-1;
|
||||
int idx = m_bezierPoints.size() - 1;
|
||||
|
||||
if( VECTOR2I( m_bezierPoints[idx] - m_bezierPoints[idx]-1 ).EuclideanNorm() < aMinSegLen )
|
||||
if( VECTOR2I( m_bezierPoints[idx] - m_bezierPoints[idx] - 1 ).EuclideanNorm() < aMinSegLen )
|
||||
{
|
||||
m_bezierPoints[idx]-1 = m_bezierPoints[idx];
|
||||
m_bezierPoints[idx - 1] = m_bezierPoints[idx];
|
||||
m_bezierPoints.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
+52
-48
@@ -91,6 +91,7 @@ GR_TEXT_V_ALIGN_T EDA_TEXT::MapVertJustify( int aVertJustify )
|
||||
EDA_TEXT::EDA_TEXT( const EDA_IU_SCALE& aIuScale, const wxString& aText ) :
|
||||
m_text( aText ),
|
||||
m_IuScale( aIuScale ),
|
||||
m_render_cache_font( nullptr ),
|
||||
m_bounding_box_cache_valid( false ),
|
||||
m_bounding_box_cache_line( -1 ),
|
||||
m_bounding_box_cache_inverted( false )
|
||||
@@ -111,8 +112,10 @@ EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText ) :
|
||||
m_attributes = aText.m_attributes;
|
||||
m_pos = aText.m_pos;
|
||||
|
||||
m_render_cache_font = aText.m_render_cache_font;
|
||||
m_render_cache_text = aText.m_render_cache_text;
|
||||
m_render_cache_angle = aText.m_render_cache_angle;
|
||||
m_render_cache_offset = aText.m_render_cache_offset;
|
||||
|
||||
m_render_cache.clear();
|
||||
|
||||
@@ -145,8 +148,10 @@ EDA_TEXT& EDA_TEXT::operator=( const EDA_TEXT& aText )
|
||||
m_attributes = aText.m_attributes;
|
||||
m_pos = aText.m_pos;
|
||||
|
||||
m_render_cache_font = aText.m_render_cache_font;
|
||||
m_render_cache_text = aText.m_render_cache_text;
|
||||
m_render_cache_angle = aText.m_render_cache_angle;
|
||||
m_render_cache_offset = aText.m_render_cache_offset;
|
||||
|
||||
m_render_cache.clear();
|
||||
|
||||
@@ -393,6 +398,9 @@ void EDA_TEXT::SetTextY( int aY )
|
||||
|
||||
void EDA_TEXT::Offset( const VECTOR2I& aOffset )
|
||||
{
|
||||
if( aOffset.x == 0 && aOffset.y == 0 )
|
||||
return;
|
||||
|
||||
m_pos += aOffset;
|
||||
|
||||
for( std::unique_ptr<KIFONT::GLYPH>& glyph : m_render_cache )
|
||||
@@ -461,24 +469,26 @@ std::vector<std::unique_ptr<KIFONT::GLYPH>>*
|
||||
EDA_TEXT::GetRenderCache( const KIFONT::FONT* aFont, const wxString& forResolvedText,
|
||||
const VECTOR2I& aOffset ) const
|
||||
{
|
||||
if( getDrawFont()->IsOutline() )
|
||||
if( aFont->IsOutline() )
|
||||
{
|
||||
EDA_ANGLE resolvedAngle = GetDrawRotation();
|
||||
|
||||
if( m_render_cache.empty()
|
||||
|| m_render_cache_font != aFont
|
||||
|| m_render_cache_text != forResolvedText
|
||||
|| m_render_cache_angle != resolvedAngle
|
||||
|| m_render_cache_offset != aOffset )
|
||||
{
|
||||
m_render_cache.clear();
|
||||
|
||||
KIFONT::OUTLINE_FONT* font = static_cast<KIFONT::OUTLINE_FONT*>( getDrawFont() );
|
||||
TEXT_ATTRIBUTES attrs = GetAttributes();
|
||||
const KIFONT::OUTLINE_FONT* font = static_cast<const KIFONT::OUTLINE_FONT*>( aFont );
|
||||
TEXT_ATTRIBUTES attrs = GetAttributes();
|
||||
|
||||
attrs.m_Angle = resolvedAngle;
|
||||
|
||||
font->GetLinesAsGlyphs( &m_render_cache, forResolvedText, GetDrawPos() + aOffset,
|
||||
attrs );
|
||||
m_render_cache_font = aFont;
|
||||
m_render_cache_angle = resolvedAngle;
|
||||
m_render_cache_text = forResolvedText;
|
||||
m_render_cache_offset = aOffset;
|
||||
@@ -553,12 +563,16 @@ BOX2I EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
||||
// bounding box will be moved later according to the actual text options
|
||||
wxSize textsize = wxSize( extents.x, extents.y );
|
||||
VECTOR2I pos = drawPos;
|
||||
int fudgeFactor = extents.y * 0.17;
|
||||
|
||||
if( font->IsStroke() )
|
||||
textsize.y += fudgeFactor;
|
||||
|
||||
if( IsMultilineAllowed() && aLine > 0 && aLine < (int) strings.GetCount() )
|
||||
pos.y -= KiROUND( aLine * font->GetInterline( fontSize.y ) );
|
||||
|
||||
if( text.Contains( wxT( "~{" ) ) )
|
||||
overbarOffset = extents.y / 14;
|
||||
overbarOffset = extents.y / 6;
|
||||
|
||||
if( aInvertY )
|
||||
pos.y = -pos.y;
|
||||
@@ -566,7 +580,7 @@ BOX2I EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
||||
bbox.SetOrigin( pos );
|
||||
|
||||
// for multiline texts and aLine < 0, merge all rectangles (aLine == -1 signals all lines)
|
||||
if( IsMultilineAllowed() && aLine < 0 && strings.GetCount() )
|
||||
if( IsMultilineAllowed() && aLine < 0 && strings.GetCount() > 1 )
|
||||
{
|
||||
for( unsigned ii = 1; ii < strings.GetCount(); ii++ )
|
||||
{
|
||||
@@ -580,6 +594,8 @@ BOX2I EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
||||
textsize.y += KiROUND( ( strings.GetCount() - 1 ) * font->GetInterline( fontSize.y ) );
|
||||
}
|
||||
|
||||
textsize.y += overbarOffset;
|
||||
|
||||
bbox.SetSize( textsize );
|
||||
|
||||
/*
|
||||
@@ -608,14 +624,16 @@ BOX2I EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
||||
switch( GetVertJustify() )
|
||||
{
|
||||
case GR_TEXT_V_ALIGN_TOP:
|
||||
bbox.Offset( 0, -fudgeFactor );
|
||||
break;
|
||||
|
||||
case GR_TEXT_V_ALIGN_CENTER:
|
||||
bbox.SetY( bbox.GetY() - ( bbox.GetHeight() + overbarOffset ) / 2 );
|
||||
bbox.SetY( bbox.GetY() - bbox.GetHeight() / 2 );
|
||||
break;
|
||||
|
||||
case GR_TEXT_V_ALIGN_BOTTOM:
|
||||
bbox.SetY( bbox.GetY() - ( bbox.GetHeight() + overbarOffset ) );
|
||||
bbox.SetY( bbox.GetY() - bbox.GetHeight() );
|
||||
bbox.Offset( 0, fudgeFactor );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -863,18 +881,33 @@ void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControl
|
||||
|
||||
|
||||
std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( bool aTriangulate,
|
||||
bool aUseTextRotation ) const
|
||||
const BOX2I& aBBox,
|
||||
const EDA_ANGLE& aAngle ) const
|
||||
{
|
||||
std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>();
|
||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||
KIFONT::FONT* font = getDrawFont();
|
||||
int penWidth = GetEffectiveTextPenWidth();
|
||||
wxString shownText( GetShownText( true ) );
|
||||
VECTOR2I drawPos = GetDrawPos();
|
||||
TEXT_ATTRIBUTES attrs = GetAttributes();
|
||||
|
||||
if( aUseTextRotation )
|
||||
attrs.m_Angle = GetDrawRotation();
|
||||
std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
|
||||
|
||||
if( aBBox.GetWidth() )
|
||||
{
|
||||
drawPos = aBBox.GetCenter();
|
||||
attrs.m_Halign = GR_TEXT_H_ALIGN_CENTER;
|
||||
attrs.m_Valign = GR_TEXT_V_ALIGN_CENTER;
|
||||
attrs.m_Angle = aAngle;
|
||||
}
|
||||
else
|
||||
attrs.m_Angle = ANGLE_0;
|
||||
{
|
||||
attrs.m_Angle = GetDrawRotation();
|
||||
|
||||
if( font->IsOutline() )
|
||||
cache = GetRenderCache( font, shownText, VECTOR2I() );
|
||||
}
|
||||
|
||||
if( aTriangulate )
|
||||
{
|
||||
@@ -896,7 +929,10 @@ std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( bool aTriangula
|
||||
shape->AddShape( triShape );
|
||||
} );
|
||||
|
||||
font->Draw( &callback_gal, GetShownText( true ), GetDrawPos(), attrs );
|
||||
if( cache )
|
||||
callback_gal.DrawGlyphs( *cache );
|
||||
else
|
||||
font->Draw( &callback_gal, shownText, drawPos, attrs );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -913,7 +949,10 @@ std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( bool aTriangula
|
||||
shape->AddShape( aPoly.Clone() );
|
||||
} );
|
||||
|
||||
font->Draw( &callback_gal, GetShownText( true ), GetDrawPos(), attrs );
|
||||
if( cache )
|
||||
callback_gal.DrawGlyphs( *cache );
|
||||
else
|
||||
font->Draw( &callback_gal, shownText, drawPos, attrs );
|
||||
}
|
||||
|
||||
return shape;
|
||||
@@ -954,41 +993,6 @@ int EDA_TEXT::Compare( const EDA_TEXT* aOther ) const
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::TransformBoundingBoxToPolygon( SHAPE_POLY_SET* aBuffer, int aClearance ) const
|
||||
{
|
||||
if( GetText().Length() == 0 )
|
||||
return;
|
||||
|
||||
VECTOR2I corners[4]; // Buffer of polygon corners
|
||||
BOX2I rect = GetTextBox();
|
||||
|
||||
// TrueType bounding boxes aren't guaranteed to include all descenders, diacriticals, etc.
|
||||
// Since we use this for zone knockouts and DRC, we need something more accurate.
|
||||
if( getDrawFont()->IsOutline() )
|
||||
rect = GetEffectiveTextShape( false, false )->BBox();
|
||||
|
||||
rect.Inflate( aClearance );
|
||||
|
||||
corners[0].x = rect.GetOrigin().x;
|
||||
corners[0].y = rect.GetOrigin().y;
|
||||
corners[1].y = corners[0].y;
|
||||
corners[1].x = rect.GetRight();
|
||||
corners[2].x = corners[1].x;
|
||||
corners[2].y = rect.GetBottom();
|
||||
corners[3].y = corners[2].y;
|
||||
corners[3].x = corners[0].x;
|
||||
|
||||
aBuffer->NewOutline();
|
||||
|
||||
for( VECTOR2I& corner : corners )
|
||||
{
|
||||
RotatePoint( corner, GetDrawPos(), GetDrawRotation() );
|
||||
|
||||
aBuffer->Append( corner.x, corner.y );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool EDA_TEXT::ValidateHyperlink( const wxString& aURL )
|
||||
{
|
||||
if( aURL.IsEmpty() || IsGotoPageHref( aURL ) )
|
||||
|
||||
+11
-3
@@ -120,10 +120,18 @@ FUTURE_FORMAT_ERROR::FUTURE_FORMAT_ERROR( const PARSE_ERROR& aParseError,
|
||||
const wxString& aRequiredVersion ) :
|
||||
PARSE_ERROR()
|
||||
{
|
||||
init( aRequiredVersion );
|
||||
if( const FUTURE_FORMAT_ERROR* ffe = dynamic_cast<const FUTURE_FORMAT_ERROR*>( &aParseError ) )
|
||||
{
|
||||
requiredVersion = ffe->requiredVersion;
|
||||
problem = ffe->Problem();
|
||||
}
|
||||
else
|
||||
{
|
||||
init( aRequiredVersion );
|
||||
|
||||
if( !aParseError.Problem().IsEmpty() )
|
||||
problem += wxS( "\n\n" ) + _( "Full error text:" ) + wxS( "\n" ) + aParseError.Problem();
|
||||
if( !aParseError.Problem().IsEmpty() )
|
||||
problem += wxS( "\n\n" ) + _( "Full error text:" ) + wxS( "\n" ) + aParseError.Problem();
|
||||
}
|
||||
|
||||
lineNumber = aParseError.lineNumber;
|
||||
byteIndex = aParseError.byteIndex;
|
||||
|
||||
@@ -253,11 +253,6 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxStri
|
||||
// first attempt to use the name as specified:
|
||||
wxString tname = aFileName;
|
||||
|
||||
#ifdef _WIN32
|
||||
// translate from KiCad's internal UNIX-like path to MSWin paths
|
||||
tname.Replace( wxT( "/" ), wxT( "\\" ) );
|
||||
#endif
|
||||
|
||||
// Note: variable expansion must preferably be performed via a threadsafe wrapper for the
|
||||
// getenv() system call. If we allow the wxFileName::Normalize() routine to perform expansion
|
||||
// then we will have a race condition since wxWidgets does not assure a threadsafe wrapper
|
||||
|
||||
@@ -347,7 +347,7 @@ VECTOR2I FONT::StringBoundaryLimits( const wxString& aText, const VECTOR2I& aSiz
|
||||
if( IsStroke() )
|
||||
{
|
||||
// Inflate by a bit more than thickness/2 to catch diacriticals, descenders, etc.
|
||||
boundingBox.Inflate( KiROUND( aThickness * 1.25 ) );
|
||||
boundingBox.Inflate( KiROUND( aThickness * 1.5 ) );
|
||||
}
|
||||
else if( IsOutline() )
|
||||
{
|
||||
|
||||
@@ -47,7 +47,6 @@ wxString FONTCONFIG::Version()
|
||||
|
||||
FONTCONFIG::FONTCONFIG()
|
||||
{
|
||||
(void) FcInitLoadConfigAndFonts();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -362,6 +362,9 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
|
||||
VECTOR2I cursor( 0, 0 );
|
||||
|
||||
if( aGlyphs )
|
||||
aGlyphs->reserve( glyphCount );
|
||||
|
||||
for( unsigned int i = 0; i < glyphCount; i++ )
|
||||
{
|
||||
// Don't process glyphs that were already included in a previous cluster
|
||||
@@ -380,7 +383,7 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
matrix.yx = (FT_Fixed) ( 0 * 0x10000L ); // Don't rotate in the y direction
|
||||
matrix.yy = (FT_Fixed) ( 1 * 0x10000L );
|
||||
|
||||
FT_Set_Transform(face, &matrix,0);
|
||||
FT_Set_Transform( face, &matrix, 0 );
|
||||
}
|
||||
|
||||
FT_Load_Glyph( face, glyphInfo[i].codepoint, FT_LOAD_NO_BITMAP );
|
||||
@@ -403,6 +406,8 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
GLYPH_POINTS points = c.m_Points;
|
||||
SHAPE_LINE_CHAIN shape;
|
||||
|
||||
shape.ReservePoints( points.size() );
|
||||
|
||||
for( const VECTOR2D& v : points )
|
||||
{
|
||||
VECTOR2D pt( v + cursor );
|
||||
@@ -447,13 +452,6 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
}
|
||||
}
|
||||
|
||||
// FONT TODO we might not want to do Fracture() here;
|
||||
// knockout text (eg. silkscreen labels with a background) will
|
||||
// need to do that after the contours have been turned into holes
|
||||
// and vice versa
|
||||
if( glyph->HasHoles() )
|
||||
glyph->Fracture( SHAPE_POLY_SET::PM_FAST ); // FONT TODO verify aFastMode
|
||||
|
||||
aGlyphs->push_back( std::move( glyph ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
|
||||
* Copyright (C) 2012-2021 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2012-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017-2018 CERN
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
@@ -537,17 +537,27 @@ void CAIRO_GAL_BASE::DrawBitmap( const BITMAP_BASE& aBitmap, double alphaBlend )
|
||||
{
|
||||
for( int col = 0; col < w; col++ )
|
||||
{
|
||||
// Build the RGB24 pixel:
|
||||
uint32_t pixel = bm_pix_buffer.GetRed( col, row ) << 16;
|
||||
pixel += bm_pix_buffer.GetGreen( col, row ) << 8;
|
||||
pixel += bm_pix_buffer.GetBlue( col, row );
|
||||
unsigned char r = bm_pix_buffer.GetRed( col, row );
|
||||
unsigned char g = bm_pix_buffer.GetGreen( col, row );
|
||||
unsigned char b = bm_pix_buffer.GetBlue( col, row );
|
||||
unsigned char a = wxALPHA_OPAQUE;
|
||||
|
||||
if( bm_pix_buffer.HasAlpha() )
|
||||
pixel += bm_pix_buffer.GetAlpha( col, row ) << 24;
|
||||
else if( bm_pix_buffer.HasMask() && pixel == mask_color )
|
||||
pixel += ( wxALPHA_TRANSPARENT << 24 );
|
||||
else
|
||||
pixel += ( wxALPHA_OPAQUE << 24 );
|
||||
{
|
||||
a = bm_pix_buffer.GetAlpha( col, row );
|
||||
|
||||
// ARGB32 format needs pre-multiplied alpha
|
||||
r = int32_t( r ) * a / 0xFF;
|
||||
g = int32_t( g ) * a / 0xFF;
|
||||
b = int32_t( b ) * a / 0xFF;
|
||||
}
|
||||
else if( bm_pix_buffer.HasMask() && ( r << 16 | g << 8 | b ) == mask_color )
|
||||
{
|
||||
a = wxALPHA_TRANSPARENT;
|
||||
}
|
||||
|
||||
// Build the ARGB24 pixel:
|
||||
uint32_t pixel = a << 24 | r << 16 | g << 8 | b;
|
||||
|
||||
// Write the pixel to the cairo image buffer:
|
||||
uint32_t* pix_ptr = (uint32_t*) pix_buffer;
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
|
||||
#include <macros.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <thread_pool.h>
|
||||
|
||||
#include <profile.h>
|
||||
#include <trace_helpers.h>
|
||||
@@ -93,9 +94,10 @@ public:
|
||||
private:
|
||||
struct CACHED_BITMAP
|
||||
{
|
||||
GLuint id;
|
||||
int w, h;
|
||||
size_t size;
|
||||
GLuint id;
|
||||
int w, h;
|
||||
size_t size;
|
||||
long long int accessTime;
|
||||
};
|
||||
|
||||
GLuint cacheBitmap( const BITMAP_BASE* aBitmap );
|
||||
@@ -104,9 +106,9 @@ private:
|
||||
const size_t m_cacheMaxSize = 256 * 1024 * 1024;
|
||||
|
||||
std::map<const KIID, CACHED_BITMAP> m_bitmaps;
|
||||
std::list<KIID> m_cacheLru;
|
||||
size_t m_cacheSize;
|
||||
std::list<GLuint> m_freedTextureIds;
|
||||
std::list<KIID> m_cacheLru;
|
||||
size_t m_cacheSize;
|
||||
std::list<GLuint> m_freedTextureIds;
|
||||
};
|
||||
|
||||
}; // namespace KIGFX
|
||||
@@ -129,6 +131,7 @@ GLuint GL_BITMAP_CACHE::RequestBitmap( const BITMAP_BASE* aBitmap )
|
||||
// A bitmap is found in cache bitmap. Ensure the associated texture is still valid.
|
||||
if( glIsTexture( it->second.id ) )
|
||||
{
|
||||
it->second.accessTime = wxGetUTCTimeMillis().GetValue();
|
||||
return it->second.id;
|
||||
}
|
||||
else
|
||||
@@ -181,56 +184,115 @@ GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap )
|
||||
m_freedTextureIds.pop_front();
|
||||
}
|
||||
|
||||
bmp.size = bmp.w * bmp.h * 4;
|
||||
auto buf = std::make_unique<uint8_t[]>( bmp.size );
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||
|
||||
for( int y = 0; y < bmp.h; y++ )
|
||||
if( imgData.HasAlpha() || imgData.HasMask() )
|
||||
{
|
||||
for( int x = 0; x < bmp.w; x++ )
|
||||
bmp.size = bmp.w * bmp.h * 4;
|
||||
auto buf = std::make_unique<uint8_t[]>( bmp.size );
|
||||
|
||||
uint8_t* dstP = buf.get();
|
||||
uint8_t* srcP = imgData.GetData();
|
||||
|
||||
long long pxCount = static_cast<long long>( bmp.w ) * bmp.h;
|
||||
|
||||
if( imgData.HasAlpha() )
|
||||
{
|
||||
uint8_t* p = buf.get() + ( bmp.w * y + x ) * 4;
|
||||
uint8_t* srcAlpha = imgData.GetAlpha();
|
||||
|
||||
p[0] = imgData.GetRed( x, y );
|
||||
p[1] = imgData.GetGreen( x, y );
|
||||
p[2] = imgData.GetBlue( x, y );
|
||||
for( long long px = 0; px < pxCount; px++ )
|
||||
{
|
||||
memcpy( dstP, srcP, 3 );
|
||||
dstP[3] = *srcAlpha;
|
||||
|
||||
if( imgData.HasAlpha() )
|
||||
p[3] = imgData.GetAlpha( x, y );
|
||||
else if( imgData.HasMask() && p[0] == imgData.GetMaskRed()
|
||||
&& p[1] == imgData.GetMaskGreen() && p[2] == imgData.GetMaskBlue() )
|
||||
p[3] = wxALPHA_TRANSPARENT;
|
||||
else
|
||||
p[3] = wxALPHA_OPAQUE;
|
||||
srcAlpha += 1;
|
||||
srcP += 3;
|
||||
dstP += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( imgData.HasMask() )
|
||||
{
|
||||
uint8_t maskRed = imgData.GetMaskRed();
|
||||
uint8_t maskGreen = imgData.GetMaskGreen();
|
||||
uint8_t maskBlue = imgData.GetMaskBlue();
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, textureID );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.w, bmp.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buf.get() );
|
||||
for( long long px = 0; px < pxCount; px++ )
|
||||
{
|
||||
memcpy( dstP, srcP, 3 );
|
||||
|
||||
if( srcP[0] == maskRed && srcP[1] == maskGreen && srcP[2] == maskBlue )
|
||||
dstP[3] = wxALPHA_TRANSPARENT;
|
||||
else
|
||||
dstP[3] = wxALPHA_OPAQUE;
|
||||
|
||||
srcP += 3;
|
||||
dstP += 4;
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, textureID );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.w, bmp.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buf.get() );
|
||||
}
|
||||
else
|
||||
{
|
||||
bmp.size = bmp.w * bmp.h * 3;
|
||||
|
||||
uint8_t* srcP = imgData.GetData();
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, textureID );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, bmp.w, bmp.h, 0, GL_RGB, GL_UNSIGNED_BYTE, srcP );
|
||||
}
|
||||
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
||||
|
||||
long long currentTime = wxGetUTCTimeMillis().GetValue();
|
||||
|
||||
bmp.id = textureID;
|
||||
bmp.accessTime = currentTime;
|
||||
|
||||
#ifndef DISABLE_BITMAP_CACHE
|
||||
m_cacheLru.emplace_back( aBitmap->GetImageID() );
|
||||
m_cacheSize += bmp.size;
|
||||
m_bitmaps.emplace( aBitmap->GetImageID(), std::move( bmp ) );
|
||||
|
||||
if( m_cacheLru.size() > m_cacheMaxElements
|
||||
|| m_cacheSize > m_cacheMaxSize )
|
||||
if( m_cacheLru.size() + 1 > m_cacheMaxElements || m_cacheSize + bmp.size > m_cacheMaxSize )
|
||||
{
|
||||
KIID last = m_cacheLru.front();
|
||||
CACHED_BITMAP& cachedBitmap = m_bitmaps[last];
|
||||
KIID toRemove( 0 );
|
||||
auto toRemoveLru = m_cacheLru.end();
|
||||
|
||||
// Remove entries accessed > 1s ago first
|
||||
for( const auto& [kiid, cachedBmp] : m_bitmaps )
|
||||
{
|
||||
const int cacheTimeoutMillis = 1000L;
|
||||
|
||||
if( currentTime - cachedBmp.accessTime > cacheTimeoutMillis )
|
||||
{
|
||||
toRemove = kiid;
|
||||
toRemoveLru = std::find( m_cacheLru.begin(), m_cacheLru.end(), toRemove );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, remove the latest entry (it's less likely to be needed soon)
|
||||
if( toRemove == niluuid )
|
||||
{
|
||||
toRemoveLru = m_cacheLru.end();
|
||||
toRemoveLru--;
|
||||
|
||||
toRemove = *toRemoveLru;
|
||||
}
|
||||
|
||||
CACHED_BITMAP& cachedBitmap = m_bitmaps[toRemove];
|
||||
|
||||
m_cacheSize -= cachedBitmap.size;
|
||||
glDeleteTextures( 1, &cachedBitmap.id );
|
||||
m_freedTextureIds.emplace_back( cachedBitmap.id );
|
||||
|
||||
m_bitmaps.erase( last );
|
||||
m_cacheLru.pop_front();
|
||||
m_bitmaps.erase( toRemove );
|
||||
m_cacheLru.erase( toRemoveLru );
|
||||
}
|
||||
|
||||
m_cacheLru.emplace_back( aBitmap->GetImageID() );
|
||||
m_cacheSize += bmp.size;
|
||||
m_bitmaps.emplace( aBitmap->GetImageID(), std::move( bmp ) );
|
||||
#endif
|
||||
|
||||
return textureID;
|
||||
@@ -259,11 +321,17 @@ OPENGL_GAL::OPENGL_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent,
|
||||
{
|
||||
m_glMainContext = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
|
||||
if( !m_glMainContext )
|
||||
throw std::runtime_error( "Could not create the main OpenGL context" );
|
||||
|
||||
m_glPrivContext = m_glMainContext;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_glPrivContext = GL_CONTEXT_MANAGER::Get().CreateCtx( this, m_glMainContext );
|
||||
|
||||
if( !m_glPrivContext )
|
||||
throw std::runtime_error( "Could not create a private OpenGL context" );
|
||||
}
|
||||
|
||||
m_shader = new SHADER();
|
||||
@@ -1104,13 +1172,21 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
|
||||
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b,
|
||||
m_strokeColor.a );
|
||||
|
||||
std::deque<VECTOR2D> pointList;
|
||||
pointList.push_back( aStartPoint );
|
||||
pointList.push_back( diagonalPointA );
|
||||
pointList.push_back( aEndPoint );
|
||||
pointList.push_back( diagonalPointB );
|
||||
pointList.push_back( aStartPoint );
|
||||
DrawPolyline( pointList );
|
||||
// DrawLine (and DrawPolyline )
|
||||
// has problem with 0 length lines so enforce minimum
|
||||
if( aStartPoint == aEndPoint )
|
||||
DrawLine( aStartPoint + VECTOR2D( 1.0, 0.0 ), aEndPoint );
|
||||
else
|
||||
{
|
||||
std::deque<VECTOR2D> pointList;
|
||||
|
||||
pointList.push_back( aStartPoint );
|
||||
pointList.push_back( diagonalPointA );
|
||||
pointList.push_back( aEndPoint );
|
||||
pointList.push_back( diagonalPointB );
|
||||
pointList.push_back( aStartPoint );
|
||||
DrawPolyline( pointList );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2250,13 +2326,13 @@ void OPENGL_GAL::drawSegmentChain( const std::function<VECTOR2D( int )>& aPointG
|
||||
auto start = aPointGetter( i - 1 );
|
||||
auto end = aPointGetter( i );
|
||||
|
||||
VECTOR2D startEndVector = start - end;
|
||||
VECTOR2D startEndVector = end - start;
|
||||
double lineLength = startEndVector.EuclideanNorm();
|
||||
|
||||
float startx = start.x;
|
||||
float starty = end.y;
|
||||
float starty = start.y;
|
||||
float endx = start.x + lineLength;
|
||||
float endy = end.y + lineLength;
|
||||
float endy = start.y + lineLength;
|
||||
|
||||
// Be careful about floating point rounding. As we draw segments in larger and larger
|
||||
// coordinates, the shader (which uses floats) will lose precision and stop drawing small
|
||||
@@ -2532,16 +2608,8 @@ void OPENGL_GAL::init()
|
||||
#endif /* wxCHECK_VERSION( 3, 0, 3 ) */
|
||||
|
||||
// Check correct initialization from the constructor
|
||||
if( !m_glMainContext )
|
||||
throw std::runtime_error( "Could not create the main OpenGL context" );
|
||||
|
||||
if( !m_glPrivContext )
|
||||
throw std::runtime_error( "Could not create a private OpenGL context" );
|
||||
|
||||
if( m_tesselator == nullptr )
|
||||
throw std::runtime_error( "Could not create the m_tesselator" );
|
||||
// End initialization checks
|
||||
|
||||
throw std::runtime_error( "Could not create the tesselator" );
|
||||
GLenum err = glewInit();
|
||||
|
||||
if( GLEW_OK != err )
|
||||
@@ -2781,15 +2849,31 @@ void OPENGL_GAL::DrawGlyphs( const std::vector<std::unique_ptr<KIFONT::GLYPH>>&
|
||||
// Optimized path for stroke fonts that pre-reserves glyph triangles.
|
||||
int triangleCount = 0;
|
||||
|
||||
if( aGlyphs.size() > 0 )
|
||||
{
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
|
||||
tp.push_loop( aGlyphs.size(),
|
||||
[&]( const int a, const int b)
|
||||
{
|
||||
for( int ii = a; ii < b; ++ii )
|
||||
{
|
||||
auto glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( aGlyphs.at( ii ).get() );
|
||||
|
||||
// Only call CacheTriangulation() if it has never been done before.
|
||||
// Otherwise we'll hash the triangulation to see if it has been edited,
|
||||
// and all our glpyh editing ops update the triangulation anyway.
|
||||
if( glyph->TriangulatedPolyCount() == 0 )
|
||||
glyph->CacheTriangulation( false );
|
||||
}
|
||||
} );
|
||||
tp.wait_for_tasks();
|
||||
}
|
||||
|
||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
|
||||
{
|
||||
const auto& outlineGlyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( *glyph );
|
||||
|
||||
// Only call CacheTriangulation if it has never been done before. Otherwise we'll hash
|
||||
// the triangulation to see if it has been edited, and glyphs after creation are read-only.
|
||||
if( outlineGlyph.TriangulatedPolyCount() == 0 )
|
||||
const_cast<KIFONT::OUTLINE_GLYPH&>( outlineGlyph ).CacheTriangulation( false );
|
||||
|
||||
for( unsigned int i = 0; i < outlineGlyph.TriangulatedPolyCount(); i++ )
|
||||
{
|
||||
const SHAPE_POLY_SET::TRIANGULATED_POLYGON* polygon =
|
||||
|
||||
+72
-12
@@ -38,6 +38,7 @@
|
||||
#include <gestfich.h>
|
||||
#include <string_utils.h>
|
||||
#include <launch_ext.h>
|
||||
#include "wx/tokenzr.h"
|
||||
|
||||
void QuoteString( wxString& string )
|
||||
{
|
||||
@@ -114,22 +115,78 @@ wxString FindKicadFile( const wxString& shortname )
|
||||
|
||||
int ExecuteFile( const wxString& aEditorName, const wxString& aFileName, wxProcess *aCallback )
|
||||
{
|
||||
wxString fullEditorName;
|
||||
wxString param;
|
||||
wxString fullEditorName;
|
||||
std::vector<wxString> params;
|
||||
|
||||
#ifdef __UNIX__
|
||||
int space = aEditorName.Find( ' ' );
|
||||
wxString param;
|
||||
bool inSingleQuotes = false;
|
||||
bool inDoubleQuotes = false;
|
||||
|
||||
if( space > 0 && !aEditorName.Contains( "\"" ) && !aEditorName.Contains( "\'" ) )
|
||||
auto pushParam =
|
||||
[&]()
|
||||
{
|
||||
if( !param.IsEmpty() )
|
||||
{
|
||||
params.push_back( param );
|
||||
param.clear();
|
||||
}
|
||||
};
|
||||
|
||||
for( wxUniChar ch : aEditorName )
|
||||
{
|
||||
fullEditorName = FindKicadFile( aEditorName.Mid( 0, space ) );
|
||||
param = aEditorName.Mid( space + 1 );
|
||||
if( inSingleQuotes )
|
||||
{
|
||||
if( ch == '\'' )
|
||||
{
|
||||
pushParam();
|
||||
inSingleQuotes = false;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
param += ch;
|
||||
}
|
||||
}
|
||||
else if( inDoubleQuotes )
|
||||
{
|
||||
if( ch == '"' )
|
||||
{
|
||||
pushParam();
|
||||
inDoubleQuotes = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
param += ch;
|
||||
}
|
||||
}
|
||||
else if( ch == '\'' )
|
||||
{
|
||||
pushParam();
|
||||
inSingleQuotes = true;
|
||||
}
|
||||
else if( ch == '"' )
|
||||
{
|
||||
pushParam();
|
||||
inDoubleQuotes = true;
|
||||
}
|
||||
else if( ch == ' ' )
|
||||
{
|
||||
pushParam();
|
||||
}
|
||||
else
|
||||
{
|
||||
param += ch;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
pushParam();
|
||||
|
||||
fullEditorName = FindKicadFile( params[0] );
|
||||
params.erase( params.begin() );
|
||||
#else
|
||||
fullEditorName = FindKicadFile( aEditorName );
|
||||
#endif
|
||||
{
|
||||
fullEditorName = FindKicadFile( aEditorName );
|
||||
}
|
||||
|
||||
if( wxFileExists( fullEditorName ) )
|
||||
{
|
||||
@@ -138,8 +195,11 @@ int ExecuteFile( const wxString& aEditorName, const wxString& aFileName, wxProce
|
||||
|
||||
args[i++] = fullEditorName.wc_str();
|
||||
|
||||
if( !param.IsEmpty() )
|
||||
args[i++] = param.wc_str();
|
||||
if( !params.empty() )
|
||||
{
|
||||
for( const wxString& p : params )
|
||||
args[i++] = p.wc_str();
|
||||
}
|
||||
|
||||
if( !aFileName.IsEmpty() )
|
||||
args[i++] = aFileName.wc_str();
|
||||
|
||||
@@ -87,7 +87,7 @@ void GL_CONTEXT_MANAGER::DeleteAll()
|
||||
|
||||
void GL_CONTEXT_MANAGER::LockCtx( wxGLContext* aContext, wxGLCanvas* aCanvas )
|
||||
{
|
||||
wxCHECK( aCanvas || m_glContexts.count( aContext ) > 0, /* void */ );
|
||||
wxCHECK( aContext && m_glContexts.count( aContext ) > 0, /* void */ );
|
||||
|
||||
m_glCtxMutex.lock();
|
||||
wxGLCanvas* canvas = aCanvas ? aCanvas : m_glContexts.at( aContext );
|
||||
@@ -106,7 +106,7 @@ void GL_CONTEXT_MANAGER::LockCtx( wxGLContext* aContext, wxGLCanvas* aCanvas )
|
||||
|
||||
void GL_CONTEXT_MANAGER::UnlockCtx( wxGLContext* aContext )
|
||||
{
|
||||
wxCHECK( m_glContexts.count( aContext ) > 0, /* void */ );
|
||||
wxCHECK( aContext && m_glContexts.count( aContext ) > 0, /* void */ );
|
||||
|
||||
if( m_glCtx == aContext )
|
||||
{
|
||||
|
||||
@@ -94,7 +94,10 @@ void GRSetColorPen( wxDC* DC, const COLOR4D& Color, int width, wxPenStyle style
|
||||
// wxWidgets will enforce a minimum pen width when printing, so we have to make the pen
|
||||
// transparent when we don't want the object stroked.
|
||||
if( width == 0 )
|
||||
{
|
||||
color = COLOR4D::UNSPECIFIED;
|
||||
style = wxPENSTYLE_TRANSPARENT;
|
||||
}
|
||||
|
||||
const wxPen& curr_pen = DC->GetPen();
|
||||
|
||||
|
||||
@@ -726,18 +726,16 @@ void GRID_TRICKS::paste_text( const wxString& cb_text )
|
||||
wxStringTokenizer cols( rowTxt, COL_SEP, wxTOKEN_RET_EMPTY );
|
||||
|
||||
if( !is_selection )
|
||||
{
|
||||
end_col = cur_col + cols.CountTokens();
|
||||
|
||||
if( end_col > tbl->GetNumberCols() )
|
||||
end_col = tbl->GetNumberCols();
|
||||
}
|
||||
|
||||
for( int col = start_col; col < end_col; ++col )
|
||||
for( int col = start_col; col < end_col && col < tbl->GetNumberCols(); ++col )
|
||||
{
|
||||
// Skip hidden columns
|
||||
if( !m_grid->IsColShown( col ) )
|
||||
{
|
||||
end_col++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If number of selected cols is larger than the count of cols on the clipboard,
|
||||
// paste again and again until the end of the selection is reached.
|
||||
|
||||
@@ -39,6 +39,8 @@ public:
|
||||
m_includeNetlistAttributes( true ),
|
||||
m_useX2Format( true ),
|
||||
m_disableApertureMacros( false ),
|
||||
m_useAuxOrigin( false ),
|
||||
m_useProtelFileExtension( true ),
|
||||
m_precision( 5 ),
|
||||
m_printMaskLayer()
|
||||
{
|
||||
@@ -59,6 +61,8 @@ public:
|
||||
bool m_includeNetlistAttributes;
|
||||
bool m_useX2Format;
|
||||
bool m_disableApertureMacros;
|
||||
bool m_useAuxOrigin;
|
||||
bool m_useProtelFileExtension;
|
||||
|
||||
int m_precision;
|
||||
|
||||
@@ -66,4 +70,4 @@ public:
|
||||
LSET m_printMaskLayer;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,9 @@ public:
|
||||
m_filename(),
|
||||
m_outputFile(),
|
||||
m_colorTheme(),
|
||||
m_mirror( false ),
|
||||
m_blackAndWhite( false ),
|
||||
m_negative( false ),
|
||||
m_plotFootprintValues( true ),
|
||||
m_plotRefDes( true ),
|
||||
m_plotBorderTitleBlocks( false ),
|
||||
@@ -45,12 +47,19 @@ public:
|
||||
wxString m_outputFile;
|
||||
wxString m_colorTheme;
|
||||
|
||||
bool m_mirror;
|
||||
bool m_blackAndWhite;
|
||||
bool m_negative;
|
||||
bool m_plotFootprintValues;
|
||||
bool m_plotRefDes;
|
||||
bool m_plotBorderTitleBlocks;
|
||||
|
||||
LSET m_printMaskLayer;
|
||||
|
||||
// How holes in pads/vias are plotted:
|
||||
// 0 = no hole, 1 = small shape, 2 = actual shape
|
||||
// Not used in some plotters (Gerber)
|
||||
int m_drillShapeOption;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
m_outputFile(),
|
||||
m_xOrigin( 0.0 ),
|
||||
m_yOrigin( 0.0 ),
|
||||
m_minDistance( 0.01 ) // 0.01 mm is a good value to connect 2 items of the board outlines
|
||||
m_boardOutlinesChainingEpsilon( 0.01 ) // 0.01 mm is a good value to connect 2 items of the board outlines
|
||||
{
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
wxString m_outputFile;
|
||||
double m_xOrigin;
|
||||
double m_yOrigin;
|
||||
double m_minDistance;
|
||||
double m_boardOutlinesChainingEpsilon;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -30,7 +30,8 @@ class JOB_EXPORT_PCB_SVG : public JOB
|
||||
public:
|
||||
JOB_EXPORT_PCB_SVG( bool aIsCli ) :
|
||||
JOB( "svg", aIsCli ), m_filename(), m_outputFile(), m_colorTheme(), m_mirror( false ),
|
||||
m_blackAndWhite( false ), m_plotDrawingSheet( true ), m_pageSizeMode( 0 ), m_printMaskLayer()
|
||||
m_blackAndWhite( false ), m_negative( false ), m_plotDrawingSheet( true ),
|
||||
m_pageSizeMode( 0 ), m_printMaskLayer()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,11 +41,17 @@ public:
|
||||
|
||||
bool m_mirror;
|
||||
bool m_blackAndWhite;
|
||||
bool m_negative;
|
||||
|
||||
bool m_plotDrawingSheet;
|
||||
int m_pageSizeMode;
|
||||
|
||||
LSET m_printMaskLayer;
|
||||
|
||||
// How holes in pads/vias are plotted:
|
||||
// 0 = no hole, 1 = small shape, 2 = actual shape
|
||||
// Not used in some plotters (Gerber)
|
||||
int m_drillShapeOption;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef JOB_EXPORT_SCH_PDF_H
|
||||
#define JOB_EXPORT_SCH_PDF_H
|
||||
|
||||
#include <wx/string.h>
|
||||
#include "job.h"
|
||||
|
||||
class JOB_EXPORT_SCH_PDF : public JOB
|
||||
{
|
||||
public:
|
||||
JOB_EXPORT_SCH_PDF( bool aIsCli ) :
|
||||
JOB( "pdf", aIsCli ),
|
||||
m_filename(),
|
||||
m_outputFile(),
|
||||
m_blackAndWhite( false ),
|
||||
m_useBackgroundColor( false ),
|
||||
m_plotDrawingSheet( false )
|
||||
{
|
||||
}
|
||||
|
||||
wxString m_filename;
|
||||
wxString m_outputFile;
|
||||
wxString m_colorTheme;
|
||||
|
||||
bool m_blackAndWhite;
|
||||
bool m_useBackgroundColor;
|
||||
bool m_plotDrawingSheet;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -18,21 +18,24 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef COMMAND_EXPORT_SCH_SVG_H
|
||||
#define COMMAND_EXPORT_SCH_SVG_H
|
||||
#ifndef JOB_EXPORT_SCH_PLOT_H
|
||||
#define JOB_EXPORT_SCH_PLOT_H
|
||||
|
||||
#include "command_export_pcb_base.h"
|
||||
#include <wx/string.h>
|
||||
#include <plotters/plotter.h>
|
||||
#include "job.h"
|
||||
|
||||
namespace CLI
|
||||
{
|
||||
class EXPORT_SCH_SVG_COMMAND : public EXPORT_PCB_BASE_COMMAND
|
||||
class JOB_EXPORT_SCH_PLOT : public JOB
|
||||
{
|
||||
public:
|
||||
EXPORT_SCH_SVG_COMMAND();
|
||||
JOB_EXPORT_SCH_PLOT( bool aIsCli, PLOT_FORMAT aPlotFormat, wxString aFilename ) :
|
||||
JOB( "plot", aIsCli ), m_plotFormat( aPlotFormat ), m_filename( aFilename )
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
int doPerform( KIWAY& aKiway ) override;
|
||||
PLOT_FORMAT m_plotFormat;
|
||||
wxString m_filename;
|
||||
SCH_PLOT_SETTINGS settings;
|
||||
};
|
||||
} // namespace CLI
|
||||
|
||||
#endif
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef JOB_EXPORT_SCH_SVG_H
|
||||
#define JOB_EXPORT_SCH_SVG_H
|
||||
|
||||
#include <wx/string.h>
|
||||
#include "job.h"
|
||||
|
||||
class JOB_EXPORT_SCH_SVG : public JOB
|
||||
{
|
||||
public:
|
||||
JOB_EXPORT_SCH_SVG( bool aIsCli ) :
|
||||
JOB( "svg", aIsCli ),
|
||||
m_filename(),
|
||||
m_outputDirectory(),
|
||||
m_blackAndWhite( false ),
|
||||
m_useBackgroundColor( false ),
|
||||
m_plotDrawingSheet( false )
|
||||
{
|
||||
}
|
||||
|
||||
wxString m_filename;
|
||||
wxString m_outputDirectory;
|
||||
wxString m_colorTheme;
|
||||
|
||||
bool m_blackAndWhite;
|
||||
bool m_useBackgroundColor;
|
||||
bool m_plotDrawingSheet;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -41,6 +41,8 @@
|
||||
#include <kiplatform/environment.h>
|
||||
#include <pgm_base.h>
|
||||
|
||||
#include <kiplatform/policy.h>
|
||||
#include <policy_keys.h>
|
||||
|
||||
struct CURL_PROGRESS
|
||||
{
|
||||
@@ -127,11 +129,29 @@ KICAD_CURL_EASY::KICAD_CURL_EASY() :
|
||||
curl_easy_setopt( m_CURL, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS );
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _WIN32
|
||||
// We need this to use the Windows Certificate store
|
||||
curl_easy_setopt( m_CURL, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA );
|
||||
long sslOpts = CURLSSLOPT_NATIVE_CA;
|
||||
|
||||
POLICY_CURL_SSL_REVOKE policyState = KIPLATFORM::POLICY::GetPolicyEnum<POLICY_CURL_SSL_REVOKE>( POLICY_KEY_REQUESTS_CURL_REVOKE );
|
||||
if( policyState == POLICY_CURL_SSL_REVOKE::BEST_EFFORT )
|
||||
{
|
||||
sslOpts |= CURLSSLOPT_REVOKE_BEST_EFFORT;
|
||||
}
|
||||
else if( policyState == POLICY_CURL_SSL_REVOKE::NONE )
|
||||
{
|
||||
sslOpts |= CURLSSLOPT_NO_REVOKE;
|
||||
}
|
||||
|
||||
curl_easy_setopt( m_CURL, CURLOPT_SSL_OPTIONS, sslOpts );
|
||||
#endif
|
||||
|
||||
if( wxGetEnv( wxT( "KICAD_CURL_VERBOSE" ), nullptr ) )
|
||||
{
|
||||
// note: curl verbose will end up in stderr
|
||||
curl_easy_setopt( m_CURL, CURLOPT_VERBOSE, 1L );
|
||||
}
|
||||
|
||||
wxPlatformInfo platformInfo;
|
||||
wxString application( Pgm().App().GetAppName() );
|
||||
wxString version( GetBuildVersion() );
|
||||
|
||||
+71
-19
@@ -45,6 +45,10 @@
|
||||
#include <wx/utils.h>
|
||||
#include <confirm.h>
|
||||
|
||||
#ifdef KICAD_USE_SENTRY
|
||||
#include <sentry.h>
|
||||
#endif
|
||||
|
||||
KIFACE* KIWAY::m_kiface[KIWAY_FACE_COUNT];
|
||||
int KIWAY::m_kiface_version[KIWAY_FACE_COUNT];
|
||||
|
||||
@@ -212,8 +216,6 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
|
||||
if( m_kiface[aFaceId] )
|
||||
return m_kiface[aFaceId];
|
||||
|
||||
wxString msg;
|
||||
|
||||
// DSO with KIFACE has not been loaded yet, does caller want to load it?
|
||||
if( doLoad )
|
||||
{
|
||||
@@ -236,6 +238,7 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
|
||||
bool codeSignOk = KIPLATFORM::ENV::VerifyFileSignature( dname );
|
||||
if( !codeSignOk )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( _( "Failed to verify kiface library '%s' signature." ), dname );
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
@@ -257,6 +260,14 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
|
||||
|
||||
setlocale( lc_new_type, user_locale.c_str() );
|
||||
|
||||
wxString msg = wxString::Format( "Loading kiface %d", aFaceId );
|
||||
#ifdef KICAD_USE_SENTRY
|
||||
sentry_value_t crumb = sentry_value_new_breadcrumb( "navigation", msg.utf8_str() );
|
||||
sentry_value_set_by_key( crumb, "category", sentry_value_new_string( "kiway.kiface" ) );
|
||||
sentry_value_set_by_key( crumb, "level", sentry_value_new_string( "info" ) );
|
||||
sentry_add_breadcrumb( crumb );
|
||||
#endif
|
||||
|
||||
if( !success )
|
||||
{
|
||||
// Failure: error reporting UI was done via wxLogSysError().
|
||||
@@ -287,15 +298,38 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
|
||||
wxASSERT_MSG( kiface,
|
||||
wxT( "attempted DSO has a bug, failed to return a KIFACE*" ) );
|
||||
|
||||
wxDllType dsoHandle = dso.Detach();
|
||||
|
||||
bool startSuccess = false;
|
||||
|
||||
// Give the DSO a single chance to do its "process level" initialization.
|
||||
// "Process level" specifically means stay away from any projects in there.
|
||||
if( kiface->OnKifaceStart( m_program, m_ctl ) )
|
||||
{
|
||||
// Tell dso's wxDynamicLibrary destructor not to Unload() the program image.
|
||||
ignore_unused( dso.Detach() );
|
||||
|
||||
try
|
||||
{
|
||||
startSuccess = kiface->OnKifaceStart( m_program, m_ctl );
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// OnKiFaceStart may generate an exception
|
||||
// Before we continue and ultimately unload our module to retry we need
|
||||
// to process the exception before we delete the free the memory space the exception resides in
|
||||
Pgm().HandleException( std::current_exception() );
|
||||
}
|
||||
|
||||
if( startSuccess )
|
||||
{
|
||||
return m_kiface[aFaceId] = kiface;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Usually means cancelled initial global library setup
|
||||
// But it could have been an exception/failure
|
||||
// Let the module go out of scope to unload
|
||||
dso.Attach( dsoHandle );
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// In any of the failure cases above, dso.Unload() should be called here
|
||||
@@ -414,6 +448,14 @@ KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate, wxTopLevelWindow
|
||||
{
|
||||
try
|
||||
{
|
||||
#ifdef KICAD_USE_SENTRY
|
||||
wxString msg = wxString::Format( "Creating window type %d", aFrameType );
|
||||
sentry_value_t crumb = sentry_value_new_breadcrumb( "navigation", msg.utf8_str() );
|
||||
sentry_value_set_by_key( crumb, "category", sentry_value_new_string( "kiway.player" ) );
|
||||
sentry_value_set_by_key( crumb, "level", sentry_value_new_string( "info" ) );
|
||||
sentry_add_breadcrumb( crumb );
|
||||
#endif
|
||||
|
||||
FACE_T face_type = KifaceType( aFrameType );
|
||||
KIFACE* kiface = KiFACE( face_type );
|
||||
|
||||
@@ -429,18 +471,9 @@ KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate, wxTopLevelWindow
|
||||
m_playerFrameId[aFrameType].store( frame->GetId() );
|
||||
return frame;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
wxLogError( ioe.What() );
|
||||
wxLogError( _( "Error loading editor." ) );
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
wxLogError( e.what() );
|
||||
wxLogError( _( "Error loading editor." ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
Pgm().HandleException( std::current_exception() );
|
||||
wxLogError( _( "Error loading editor." ) );
|
||||
}
|
||||
}
|
||||
@@ -462,11 +495,19 @@ bool KIWAY::PlayerClose( FRAME_T aFrameType, bool doForce )
|
||||
return false;
|
||||
}
|
||||
|
||||
KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
|
||||
KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
|
||||
|
||||
if( frame == nullptr ) // Already closed
|
||||
return true;
|
||||
|
||||
#ifdef KICAD_USE_SENTRY
|
||||
wxString msg = wxString::Format( "Closing window type %d", aFrameType );
|
||||
sentry_value_t crumb = sentry_value_new_breadcrumb( "navigation", msg.utf8_str() );
|
||||
sentry_value_set_by_key( crumb, "category", sentry_value_new_string( "kiway.playerclose" ) );
|
||||
sentry_value_set_by_key( crumb, "level", sentry_value_new_string( "info" ) );
|
||||
sentry_add_breadcrumb( crumb );
|
||||
#endif
|
||||
|
||||
if( frame->NonUserClose( doForce ) )
|
||||
{
|
||||
m_playerFrameId[aFrameType] = wxID_NONE;
|
||||
@@ -482,14 +523,18 @@ bool KIWAY::PlayersClose( bool doForce )
|
||||
bool ret = true;
|
||||
|
||||
for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
|
||||
{
|
||||
ret = ret && PlayerClose( FRAME_T( i ), doForce );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void KIWAY::PlayerDidClose( FRAME_T aFrameType )
|
||||
{
|
||||
m_playerFrameId[aFrameType] = wxID_NONE;
|
||||
}
|
||||
|
||||
|
||||
void KIWAY::ExpressMail( FRAME_T aDestination, MAIL_T aCommand, std::string& aPayload,
|
||||
wxWindow* aSource )
|
||||
{
|
||||
@@ -599,6 +644,13 @@ void KIWAY::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
|
||||
|
||||
void KIWAY::ProjectChanged()
|
||||
{
|
||||
#ifdef KICAD_USE_SENTRY
|
||||
sentry_value_t crumb = sentry_value_new_breadcrumb( "navigation", "Changing project" );
|
||||
sentry_value_set_by_key( crumb, "category", sentry_value_new_string( "kiway.projectchanged" ) );
|
||||
sentry_value_set_by_key( crumb, "level", sentry_value_new_string( "info" ) );
|
||||
sentry_add_breadcrumb( crumb );
|
||||
#endif
|
||||
|
||||
if( m_ctl & KFCTL_CPP_PROJECT_SUITE )
|
||||
{
|
||||
// A dynamic_cast could be better, but creates link issues
|
||||
|
||||
@@ -55,6 +55,12 @@ KIWAY_PLAYER::KIWAY_PLAYER( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType
|
||||
}
|
||||
|
||||
|
||||
// Don't use this one; it's only for wxFormBuilder, and it must be augmented with code to
|
||||
// correct the m_ident and set the m_kiway early in derived constructor.
|
||||
//
|
||||
// Because of its inherent danger, it's also declared private and requires friend-class
|
||||
// declarations for each usage.
|
||||
//
|
||||
KIWAY_PLAYER::KIWAY_PLAYER( wxWindow* aParent, wxWindowID aId, const wxString& aTitle,
|
||||
const wxPoint& aPos, const wxSize& aSize, long aStyle,
|
||||
const wxString& aWdoName ) :
|
||||
@@ -169,6 +175,8 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult, wxWindow* aResultantFocusWindow
|
||||
|
||||
bool KIWAY_PLAYER::Destroy()
|
||||
{
|
||||
Kiway().PlayerDidClose( GetFrameType() );
|
||||
|
||||
return EDA_BASE_FRAME::Destroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ wxString LayerName( int aLayer )
|
||||
switch( aLayer )
|
||||
{
|
||||
// PCB_LAYER_ID
|
||||
case UNDEFINED_LAYER: return _( "undefined" );
|
||||
|
||||
// Copper
|
||||
case F_Cu: return wxT( "F.Cu" );
|
||||
case In1_Cu: return wxT( "In1.Cu" );
|
||||
case In2_Cu: return wxT( "In2.Cu" );
|
||||
|
||||
+123
-31
@@ -127,6 +127,13 @@ LIB_TABLE::~LIB_TABLE()
|
||||
}
|
||||
|
||||
|
||||
void LIB_TABLE::Clear()
|
||||
{
|
||||
m_rows.clear();
|
||||
m_rowsMap.clear();
|
||||
}
|
||||
|
||||
|
||||
bool LIB_TABLE::IsEmpty( bool aIncludeFallback )
|
||||
{
|
||||
if( !aIncludeFallback || !m_fallBack )
|
||||
@@ -191,31 +198,26 @@ LIB_TABLE_ROW* LIB_TABLE::findRow( const wxString& aNickName, bool aCheckIfEnabl
|
||||
|
||||
do
|
||||
{
|
||||
cur->ensureIndex();
|
||||
std::shared_lock<std::shared_mutex> lock( cur->m_mutex, std::try_to_lock );
|
||||
|
||||
std::shared_lock<std::shared_mutex> lock( cur->m_nickIndexMutex );
|
||||
if( !cur->m_rowsMap.count( aNickName ) )
|
||||
continue;
|
||||
|
||||
for( const std::pair<const wxString, int>& entry : cur->m_nickIndex )
|
||||
{
|
||||
if( entry.first == aNickName )
|
||||
{
|
||||
row = &cur->m_rows[entry.second];
|
||||
row = &*cur->m_rowsMap.at( aNickName );
|
||||
|
||||
if( !aCheckIfEnabled || row->GetIsEnabled() )
|
||||
return row;
|
||||
}
|
||||
}
|
||||
if( !aCheckIfEnabled || row->GetIsEnabled() )
|
||||
return row;
|
||||
|
||||
// Repeat, this time looking for names that were "fixed" by legacy versions because
|
||||
// the old eeschema file format didn't support spaces in tokens.
|
||||
for( const std::pair<const wxString, int>& entry : cur->m_nickIndex )
|
||||
for( const std::pair<const wxString, LIB_TABLE_ROWS_ITER>& entry : cur->m_rowsMap )
|
||||
{
|
||||
wxString legacyLibName = entry.first;
|
||||
legacyLibName.Replace( " ", "_" );
|
||||
|
||||
if( legacyLibName == aNickName )
|
||||
{
|
||||
row = &cur->m_rows[entry.second];
|
||||
row = &*entry.second;
|
||||
|
||||
if( !aCheckIfEnabled || row->GetIsEnabled() )
|
||||
return row;
|
||||
@@ -235,9 +237,7 @@ const LIB_TABLE_ROW* LIB_TABLE::FindRowByURI( const wxString& aURI )
|
||||
|
||||
do
|
||||
{
|
||||
cur->ensureIndex();
|
||||
|
||||
for( unsigned i = 0; i < cur->m_rows.size(); i++ )
|
||||
for( unsigned i = 0; i < cur->m_rows.size(); i++ )
|
||||
{
|
||||
wxString tmp = cur->m_rows[i].GetFullURI( true );
|
||||
|
||||
@@ -276,10 +276,10 @@ std::vector<wxString> LIB_TABLE::GetLogicalLibs()
|
||||
|
||||
do
|
||||
{
|
||||
for( LIB_TABLE_ROWS_CITER it = cur->m_rows.begin(); it!=cur->m_rows.end(); ++it )
|
||||
for( const LIB_TABLE_ROW& row : cur->m_rows )
|
||||
{
|
||||
if( it->GetIsEnabled() )
|
||||
unique.insert( it->GetNickName() );
|
||||
if( row.GetIsEnabled() )
|
||||
unique.insert( row.GetNickName() );
|
||||
}
|
||||
|
||||
} while( ( cur = cur->m_fallBack ) != nullptr );
|
||||
@@ -303,28 +303,120 @@ std::vector<wxString> LIB_TABLE::GetLogicalLibs()
|
||||
|
||||
bool LIB_TABLE::InsertRow( LIB_TABLE_ROW* aRow, bool doReplace )
|
||||
{
|
||||
ensureIndex();
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
std::lock_guard<std::shared_mutex> lock( m_nickIndexMutex );
|
||||
auto it = m_rowsMap.find( aRow->GetNickName() );
|
||||
|
||||
INDEX_CITER it = m_nickIndex.find( aRow->GetNickName() );
|
||||
if( it != m_rowsMap.end() )
|
||||
{
|
||||
if( !doReplace )
|
||||
return false;
|
||||
|
||||
aRow->SetParent( this );
|
||||
|
||||
if( it == m_nickIndex.end() )
|
||||
m_rows.replace( it->second, aRow );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rows.push_back( aRow );
|
||||
m_nickIndex.insert( INDEX_VALUE( aRow->GetNickName(), m_rows.size() - 1 ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
if( doReplace )
|
||||
aRow->SetParent( this );
|
||||
reindex();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LIB_TABLE::RemoveRow( const LIB_TABLE_ROW* aRow )
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
bool found = false;
|
||||
auto it = m_rowsMap.find( aRow->GetNickName() );
|
||||
|
||||
if( it != m_rowsMap.end() )
|
||||
{
|
||||
m_rows.replace( it->second, aRow );
|
||||
return true;
|
||||
if( &*it->second == aRow )
|
||||
{
|
||||
found = true;
|
||||
m_rows.erase( it->second );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if( !found )
|
||||
{
|
||||
// Bookkeeping got messed up...
|
||||
for( size_t i = m_rows.size() - 1; i >= 0; --i )
|
||||
{
|
||||
if( &m_rows[i] == aRow )
|
||||
{
|
||||
m_rows.erase( m_rows.begin() + i );
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( found )
|
||||
reindex();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
bool LIB_TABLE::ReplaceRow( size_t aIndex, LIB_TABLE_ROW* aRow )
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
if( aIndex >= m_rows.size() )
|
||||
return false;
|
||||
|
||||
m_rowsMap.erase( m_rows[aIndex].GetNickName() );
|
||||
|
||||
m_rows.replace( aIndex, aRow );
|
||||
reindex();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LIB_TABLE::ChangeRowOrder( size_t aIndex, int aOffset )
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
if( aIndex >= m_rows.size() )
|
||||
return false;
|
||||
|
||||
int newPos = static_cast<int>( aIndex ) + aOffset;
|
||||
|
||||
if( newPos < 0 || newPos > static_cast<int>( m_rows.size() ) - 1 )
|
||||
return false;
|
||||
|
||||
auto element = m_rows.release( m_rows.begin() + aIndex );
|
||||
|
||||
m_rows.insert( m_rows.begin() + newPos, element.release() );
|
||||
reindex();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LIB_TABLE::TransferRows( LIB_TABLE_ROWS& aRowsList )
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
m_rows.transfer( m_rows.end(), aRowsList.begin(), aRowsList.end(), aRowsList );
|
||||
|
||||
reindex();
|
||||
}
|
||||
|
||||
|
||||
void LIB_TABLE::reindex()
|
||||
{
|
||||
m_rowsMap.clear();
|
||||
|
||||
for( LIB_TABLE_ROWS_ITER it = m_rows.begin(); it != m_rows.end(); ++it )
|
||||
{
|
||||
it->SetParent( this );
|
||||
m_rowsMap[it->GetNickName()] = it;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+21
-12
@@ -90,7 +90,7 @@ void LIB_TREE_NODE::SortNodes()
|
||||
std::sort( m_Children.begin(), m_Children.end(),
|
||||
[]( std::unique_ptr<LIB_TREE_NODE>& a, std::unique_ptr<LIB_TREE_NODE>& b )
|
||||
{
|
||||
return Compare( *a, *b ) > 0;
|
||||
return Compare( *a, *b );
|
||||
} );
|
||||
|
||||
for( std::unique_ptr<LIB_TREE_NODE>& node: m_Children )
|
||||
@@ -98,27 +98,38 @@ void LIB_TREE_NODE::SortNodes()
|
||||
}
|
||||
|
||||
|
||||
int LIB_TREE_NODE::Compare( LIB_TREE_NODE const& aNode1, LIB_TREE_NODE const& aNode2 )
|
||||
bool LIB_TREE_NODE::Compare( LIB_TREE_NODE const& aNode1, LIB_TREE_NODE const& aNode2 )
|
||||
{
|
||||
if( aNode1.m_Type != aNode2.m_Type )
|
||||
return 0;
|
||||
return aNode1.m_Type < aNode2.m_Type;
|
||||
|
||||
// Recently used sorts at top
|
||||
if( aNode1.m_Name.StartsWith( wxT( "-- " ) ) )
|
||||
return 1;
|
||||
{
|
||||
if( aNode2.m_Name.StartsWith( wxT( "-- " ) ) )
|
||||
{
|
||||
return aNode1.m_IntrinsicRank > aNode2.m_IntrinsicRank;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( aNode2.m_Name.StartsWith( wxT( "-- " ) ) )
|
||||
return 0;
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pinned nodes go next
|
||||
if( aNode1.m_Pinned && !aNode2.m_Pinned )
|
||||
return 1;
|
||||
return true;
|
||||
else if( aNode2.m_Pinned && !aNode1.m_Pinned )
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
if( aNode1.m_Parent != aNode2.m_Parent )
|
||||
return 0;
|
||||
if( aNode1.m_IntrinsicRank != aNode2.m_IntrinsicRank )
|
||||
return aNode1.m_IntrinsicRank > aNode2.m_IntrinsicRank;
|
||||
|
||||
return aNode1.m_IntrinsicRank - aNode2.m_IntrinsicRank;
|
||||
return reinterpret_cast<const void*>( &aNode1 ) < reinterpret_cast<const void*>( &aNode2 );
|
||||
}
|
||||
|
||||
|
||||
@@ -311,8 +322,6 @@ LIB_TREE_NODE_LIB_ID& LIB_TREE_NODE_LIB::AddItem( LIB_TREE_ITEM* aItem )
|
||||
|
||||
void LIB_TREE_NODE_LIB::UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib )
|
||||
{
|
||||
m_Score = 0;
|
||||
|
||||
// We need to score leaf nodes, which are usually (but not always) children.
|
||||
|
||||
if( m_Children.size() )
|
||||
|
||||
@@ -416,6 +416,12 @@ wxDataViewItem LIB_TREE_MODEL_ADAPTER::FindItem( const LIB_ID& aLibId )
|
||||
}
|
||||
|
||||
|
||||
wxDataViewItem LIB_TREE_MODEL_ADAPTER::GetCurrentDataViewItem()
|
||||
{
|
||||
return FindItem( m_preselect_lib_id );
|
||||
}
|
||||
|
||||
|
||||
unsigned int LIB_TREE_MODEL_ADAPTER::GetChildren( const wxDataViewItem& aItem,
|
||||
wxDataViewItemArray& aChildren ) const
|
||||
{
|
||||
|
||||
@@ -646,7 +646,7 @@ void dumpNode( wxString& buf, TREE_NODE* tok, int depth = 0 )
|
||||
|
||||
case TR_OP_FUNC_CALL:
|
||||
buf += "CALL '";
|
||||
buf += *tok->leaf[0]->value.str;
|
||||
buf += formatNode( tok->leaf[0] );
|
||||
buf += "': ";
|
||||
dumpNode( buf, tok->leaf[1], depth + 1 );
|
||||
break;
|
||||
@@ -786,7 +786,7 @@ static std::vector<TREE_NODE*> squashParamList( TREE_NODE* root )
|
||||
std::reverse( args.begin(), args.end() );
|
||||
|
||||
for( size_t i = 0; i < args.size(); i++ )
|
||||
libeval_dbg( 10, "squash arg%d: %s\n", int( i ), *args[i]->value.str );
|
||||
libeval_dbg( 10, "squash arg%d: %s\n", int( i ), formatNode( args[i] ) );
|
||||
|
||||
return args;
|
||||
}
|
||||
@@ -845,7 +845,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
int pos = node->leaf[0]->srcPos;
|
||||
|
||||
if( node->leaf[0]->value.str )
|
||||
pos -= static_cast<int>( node->leaf[0]->value.str->length() );
|
||||
pos -= static_cast<int>( formatNode( node->leaf[0] ).length() );
|
||||
|
||||
reportError( CST_CODEGEN, _( "Unknown parent of property" ), pos );
|
||||
|
||||
@@ -864,8 +864,8 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
// leaf[0]: object
|
||||
// leaf[1]: field
|
||||
|
||||
wxString itemName = *node->leaf[0]->value.str;
|
||||
wxString propName = *node->leaf[1]->value.str;
|
||||
wxString itemName = formatNode( node->leaf[0] );
|
||||
wxString propName = formatNode( node->leaf[1] );
|
||||
std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( itemName, propName );
|
||||
|
||||
if( !vref )
|
||||
@@ -895,7 +895,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
// leaf[0]: function name
|
||||
// leaf[1]: parameter
|
||||
|
||||
wxString itemName = *node->leaf[0]->value.str;
|
||||
wxString itemName = formatNode( node->leaf[0] );
|
||||
std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( itemName, "" );
|
||||
|
||||
if( !vref )
|
||||
@@ -905,7 +905,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
node->leaf[0]->srcPos - (int) itemName.length() );
|
||||
}
|
||||
|
||||
wxString functionName = *node->leaf[1]->leaf[0]->value.str;
|
||||
wxString functionName = formatNode( node->leaf[1]->leaf[0] );
|
||||
auto func = aCode->CreateFuncCall( functionName );
|
||||
std::vector<TREE_NODE*> params = squashParamList( node->leaf[1]->leaf[1] );
|
||||
|
||||
@@ -924,7 +924,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
for( TREE_NODE* pnode : params )
|
||||
{
|
||||
VALUE* param = aPreflightContext->AllocValue();
|
||||
param->Set( *pnode->value.str );
|
||||
param->Set( formatNode( pnode ) );
|
||||
aPreflightContext->Push( param );
|
||||
}
|
||||
|
||||
@@ -968,8 +968,8 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
// leaf[0]: object
|
||||
// leaf[1]: malformed syntax
|
||||
|
||||
wxString itemName = *node->leaf[0]->value.str;
|
||||
wxString propName = *node->leaf[1]->value.str;
|
||||
wxString itemName = formatNode( node->leaf[0] );
|
||||
wxString propName = formatNode( node->leaf[1] );
|
||||
std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( itemName, propName );
|
||||
|
||||
if( !vref )
|
||||
@@ -1006,12 +1006,12 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
{
|
||||
if( m_unitResolver->GetSupportedUnits().empty() )
|
||||
{
|
||||
msg.Printf( _( "Unexpected units for '%s'" ), *node->value.str );
|
||||
msg.Printf( _( "Unexpected units for '%s'" ), formatNode( node ) );
|
||||
reportError( CST_CODEGEN, msg, node->srcPos );
|
||||
}
|
||||
|
||||
int units = son->value.idx;
|
||||
value = m_unitResolver->Convert( *node->value.str, units );
|
||||
value = m_unitResolver->Convert( formatNode( node ), units );
|
||||
son->isVisited = true;
|
||||
}
|
||||
else
|
||||
@@ -1019,12 +1019,12 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
if( !m_unitResolver->GetSupportedUnitsMessage().empty() )
|
||||
{
|
||||
msg.Printf( _( "Missing units for '%s'| (%s)" ),
|
||||
*node->value.str,
|
||||
formatNode( node ),
|
||||
m_unitResolver->GetSupportedUnitsMessage() );
|
||||
reportError( CST_CODEGEN, msg, node->srcPos );
|
||||
}
|
||||
|
||||
value = EDA_UNIT_UTILS::UI::DoubleValueFromString( *node->value.str );
|
||||
value = EDA_UNIT_UTILS::UI::DoubleValueFromString( formatNode( node ) );
|
||||
}
|
||||
|
||||
node->SetUop( TR_UOP_PUSH_VALUE, value );
|
||||
@@ -1034,7 +1034,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
|
||||
case TR_STRING:
|
||||
{
|
||||
wxString str = *node->value.str;
|
||||
wxString str = formatNode( node );
|
||||
bool isWildcard = str.Contains("?") || str.Contains("*");
|
||||
node->SetUop( TR_UOP_PUSH_VALUE, str, isWildcard );
|
||||
node->isTerminal = true;
|
||||
@@ -1043,12 +1043,12 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
|
||||
case TR_IDENTIFIER:
|
||||
{
|
||||
std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( *node->value.str, "" );
|
||||
std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( formatNode( node ), "" );
|
||||
|
||||
if( !vref )
|
||||
{
|
||||
msg.Printf( _( "Unrecognized item '%s'" ), *node->value.str );
|
||||
reportError( CST_CODEGEN, msg, node->srcPos - (int) node->value.str->length() );
|
||||
msg.Printf( _( "Unrecognized item '%s'" ), formatNode( node ) );
|
||||
reportError( CST_CODEGEN, msg, node->srcPos - (int) formatNode( node ).length() );
|
||||
}
|
||||
|
||||
node->SetUop( TR_UOP_PUSH_VAR, std::move( vref ) );
|
||||
@@ -1220,7 +1220,7 @@ void UOP::Exec( CONTEXT* ctx )
|
||||
result = arg1Value != 0.0 ? 0 : 1;
|
||||
break;
|
||||
default:
|
||||
result = 0.0;
|
||||
result = arg1Value != 0.0 ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014-2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2014-2022 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <build_version.h>
|
||||
#include <lockfile.h>
|
||||
|
||||
#include <wx/filename.h>
|
||||
#include <wx/snglinst.h>
|
||||
|
||||
|
||||
std::unique_ptr<wxSingleInstanceChecker> LockFile( const wxString& aFileName )
|
||||
{
|
||||
// first make absolute and normalize, to avoid that different lock files
|
||||
// for the same file can be created
|
||||
wxFileName fn( aFileName );
|
||||
|
||||
fn.MakeAbsolute();
|
||||
|
||||
wxString lockFileName = fn.GetFullPath() + ".lock";
|
||||
|
||||
lockFileName.Replace( "/", "_" );
|
||||
|
||||
// We can have filenames coming from Windows, so also convert Windows separator
|
||||
lockFileName.Replace( "\\", "_" );
|
||||
|
||||
auto p = std::make_unique<wxSingleInstanceChecker>( lockFileName, GetKicadLockFilePath() );
|
||||
|
||||
if( p->IsAnotherRunning() )
|
||||
p = nullptr;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
wxString GetKicadLockFilePath()
|
||||
{
|
||||
wxFileName lockpath;
|
||||
lockpath.AssignDir( wxGetHomeDir() ); // Default wx behavior
|
||||
|
||||
#if defined( __WXMAC__ )
|
||||
// In OSX use the standard per user cache directory
|
||||
lockpath.AppendDir( "Library" );
|
||||
lockpath.AppendDir( "Caches" );
|
||||
lockpath.AppendDir( "kicad" );
|
||||
#elif defined( __UNIX__ )
|
||||
wxString envstr;
|
||||
// Try first the standard XDG_RUNTIME_DIR, falling back to XDG_CACHE_HOME
|
||||
if( wxGetEnv( "XDG_RUNTIME_DIR", &envstr ) && !envstr.IsEmpty() )
|
||||
{
|
||||
lockpath.AssignDir( envstr );
|
||||
}
|
||||
else if( wxGetEnv( "XDG_CACHE_HOME", &envstr ) && !envstr.IsEmpty() )
|
||||
{
|
||||
lockpath.AssignDir( envstr );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If all fails, just use ~/.cache
|
||||
lockpath.AppendDir( ".cache" );
|
||||
}
|
||||
|
||||
lockpath.AppendDir( wxString::Format( "kicad_v%s", GetMajorMinorVersion() ) );
|
||||
#endif
|
||||
|
||||
#if defined( __WXMAC__ ) || defined( __UNIX__ )
|
||||
if( !lockpath.DirExists() )
|
||||
{
|
||||
// Lockfiles should be only readable by the user
|
||||
lockpath.Mkdir( 0700, wxPATH_MKDIR_FULL );
|
||||
}
|
||||
#endif
|
||||
return lockpath.GetPath();
|
||||
}
|
||||
@@ -288,6 +288,24 @@ wxString PATHS::GetStockPlugins3DPath()
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
#elif defined( __WXMAC__ )
|
||||
fn.Assign( wxStandardPaths::Get().GetPluginsDir(), wxEmptyString );
|
||||
|
||||
// This must be mapped to main bundle for everything but kicad.app
|
||||
const wxArrayString dirs = fn.GetDirs();
|
||||
|
||||
// Check if we are the main kicad binary. in this case, the path will be
|
||||
// /path/to/bundlename.app/Contents/PlugIns
|
||||
// If we are an aux binary, the path will be something like
|
||||
// /path/to/bundlename.app/Contents/Applications/<standalone>.app/Contents/PlugIns
|
||||
if( dirs.GetCount() >= 6 &&
|
||||
dirs[dirs.GetCount() - 4] == wxT( "Applications" ) &&
|
||||
dirs[dirs.GetCount() - 6].Lower().EndsWith( wxT( "app" ) ) )
|
||||
{
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
}
|
||||
#else
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
@@ -434,6 +452,17 @@ wxString PATHS::GetOSXKicadDataDir()
|
||||
|
||||
|
||||
#ifdef __WXWINDOWS__
|
||||
wxString PATHS::GetWindowsFontConfigDir()
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.AssignDir( getWindowsKiCadRoot() );
|
||||
fn.AppendDir( wxS( "etc" ) );
|
||||
fn.AppendDir( wxS( "fonts" ) );
|
||||
|
||||
return fn.GetPathWithSep();
|
||||
}
|
||||
|
||||
|
||||
wxString PATHS::getWindowsKiCadRoot()
|
||||
{
|
||||
wxFileName root( Pgm().GetExecutablePath() + wxT( "/../" ) );
|
||||
|
||||
+55
-12
@@ -54,7 +54,7 @@
|
||||
#include <id.h>
|
||||
#include <kicad_curl/kicad_curl.h>
|
||||
#include <kiplatform/policy.h>
|
||||
#include <lockfile.h>
|
||||
#include <macros.h>
|
||||
#include <menus_helpers.h>
|
||||
#include <paths.h>
|
||||
#include <pgm_base.h>
|
||||
@@ -161,6 +161,8 @@ void PGM_BASE::Destroy()
|
||||
// unlike a normal destructor, this is designed to be called more than once safely:
|
||||
delete m_locale;
|
||||
m_locale = nullptr;
|
||||
|
||||
m_pgm_checker.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -238,11 +240,11 @@ const wxString PGM_BASE::AskUserForPreferredEditor( const wxString& aDefaultEdit
|
||||
#ifdef KICAD_USE_SENTRY
|
||||
bool PGM_BASE::IsSentryOptedIn()
|
||||
{
|
||||
KIPLATFORM::POLICY::STATE policyState =
|
||||
KIPLATFORM::POLICY::GetPolicyState( POLICY_KEY_DATACOLLECTION );
|
||||
if( policyState != KIPLATFORM::POLICY::STATE::NOT_CONFIGURED )
|
||||
KIPLATFORM::POLICY::PBOOL policyState =
|
||||
KIPLATFORM::POLICY::GetPolicyBool( POLICY_KEY_DATACOLLECTION );
|
||||
if( policyState != KIPLATFORM::POLICY::PBOOL::NOT_CONFIGURED )
|
||||
{
|
||||
return policyState == KIPLATFORM::POLICY::STATE::ENABLED;
|
||||
return policyState == KIPLATFORM::POLICY::PBOOL::ENABLED;
|
||||
}
|
||||
|
||||
return m_sentry_optin_fn.Exists();
|
||||
@@ -349,10 +351,10 @@ void PGM_BASE::sentryPrompt()
|
||||
if( !IsGUI() )
|
||||
return;
|
||||
|
||||
KIPLATFORM::POLICY::STATE policyState =
|
||||
KIPLATFORM::POLICY::GetPolicyState( POLICY_KEY_DATACOLLECTION );
|
||||
KIPLATFORM::POLICY::PBOOL policyState =
|
||||
KIPLATFORM::POLICY::GetPolicyBool( POLICY_KEY_DATACOLLECTION );
|
||||
|
||||
if( policyState == KIPLATFORM::POLICY::STATE::NOT_CONFIGURED
|
||||
if( policyState == KIPLATFORM::POLICY::PBOOL::NOT_CONFIGURED
|
||||
&& !m_settings_manager->GetCommonSettings()->m_DoNotShowAgain.data_collection_prompt )
|
||||
{
|
||||
wxMessageDialog optIn = wxMessageDialog(
|
||||
@@ -443,6 +445,8 @@ bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
m_pgm_checker = std::make_unique<wxSingleInstanceChecker>();
|
||||
m_pgm_checker->Create( pgm_name, wxStandardPaths::Get().GetTempDir() );
|
||||
|
||||
// Init KiCad environment
|
||||
// the environment variable KICAD (if exists) gives the kicad path:
|
||||
@@ -479,6 +483,13 @@ bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
|
||||
SetLanguagePath();
|
||||
SetDefaultLanguage( tmp );
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// We need to set this because the internal fontconfig logic
|
||||
// seems to search relative to the dll rather the other logic it
|
||||
// has to look for the /etc folder above the dll
|
||||
wxSetEnv( "FONTCONFIG_PATH", PATHS::GetWindowsFontConfigDir() );
|
||||
#endif
|
||||
|
||||
m_settings_manager = std::make_unique<SETTINGS_MANAGER>( aHeadless );
|
||||
|
||||
// Our unit test mocks break if we continue
|
||||
@@ -655,7 +666,7 @@ bool PGM_BASE::SetLanguage( wxString& aErrMsg, bool first_time )
|
||||
|
||||
// don't use wxLOCALE_LOAD_DEFAULT flag so that Init() doesn't return
|
||||
// false just because it failed to load wxstd catalog
|
||||
if( !m_locale->Init( m_language_id, wxLOCALE_DONT_LOAD_DEFAULT ) )
|
||||
if( !m_locale->Init( m_language_id ) )
|
||||
{
|
||||
wxLogTrace( traceLocale, wxT( "This language is not supported by the system." ) );
|
||||
|
||||
@@ -663,7 +674,7 @@ bool PGM_BASE::SetLanguage( wxString& aErrMsg, bool first_time )
|
||||
delete m_locale;
|
||||
|
||||
m_locale = new wxLocale;
|
||||
m_locale->Init( wxLANGUAGE_DEFAULT, wxLOCALE_DONT_LOAD_DEFAULT);
|
||||
m_locale->Init( wxLANGUAGE_DEFAULT );
|
||||
|
||||
aErrMsg = _( "This language is not supported by the operating system." );
|
||||
return false;
|
||||
@@ -714,7 +725,7 @@ bool PGM_BASE::SetLanguage( wxString& aErrMsg, bool first_time )
|
||||
delete m_locale;
|
||||
|
||||
m_locale = new wxLocale;
|
||||
m_locale->Init( wxLANGUAGE_DEFAULT, wxLOCALE_DONT_LOAD_DEFAULT);
|
||||
m_locale->Init( wxLANGUAGE_DEFAULT );
|
||||
|
||||
aErrMsg = _( "The KiCad language file for this language is not installed." );
|
||||
return false;
|
||||
@@ -880,4 +891,36 @@ bool PGM_BASE::IsGUI()
|
||||
bool run_gui = wxTheApp->GetClassName() != KICAD_CLI_APP_NAME;
|
||||
return run_gui;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PGM_BASE::HandleException( std::exception_ptr aPtr )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( aPtr )
|
||||
std::rethrow_exception( aPtr );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
wxLogError( ioe.What() );
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
#ifdef KICAD_USE_SENTRY
|
||||
sentry_value_t exc = sentry_value_new_exception( "exception", e.what() );
|
||||
sentry_value_set_stacktrace( exc, NULL, 0 );
|
||||
|
||||
sentry_value_t sentryEvent = sentry_value_new_event();
|
||||
sentry_event_add_exception( sentryEvent, exc );
|
||||
sentry_capture_event( sentryEvent );
|
||||
#endif
|
||||
|
||||
wxLogError( wxT( "Unhandled exception class: %s what: %s" ),
|
||||
FROM_UTF8( typeid( e ).name() ), FROM_UTF8( e.what() ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
wxLogError( wxT( "Unhandled exception of unknown type" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <string_utils.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <trigo.h>
|
||||
#include <fmt/core.h>
|
||||
|
||||
/**
|
||||
* Oblique angle for DXF native text
|
||||
@@ -146,6 +147,26 @@ void DXF_PLOTTER::SetUnits( DXF_UNITS aUnit )
|
||||
}
|
||||
|
||||
|
||||
// convert aValue to a string, and remove trailing zeros
|
||||
// In DXF files coordinates need a high precision: at least 9 digits when given
|
||||
// in inches and 7 digits when in mm.
|
||||
// So we use 16 digits and remove trailing 0 (if any)
|
||||
static std::string formatCoord( double aValue )
|
||||
{
|
||||
std::string buf;
|
||||
|
||||
buf = fmt::format( "{:.16f}", aValue );
|
||||
|
||||
// remove trailing zeros
|
||||
while( !buf.empty() && buf[buf.size() - 1] == '0' )
|
||||
{
|
||||
buf.pop_back();
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void DXF_PLOTTER::SetViewport( const VECTOR2I& aOffset, double aIusPerDecimil,
|
||||
double aScale, bool aMirror )
|
||||
{
|
||||
@@ -417,11 +438,24 @@ void DXF_PLOTTER::SetColor( const COLOR4D& color )
|
||||
void DXF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
|
||||
{
|
||||
wxASSERT( m_outputFile );
|
||||
MoveTo( p1 );
|
||||
LineTo( VECTOR2I( p1.x, p2.y ) );
|
||||
LineTo( VECTOR2I( p2.x, p2.y ) );
|
||||
LineTo( VECTOR2I( p2.x, p1.y ) );
|
||||
FinishTo( VECTOR2I( p1.x, p1.y ) );
|
||||
|
||||
if( p1 != p2 )
|
||||
{
|
||||
MoveTo( p1 );
|
||||
LineTo( VECTOR2I( p1.x, p2.y ) );
|
||||
LineTo( VECTOR2I( p2.x, p2.y ) );
|
||||
LineTo( VECTOR2I( p2.x, p1.y ) );
|
||||
FinishTo( VECTOR2I( p1.x, p1.y ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw as a point
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
VECTOR2D point_dev = userToDeviceCoordinates( p1 );
|
||||
|
||||
fprintf( m_outputFile, "0\nPOINT\n8\n%s\n10\n%g\n20\n%g\n", TO_UTF8( cname ), point_dev.x,
|
||||
point_dev.y );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -431,31 +465,43 @@ void DXF_PLOTTER::Circle( const VECTOR2I& centre, int diameter, FILL_T fill, int
|
||||
double radius = userToDeviceSize( diameter / 2 );
|
||||
VECTOR2D centre_dev = userToDeviceCoordinates( centre );
|
||||
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
|
||||
if( radius > 0 )
|
||||
{
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
|
||||
if( fill == FILL_T::NO_FILL )
|
||||
{
|
||||
fprintf( m_outputFile, "0\nCIRCLE\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n",
|
||||
fprintf( m_outputFile, "0\nCIRCLE\n8\n%s\n10\n%s\n20\n%s\n40\n%s\n",
|
||||
TO_UTF8( cname ),
|
||||
centre_dev.x, centre_dev.y, radius );
|
||||
formatCoord( centre_dev.x ).c_str(),
|
||||
formatCoord( centre_dev.y ).c_str(),
|
||||
formatCoord( radius ).c_str() );
|
||||
}
|
||||
else if( fill == FILL_T::FILLED_SHAPE )
|
||||
{
|
||||
double r = radius*0.5;
|
||||
double r = radius * 0.5;
|
||||
fprintf( m_outputFile, "0\nPOLYLINE\n" );
|
||||
fprintf( m_outputFile, "8\n%s\n66\n1\n70\n1\n", TO_UTF8( cname ) );
|
||||
fprintf( m_outputFile, "40\n%g\n41\n%g\n", radius, radius);
|
||||
fprintf( m_outputFile, "40\n%s\n41\n%s\n",
|
||||
formatCoord( radius ).c_str(),
|
||||
formatCoord( radius ).c_str() );
|
||||
fprintf( m_outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ) );
|
||||
fprintf( m_outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
|
||||
centre_dev.x-r, centre_dev.y );
|
||||
fprintf( m_outputFile, "10\n%s\n 20\n%s\n42\n1.0\n",
|
||||
formatCoord( centre_dev.x-r ).c_str(),
|
||||
formatCoord( centre_dev.y ).c_str() );
|
||||
fprintf( m_outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ) );
|
||||
fprintf( m_outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
|
||||
centre_dev.x+r, centre_dev.y );
|
||||
fprintf( m_outputFile, "10\n%s\n 20\n%s\n42\n1.0\n",
|
||||
formatCoord( centre_dev.x+r ).c_str(),
|
||||
formatCoord( centre_dev.y ).c_str() );
|
||||
fprintf( m_outputFile, "0\nSEQEND\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw as a point
|
||||
fprintf( m_outputFile, "0\nPOINT\n8\n%s\n10\n%g\n20\n%g\n", TO_UTF8( cname ), centre_dev.x,
|
||||
centre_dev.y );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -578,9 +624,12 @@ void DXF_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
|
||||
// DXF LINE
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
const char* lname = getDXFLineType( static_cast<PLOT_DASH_TYPE>( m_currentLineType ) );
|
||||
fprintf( m_outputFile, "0\nLINE\n8\n%s\n6\n%s\n10\n%g\n20\n%g\n11\n%g\n21\n%g\n",
|
||||
fprintf( m_outputFile, "0\nLINE\n8\n%s\n6\n%s\n10\n%s\n20\n%s\n11\n%s\n21\n%s\n",
|
||||
TO_UTF8( cname ), lname,
|
||||
pen_lastpos_dev.x, pen_lastpos_dev.y, pos_dev.x, pos_dev.y );
|
||||
formatCoord( pen_lastpos_dev.x ).c_str(),
|
||||
formatCoord( pen_lastpos_dev.y ).c_str(),
|
||||
formatCoord( pos_dev.x ).c_str(),
|
||||
formatCoord( pos_dev.y ).c_str() );
|
||||
}
|
||||
|
||||
m_penLastpos = pos;
|
||||
@@ -626,8 +675,8 @@ void DXF_PLOTTER::ThickSegment( const VECTOR2I& aStart, const VECTOR2I& aEnd, in
|
||||
}
|
||||
|
||||
|
||||
void DXF_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void DXF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
wxASSERT( m_outputFile );
|
||||
|
||||
@@ -648,9 +697,11 @@ void DXF_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
// Emit a DXF ARC entity
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
fprintf( m_outputFile,
|
||||
"0\nARC\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n50\n%g\n51\n%g\n",
|
||||
"0\nARC\n8\n%s\n10\n%s\n20\n%s\n40\n%s\n50\n%.8f\n51\n%.8f\n",
|
||||
TO_UTF8( cname ),
|
||||
centre_device.x, centre_device.y, radius_device,
|
||||
formatCoord( centre_device.x ).c_str(),
|
||||
formatCoord( centre_device.y ).c_str(),
|
||||
formatCoord( radius_device ).c_str(),
|
||||
startAngle.AsDegrees(), endAngle.AsDegrees() );
|
||||
}
|
||||
|
||||
@@ -936,21 +987,21 @@ void DXF_PLOTTER::plotOneLineOfText( const VECTOR2I& aPos, const COLOR4D& aColor
|
||||
" 8\n"
|
||||
"%s\n" // Layer name
|
||||
" 10\n"
|
||||
"%g\n" // First point X
|
||||
"%s\n" // First point X
|
||||
" 11\n"
|
||||
"%g\n" // Second point X
|
||||
"%s\n" // Second point X
|
||||
" 20\n"
|
||||
"%g\n" // First point Y
|
||||
"%s\n" // First point Y
|
||||
" 21\n"
|
||||
"%g\n" // Second point Y
|
||||
"%s\n" // Second point Y
|
||||
" 40\n"
|
||||
"%g\n" // Text height
|
||||
"%s\n" // Text height
|
||||
" 41\n"
|
||||
"%g\n" // Width factor
|
||||
"%s\n" // Width factor
|
||||
" 50\n"
|
||||
"%g\n" // Rotation
|
||||
"%.8f\n" // Rotation
|
||||
" 51\n"
|
||||
"%g\n" // Oblique angle
|
||||
"%.8f\n" // Oblique angle
|
||||
" 71\n"
|
||||
"%d\n" // Mirror flags
|
||||
" 72\n"
|
||||
@@ -960,9 +1011,9 @@ void DXF_PLOTTER::plotOneLineOfText( const VECTOR2I& aPos, const COLOR4D& aColor
|
||||
aAttributes.m_Bold ?
|
||||
(aAttributes.m_Italic ? "KICADBI" : "KICADB")
|
||||
: (aAttributes.m_Italic ? "KICADI" : "KICAD"), TO_UTF8( cname ),
|
||||
origin_dev.x, origin_dev.x,
|
||||
origin_dev.y, origin_dev.y,
|
||||
size_dev.y, fabs( size_dev.x / size_dev.y ),
|
||||
formatCoord( origin_dev.x ).c_str(), formatCoord( origin_dev.x ).c_str(),
|
||||
formatCoord( origin_dev.y ).c_str(), formatCoord( origin_dev.y ).c_str(),
|
||||
formatCoord( size_dev.y ).c_str(), formatCoord( fabs( size_dev.x / size_dev.y ) ).c_str(),
|
||||
aAttributes.m_Angle.AsDegrees(),
|
||||
aAttributes.m_Italic ? DXF_OBLIQUE_ANGLE : 0,
|
||||
aAttributes.m_Mirrored ? 2 : 0, // X mirror flag
|
||||
|
||||
@@ -826,8 +826,8 @@ void GERBER_PLOTTER::Circle( const VECTOR2I& aCenter, int aDiameter, FILL_T aFil
|
||||
|
||||
|
||||
|
||||
void GERBER_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void GERBER_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
||||
@@ -1149,8 +1149,8 @@ void GERBER_PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, i
|
||||
}
|
||||
}
|
||||
|
||||
void GERBER_PLOTTER::ThickArc( const VECTOR2I& aCentre, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, int aWidth,
|
||||
void GERBER_PLOTTER::ThickArc( const VECTOR2D& aCentre, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, int aWidth,
|
||||
OUTLINE_MODE aTraceMode, void* aData )
|
||||
{
|
||||
GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
|
||||
|
||||
@@ -394,22 +394,16 @@ void HPGL_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T aFill, i
|
||||
VECTOR2D p1_device = userToDeviceCoordinates( p1 );
|
||||
VECTOR2D p2_device = userToDeviceCoordinates( p2 );
|
||||
|
||||
MoveTo( p1 );
|
||||
// EA command seems to always fill the rectangle, so plot as a polygon instead
|
||||
std::vector<VECTOR2I> cornerList;
|
||||
|
||||
if( aFill == FILL_T::FILLED_SHAPE )
|
||||
{
|
||||
startOrAppendItem( p1_device, wxString::Format( "RA %.0f,%.0f;",
|
||||
p2_device.x,
|
||||
p2_device.y ) );
|
||||
}
|
||||
cornerList.emplace_back( p1.x, p1.y );
|
||||
cornerList.emplace_back( p2.x, p1.y );
|
||||
cornerList.emplace_back( p2.x, p2.y );
|
||||
cornerList.emplace_back( p1.x, p2.y );
|
||||
cornerList.emplace_back( p1.x, p1.y );
|
||||
|
||||
startOrAppendItem( p1_device, wxString::Format( "EA %.0f,%.0f;",
|
||||
p2_device.x,
|
||||
p2_device.y ) );
|
||||
|
||||
m_current_item->loc_end = m_current_item->loc_start;
|
||||
m_current_item->bbox.Merge( p2_device );
|
||||
PenFinish();
|
||||
PlotPoly( cornerList, aFill, aWidth, nullptr );
|
||||
}
|
||||
|
||||
|
||||
@@ -435,7 +429,6 @@ void HPGL_PLOTTER::Circle( const VECTOR2I& aCenter, int aDiameter, FILL_T aFill,
|
||||
chord_angle.AsDegrees(),
|
||||
hpgl_end_polygon_cmd ) );
|
||||
m_current_item->lift_before = true;
|
||||
m_current_item->pen_returns = true;
|
||||
m_current_item->bbox.Merge( BOX2D( center_dev - radius,
|
||||
VECTOR2D( 2 * radius, 2 * radius ) ) );
|
||||
PenFinish();
|
||||
@@ -448,7 +441,6 @@ void HPGL_PLOTTER::Circle( const VECTOR2I& aCenter, int aDiameter, FILL_T aFill,
|
||||
radius,
|
||||
chord_angle.AsDegrees() ) );
|
||||
m_current_item->lift_before = true;
|
||||
m_current_item->pen_returns = true;
|
||||
m_current_item->bbox.Merge( BOX2D( center_dev - radius,
|
||||
VECTOR2D( 2 * radius, 2 * radius ) ) );
|
||||
PenFinish();
|
||||
@@ -567,8 +559,8 @@ void HPGL_PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end,
|
||||
}
|
||||
|
||||
|
||||
void HPGL_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void HPGL_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
if( aRadius <= 0 )
|
||||
return;
|
||||
|
||||
@@ -217,12 +217,43 @@ void PDF_PLOTTER::SetDash( int aLineWidth, PLOT_DASH_TYPE aLineStyle )
|
||||
void PDF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
|
||||
{
|
||||
wxASSERT( m_workFile );
|
||||
|
||||
SetCurrentLineWidth( width );
|
||||
|
||||
VECTOR2I size = p2 - p1;
|
||||
|
||||
if( size.x == 0 && size.y == 0 )
|
||||
{
|
||||
// Can't draw zero-sized rectangles
|
||||
SetCurrentLineWidth( width );
|
||||
|
||||
MoveTo( VECTOR2I( p1.x, p1.y ) );
|
||||
FinishTo( VECTOR2I( p1.x, p1.y ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( std::min( std::abs( size.x ), std::abs( size.y ) ) < width )
|
||||
{
|
||||
// Too thick stroked rectangles are buggy, draw as polygon
|
||||
std::vector<VECTOR2I> cornerList;
|
||||
|
||||
cornerList.emplace_back( p1.x, p1.y );
|
||||
cornerList.emplace_back( p2.x, p1.y );
|
||||
cornerList.emplace_back( p2.x, p2.y );
|
||||
cornerList.emplace_back( p1.x, p2.y );
|
||||
cornerList.emplace_back( p1.x, p1.y );
|
||||
|
||||
PlotPoly( cornerList, fill, width, nullptr );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VECTOR2D p1_dev = userToDeviceCoordinates( p1 );
|
||||
VECTOR2D p2_dev = userToDeviceCoordinates( p2 );
|
||||
|
||||
SetCurrentLineWidth( width );
|
||||
fprintf( m_workFile, "%g %g %g %g re %c\n", p1_dev.x, p1_dev.y,
|
||||
p2_dev.x - p1_dev.x, p2_dev.y - p1_dev.y, fill == FILL_T::NO_FILL ? 'S' : 'B' );
|
||||
fprintf( m_workFile, "%g %g %g %g re %c\n", p1_dev.x, p1_dev.y, p2_dev.x - p1_dev.x,
|
||||
p2_dev.y - p1_dev.y, fill == FILL_T::NO_FILL ? 'S' : 'B' );
|
||||
}
|
||||
|
||||
|
||||
@@ -336,8 +367,8 @@ void PDF_PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VE
|
||||
}
|
||||
|
||||
|
||||
void PDF_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void PDF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
wxASSERT( m_workFile );
|
||||
|
||||
@@ -1217,7 +1248,7 @@ bool PDF_PLOTTER::EndPlot()
|
||||
|
||||
js += wxT( "var cChoice = app.popUpMenuEx.apply\\( app, aParams \\); " );
|
||||
js += wxT( "if\\( cChoice != null && cChoice.substring\\( 0, 1 \\) == '#' \\)"
|
||||
" this.pageNum = cChoice.slice\\( 1 \\); " );
|
||||
" this.pageNum = parseInt\\( cChoice.slice\\( 1 \\) \\); " );
|
||||
js += wxT( "else if\\( cChoice != null && cChoice.substring\\( 0, 4 \\) == 'http' \\)"
|
||||
" app.launchURL\\( cChoice \\);" );
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ void PSLIKE_PLOTTER::FlashPadOval( const VECTOR2I& aPadPos, const VECTOR2I& aSiz
|
||||
if( aTraceMode == FILLED )
|
||||
ThickSegment( a + aPadPos, b + aPadPos, size.x, aTraceMode, nullptr );
|
||||
else
|
||||
sketchOval( aPadPos, size, orient, -1 );
|
||||
sketchOval( aPadPos, size, orient, USE_DEFAULT_LINE_WIDTH );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -443,8 +443,8 @@ void SVG_PLOTTER::Circle( const VECTOR2I& pos, int diametre, FILL_T fill, int wi
|
||||
}
|
||||
|
||||
|
||||
void SVG_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void SVG_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
/* Draws an arc of a circle, centered on (xc,yc), with starting point (x1, y1) and ending
|
||||
* at (x2, y2). The current pen is used for the outline and the current brush for filling
|
||||
|
||||
@@ -149,7 +149,7 @@ void PlotDrawingSheet( PLOTTER* plotter, const PROJECT* aProject, const TITLE_BL
|
||||
case WSG_POLY_T:
|
||||
{
|
||||
DS_DRAW_ITEM_POLYPOLYGONS* poly = (DS_DRAW_ITEM_POLYPOLYGONS*) item;
|
||||
int penWidth = std::max( poly->GetPenWidth(), defaultPenWidth );
|
||||
int penWidth = poly->GetPenWidth();
|
||||
std::vector<VECTOR2I> points;
|
||||
|
||||
for( int idx = 0; idx < poly->GetPolygons().OutlineCount(); ++idx )
|
||||
|
||||
@@ -145,13 +145,31 @@ double PLOTTER::GetDashGapLenIU( int aLineWidth ) const
|
||||
return userToDeviceSize( m_renderSettings->GetGapLength( aLineWidth ) );
|
||||
}
|
||||
|
||||
|
||||
#include <wx/log.h>
|
||||
void PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
|
||||
FILL_T aFill, int aWidth, int aMaxError )
|
||||
{
|
||||
EDA_ANGLE startAngle( aStart - aCenter );
|
||||
EDA_ANGLE endAngle( aEnd - aCenter );
|
||||
int radius = ( aStart - aCenter ).EuclideanNorm();
|
||||
// Recalculate aCenter using double to be sure we will use a exact value, from aStart and aEnd
|
||||
// it must be on the line passing by the middle of segment {aStart, aEnd}
|
||||
// To simplify calculations, use aStart as origin in intermediate calculations
|
||||
VECTOR2D center = aCenter - aStart;
|
||||
VECTOR2D end = aEnd - aStart;
|
||||
EDA_ANGLE segAngle( end );
|
||||
|
||||
// Rotate end and center, to make segment {aStart, aEnd} horizontal
|
||||
RotatePoint( end, segAngle );
|
||||
RotatePoint( center, segAngle );
|
||||
|
||||
// center.x must be at end.x/2 coordinate
|
||||
center.x = end.x / 2;
|
||||
|
||||
// Now calculate the right center position
|
||||
RotatePoint( center, -segAngle );
|
||||
center += aStart;
|
||||
|
||||
EDA_ANGLE startAngle( VECTOR2D( aStart ) - center );
|
||||
EDA_ANGLE endAngle( VECTOR2D( aEnd ) - center );
|
||||
double radius = ( VECTOR2D( aStart ) - center ).EuclideanNorm();
|
||||
|
||||
if( startAngle > endAngle )
|
||||
{
|
||||
@@ -168,12 +186,12 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR
|
||||
startAngle = -startAngle;
|
||||
endAngle = -endAngle;
|
||||
|
||||
Arc( aCenter, startAngle, endAngle, radius, aFill, aWidth );
|
||||
Arc( center, startAngle, endAngle, radius, aFill, aWidth );
|
||||
}
|
||||
|
||||
|
||||
void PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
EDA_ANGLE startAngle( aStartAngle );
|
||||
EDA_ANGLE endAngle( aEndAngle );
|
||||
@@ -570,8 +588,8 @@ void PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int widt
|
||||
}
|
||||
|
||||
|
||||
void PLOTTER::ThickArc( const VECTOR2I& centre, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, int aWidth,
|
||||
void PLOTTER::ThickArc( const VECTOR2D& centre, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, int aWidth,
|
||||
OUTLINE_MODE aTraceMode, void* aData )
|
||||
{
|
||||
if( aTraceMode == FILLED )
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Thomas Pointhuber <thomas.pointhuber@gmx.at>
|
||||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -88,26 +89,106 @@ ALTIUM_COMPOUND_FILE::ALTIUM_COMPOUND_FILE( const wxString& aFilePath )
|
||||
}
|
||||
|
||||
|
||||
static const CFB::COMPOUND_FILE_ENTRY*
|
||||
FindStreamSingleLevel( const CFB::CompoundFileReader& aReader,
|
||||
const CFB::COMPOUND_FILE_ENTRY* aEntry, const std::string aName,
|
||||
const bool aIsStream )
|
||||
std::map<wxString, wxString> ALTIUM_COMPOUND_FILE::ListLibFootprints() const
|
||||
{
|
||||
std::map<wxString, wxString> patternMap;
|
||||
|
||||
if( !m_reader )
|
||||
return patternMap;
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* root = m_reader->GetRootEntry();
|
||||
|
||||
if( !root )
|
||||
return patternMap;
|
||||
|
||||
m_reader->EnumFiles( root, 2,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string& dir,
|
||||
int level ) -> void
|
||||
{
|
||||
std::wstring dirName = UTF16ToWstring( dir.data(), dir.size() );
|
||||
std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen );
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"Parameters" )
|
||||
{
|
||||
ALTIUM_PARSER parametersReader( *this, entry );
|
||||
std::map<wxString, wxString> parameterProperties =
|
||||
parametersReader.ReadProperties();
|
||||
|
||||
wxString key = ALTIUM_PARSER::ReadString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
wxString fpName = ALTIUM_PARSER::ReadUnicodeString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
patternMap.emplace( key, fpName );
|
||||
}
|
||||
} );
|
||||
|
||||
return patternMap;
|
||||
}
|
||||
|
||||
|
||||
wxString ALTIUM_COMPOUND_FILE::FindLibFootprintDirName( const wxString& aFpUnicodeName ) const
|
||||
{
|
||||
if( !m_reader )
|
||||
return wxEmptyString;
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* root = m_reader->GetRootEntry();
|
||||
|
||||
if( !root )
|
||||
return wxEmptyString;
|
||||
|
||||
wxString ret;
|
||||
|
||||
m_reader->EnumFiles( root, 2,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string& dir,
|
||||
int level ) -> void
|
||||
{
|
||||
std::wstring dirName = UTF16ToWstring( dir.data(), dir.size() );
|
||||
std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen );
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"Parameters" )
|
||||
{
|
||||
ALTIUM_PARSER parametersReader( *this, entry );
|
||||
std::map<wxString, wxString> parameterProperties =
|
||||
parametersReader.ReadProperties();
|
||||
|
||||
wxString fpName = ALTIUM_PARSER::ReadUnicodeString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
if( fpName == aFpUnicodeName )
|
||||
{
|
||||
ret = dirName;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY*
|
||||
ALTIUM_COMPOUND_FILE::FindStreamSingleLevel( const CFB::COMPOUND_FILE_ENTRY* aEntry,
|
||||
const std::string aName, const bool aIsStream ) const
|
||||
{
|
||||
if( !m_reader || !aEntry )
|
||||
return nullptr;
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* ret = nullptr;
|
||||
|
||||
aReader.EnumFiles( aEntry, 1,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string& dir,
|
||||
int level ) -> void
|
||||
{
|
||||
if( aReader.IsStream( entry ) == aIsStream )
|
||||
{
|
||||
std::string name = UTF16ToUTF8( entry->name );
|
||||
if( name == aName.c_str() )
|
||||
{
|
||||
ret = entry;
|
||||
}
|
||||
}
|
||||
} );
|
||||
m_reader->EnumFiles( aEntry, 1,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string& dir,
|
||||
int level ) -> void
|
||||
{
|
||||
if( m_reader->IsStream( entry ) == aIsStream )
|
||||
{
|
||||
std::string name = UTF16ToUTF8( entry->name );
|
||||
if( name == aName.c_str() )
|
||||
{
|
||||
ret = entry;
|
||||
}
|
||||
}
|
||||
} );
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -116,9 +197,7 @@ const CFB::COMPOUND_FILE_ENTRY*
|
||||
ALTIUM_COMPOUND_FILE::FindStream( const std::vector<std::string>& aStreamPath ) const
|
||||
{
|
||||
if( !m_reader )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* currentDirEntry = m_reader->GetRootEntry();
|
||||
|
||||
@@ -129,12 +208,11 @@ ALTIUM_COMPOUND_FILE::FindStream( const std::vector<std::string>& aStreamPath )
|
||||
|
||||
if( ++it == aStreamPath.cend() )
|
||||
{
|
||||
return FindStreamSingleLevel( *m_reader.get(), currentDirEntry, name, true );
|
||||
return FindStreamSingleLevel( currentDirEntry, name, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
currentDirEntry =
|
||||
FindStreamSingleLevel( *m_reader.get(), currentDirEntry, name, false );
|
||||
currentDirEntry = FindStreamSingleLevel( currentDirEntry, name, false );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,9 +310,12 @@ std::map<wxString, wxString> ALTIUM_PARSER::ReadProperties()
|
||||
else
|
||||
value = wxString( valueS.c_str(), wxConvISO8859_1 );
|
||||
|
||||
// Breathless hack because I haven't a clue what the story is here (but this character
|
||||
// appears in a lot of radial dimensions and is rendered by Altium as a space).
|
||||
value.Replace( wxT( "ÿ" ), wxT( " " ) );
|
||||
if( canonicalKey != wxS( "PATTERN" ) && canonicalKey != wxS( "SOURCEFOOTPRINTLIBRARY" ) )
|
||||
{
|
||||
// Breathless hack because I haven't a clue what the story is here (but this character
|
||||
// appears in a lot of radial dimensions and is rendered by Altium as a space).
|
||||
value.Replace( wxT( "ÿ" ), wxT( " " ) );
|
||||
}
|
||||
|
||||
if( canonicalKey == wxT( "DESIGNATOR" )
|
||||
|| canonicalKey == wxT( "NAME" )
|
||||
@@ -341,3 +422,28 @@ wxString ALTIUM_PARSER::ReadString( const std::map<wxString, wxString>& aProps,
|
||||
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
|
||||
wxString ALTIUM_PARSER::ReadUnicodeString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault )
|
||||
{
|
||||
const auto& unicodeFlag = aProps.find( wxS( "UNICODE" ) );
|
||||
|
||||
if( unicodeFlag != aProps.end() && unicodeFlag->second.Contains( wxS( "EXISTS" ) ) )
|
||||
{
|
||||
const auto& unicodeValue = aProps.find( wxString( "UNICODE__" ) + aKey );
|
||||
|
||||
if( unicodeValue != aProps.end() )
|
||||
{
|
||||
wxArrayString arr = wxSplit( unicodeValue->second, ',', '\0' );
|
||||
wxString out;
|
||||
|
||||
for( wxString part : arr )
|
||||
out += wxString( wchar_t( wxAtoi( part ) ) );
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
return ReadString( aProps, aKey, aDefault );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Thomas Pointhuber <thomas.pointhuber@gmx.at>
|
||||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -63,8 +63,16 @@ public:
|
||||
|
||||
const CFB::CompoundFileReader& GetCompoundFileReader() const { return *m_reader; }
|
||||
|
||||
std::map<wxString, wxString> ListLibFootprints() const;
|
||||
|
||||
wxString FindLibFootprintDirName( const wxString& aFpUnicodeName ) const;
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* FindStream( const std::vector<std::string>& aStreamPath ) const;
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* FindStreamSingleLevel( const CFB::COMPOUND_FILE_ENTRY* aEntry,
|
||||
const std::string aName,
|
||||
const bool aIsStream ) const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<CFB::CompoundFileReader> m_reader;
|
||||
std::vector<char> m_buffer;
|
||||
@@ -107,24 +115,31 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
wxString ReadWxString()
|
||||
wxScopedCharBuffer ReadCharBuffer()
|
||||
{
|
||||
uint8_t len = Read<uint8_t>();
|
||||
if( GetRemainingBytes() >= len )
|
||||
{
|
||||
// TODO: Identify where the actual code page is stored. For now, this default code page
|
||||
// has limited impact, because recent Altium files come with a UTF16 string table
|
||||
wxString val = wxString( m_pos, wxConvISO8859_1, len );
|
||||
char* buf = new char[len];
|
||||
memcpy( buf, m_pos, len );
|
||||
m_pos += len;
|
||||
return val;
|
||||
|
||||
return wxScopedCharBuffer::CreateOwned( buf, len );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_error = true;
|
||||
return wxString( "" );
|
||||
return wxScopedCharBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
wxString ReadWxString()
|
||||
{
|
||||
// TODO: Identify where the actual code page is stored. For now, this default code page
|
||||
// has limited impact, because recent Altium files come with a UTF16 string table
|
||||
return wxString( ReadCharBuffer(), wxConvISO8859_1 );
|
||||
}
|
||||
|
||||
std::map<uint32_t, wxString> ReadWideStringTable()
|
||||
{
|
||||
std::map<uint32_t, wxString> table;
|
||||
@@ -225,6 +240,9 @@ public:
|
||||
static wxString ReadString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault );
|
||||
|
||||
static wxString ReadUnicodeString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault );
|
||||
|
||||
void Skip( size_t aLength )
|
||||
{
|
||||
if( GetRemainingBytes() >= aLength )
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017-2022 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -117,6 +117,12 @@ bool POLYGON_GEOM_MANAGER::IsPolygonInProgress() const
|
||||
}
|
||||
|
||||
|
||||
int POLYGON_GEOM_MANAGER::PolygonPointCount() const
|
||||
{
|
||||
return m_lockedPoints.PointCount();
|
||||
}
|
||||
|
||||
|
||||
bool POLYGON_GEOM_MANAGER::NewPointClosesOutline( const VECTOR2I& aPt ) const
|
||||
{
|
||||
return m_lockedPoints.PointCount() > 0 && m_lockedPoints.CPoint( 0 ) == aPt;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019-2021 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -154,6 +154,22 @@ void KIGFX::PREVIEW::DrawTextNextToCursor( KIGFX::VIEW* aView, const VECTOR2D& a
|
||||
textPos.x -= 15.0 / gal->GetWorldScale();
|
||||
}
|
||||
|
||||
// text is left (or right) aligned, so a shadow text need a small offset to be draw
|
||||
// around the basic text
|
||||
int shadowXoffset = aDrawingDropShadows ? textDims.ShadowWidth : 0;
|
||||
|
||||
// Due to the fact a shadow text is drawn left or right aligned,
|
||||
// it needs an offset = shadowWidth/2 to be drawn at the same place as normal text
|
||||
// But for some reason we need to slightly modify this offset
|
||||
// for a better look for KiCad font (better alignment of shadow shape)
|
||||
const float adjust = 1.2f; // Value chosen after tests
|
||||
shadowXoffset *= adjust;
|
||||
|
||||
if( ( textAttrs.m_Halign == GR_TEXT_H_ALIGN_LEFT ) != viewFlipped )
|
||||
textPos.x -= shadowXoffset;
|
||||
else
|
||||
textPos.x += shadowXoffset;
|
||||
|
||||
gal->SetStrokeColor( aView->GetPainter()->GetSettings()->GetLayerColor( LAYER_AUX_ITEMS ) );
|
||||
textAttrs.m_Mirrored = viewFlipped; // Prevent text flipping when view is flipped
|
||||
textAttrs.m_Size = textDims.GlyphSize;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017-2022 Kicad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2017-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -167,25 +167,50 @@ void drawTicksAlongLine( KIGFX::VIEW* aView, const VECTOR2D& aOrigin, const VECT
|
||||
EDA_ANGLE labelAngle = - EDA_ANGLE( tickLine );
|
||||
VECTOR2I labelOffset = tickLine.Resize( majorTickLen );
|
||||
|
||||
// text is left (or right) aligned, so shadow text need a small offset to be draw
|
||||
// around the basic text
|
||||
int shadowXoffset = 0;
|
||||
|
||||
if( aDrawingDropShadows )
|
||||
{
|
||||
labelDims.StrokeWidth += 2 * labelDims.ShadowWidth;
|
||||
shadowXoffset = labelDims.ShadowWidth;
|
||||
// Due to the fact a shadow text is drawn left or right aligned,
|
||||
// it needs an offset = shadowXoffset to be drawn at the same place as normal text
|
||||
// But for some reason we need to slightly modify this offset
|
||||
// for a better look for KiCad font (better alignment of shadow shape)
|
||||
const float adjust = 1.2f; // Value chosen after tests
|
||||
shadowXoffset *= adjust;
|
||||
}
|
||||
|
||||
if( aView->IsMirroredX() )
|
||||
{
|
||||
labelOffset = -labelOffset;
|
||||
shadowXoffset = -shadowXoffset;
|
||||
}
|
||||
|
||||
TEXT_ATTRIBUTES labelAttrs;
|
||||
labelAttrs.m_Size = labelDims.GlyphSize;
|
||||
labelAttrs.m_StrokeWidth = labelDims.StrokeWidth;
|
||||
labelAttrs.m_Mirrored = aView->IsMirroredX(); // Prevent text mirrored when view is mirrored
|
||||
|
||||
if( EDA_ANGLE( aLine ) > ANGLE_0 )
|
||||
{
|
||||
labelAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT;
|
||||
labelAttrs.m_Angle = labelAngle;
|
||||
|
||||
// Adjust the text position of the shadow shape:
|
||||
labelOffset.x -= shadowXoffset * labelAttrs.m_Angle.Cos();;
|
||||
labelOffset.y += shadowXoffset * labelAttrs.m_Angle.Sin();;
|
||||
}
|
||||
else
|
||||
{
|
||||
labelAttrs.m_Halign = GR_TEXT_H_ALIGN_RIGHT;
|
||||
labelAttrs.m_Angle = labelAngle + ANGLE_180;
|
||||
|
||||
// Adjust the text position of the shadow shape:
|
||||
labelOffset.x += shadowXoffset * labelAttrs.m_Angle.Cos();;
|
||||
labelOffset.y -= shadowXoffset * labelAttrs.m_Angle.Sin();;
|
||||
}
|
||||
|
||||
BOX2D viewportD = aView->GetViewport();
|
||||
@@ -194,6 +219,8 @@ void drawTicksAlongLine( KIGFX::VIEW* aView, const VECTOR2D& aOrigin, const VECT
|
||||
viewport.Inflate( majorTickLen * 2 ); // Doesn't have to be accurate, just big enough not
|
||||
// to exclude anything that should be partially drawn
|
||||
|
||||
int isign = aView->IsMirroredX() ? -1 : 1;
|
||||
|
||||
for( int i = 0; i < numTicks; ++i )
|
||||
{
|
||||
const VECTOR2D tickPos = aOrigin + aLine.Resize( tickSpace * i );
|
||||
@@ -216,7 +243,7 @@ void drawTicksAlongLine( KIGFX::VIEW* aView, const VECTOR2D& aOrigin, const VECT
|
||||
}
|
||||
|
||||
gal->SetLineWidth( labelAttrs.m_StrokeWidth / 2 );
|
||||
gal->DrawLine( tickPos, tickPos + tickLine.Resize( length ) );
|
||||
gal->DrawLine( tickPos, tickPos + tickLine.Resize( length*isign ) );
|
||||
|
||||
if( drawLabel )
|
||||
{
|
||||
@@ -244,9 +271,10 @@ void drawBacksideTicks( KIGFX::VIEW* aView, const VECTOR2D& aOrigin, const VECTO
|
||||
TEXT_DIMS textDims = GetConstantGlyphHeight( gal, -1 );
|
||||
const double backTickSpace = aLine.EuclideanNorm() / aNumDivisions;
|
||||
VECTOR2D backTickVec = aLine;
|
||||
int isign = aView->IsMirroredX() ? -1 : 1;
|
||||
|
||||
RotatePoint( backTickVec, -ANGLE_90 );
|
||||
backTickVec = backTickVec.Resize( aTickLen );
|
||||
backTickVec = backTickVec.Resize( aTickLen * isign );
|
||||
|
||||
BOX2D viewportD = aView->GetViewport();
|
||||
BOX2I viewport( VECTOR2I( viewportD.GetPosition() ), VECTOR2I( viewportD.GetSize() ) );
|
||||
|
||||
@@ -569,9 +569,42 @@ bool PROJECT_FILE::SaveToFile( const wxString& aDirectory, bool aForce )
|
||||
|
||||
bool PROJECT_FILE::SaveAs( const wxString& aDirectory, const wxString& aFile )
|
||||
{
|
||||
wxFileName oldFilename( GetFilename() );
|
||||
wxString oldProjectName = oldFilename.GetName();
|
||||
wxString oldProjectPath = oldFilename.GetPath();
|
||||
|
||||
Set( "meta.filename", aFile + "." + ProjectFileExtension );
|
||||
SetFilename( aFile );
|
||||
|
||||
auto updatePath =
|
||||
[&]( wxString& aPath )
|
||||
{
|
||||
if( aPath.StartsWith( oldProjectName + wxS( "." ) ) )
|
||||
aPath.Replace( oldProjectName, aFile, false );
|
||||
else if( aPath.StartsWith( oldProjectPath + wxS( "/" ) ) )
|
||||
aPath.Replace( oldProjectPath, aDirectory, false );
|
||||
};
|
||||
|
||||
updatePath( m_BoardDrawingSheetFile );
|
||||
|
||||
for( int ii = LAST_PATH_FIRST; ii < (int) LAST_PATH_SIZE; ++ii )
|
||||
updatePath( m_PcbLastPath[ ii ] );
|
||||
|
||||
auto updatePathByPtr =
|
||||
[&]( const std::string& aPtr )
|
||||
{
|
||||
if( std::optional<wxString> path = Get<wxString>( aPtr ) )
|
||||
{
|
||||
updatePath( path.value() );
|
||||
Set( aPtr, path.value() );
|
||||
}
|
||||
};
|
||||
|
||||
updatePathByPtr( "schematic.page_layout_descr_file" );
|
||||
updatePathByPtr( "schematic.plot_directory" );
|
||||
updatePathByPtr( "schematic.ngspice.workbook_filename" );
|
||||
updatePathByPtr( "pcbnew.page_layout_descr_file" );
|
||||
|
||||
// While performing Save As, we have already checked that we can write to the directory
|
||||
// so don't carry the previous flag
|
||||
SetReadOnly( false );
|
||||
|
||||
+2
-1
@@ -63,7 +63,8 @@ void RC_ITEM::SetItems( const EDA_ITEM* aItem, const EDA_ITEM* bItem,
|
||||
{
|
||||
m_ids.clear();
|
||||
|
||||
m_ids.push_back( aItem->m_Uuid );
|
||||
if( aItem )
|
||||
m_ids.push_back( aItem->m_Uuid );
|
||||
|
||||
if( bItem )
|
||||
m_ids.push_back( bItem->m_Uuid );
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user