mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-10 01:02:08 +10:00
Compare commits
1125 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bb3b37f23b | |||
| fcea5975a8 | |||
| 2294ac45a2 | |||
| 5598f22b2f | |||
| 812b7adb28 | |||
| 9fd5a8fe96 | |||
| 0b8952e354 | |||
| 5c47ff1ef0 | |||
| b85b93404b | |||
| b46f46aa99 | |||
| 48266d3b27 | |||
| eb6cc76f02 | |||
| a5d512ca37 | |||
| 1d038b5f8c | |||
| 9366f9c602 | |||
| 23b4fcae02 | |||
| 14a994e68f | |||
| 894ff1a2cb | |||
| 78dcd27e1d | |||
| 714db98afa | |||
| 2faa2c6d61 | |||
| 3c45336afe | |||
| a0601cc83d | |||
| 9925d58347 | |||
| 6c241b3180 | |||
| 838adc9a51 | |||
| 41d2b73cca | |||
| 8d3789a0b0 | |||
| 95f65dcdf1 | |||
| 3d0f9554b0 | |||
| 0c21e013b4 | |||
| f8e24b0937 | |||
| 37d5ce18fc | |||
| e9a2785344 | |||
| 4de3b6d97c | |||
| 92a2bb9809 | |||
| 440b953531 | |||
| 1bc11e09ab | |||
| f20b896184 | |||
| 49d93b42a4 | |||
| b279510e5c | |||
| a83cda9ecd | |||
| f63b422a8c | |||
| 7af919b303 | |||
| 1c1ec2fcf5 | |||
| 8ccdd84a6f | |||
| 54ff518438 | |||
| c893b37fdf | |||
| 81e259bb62 | |||
| d5aac6b265 | |||
| d544797047 | |||
| 8ed2c0c9a5 | |||
| 2d1cf515d6 | |||
| 2553ffbba7 | |||
| 04418f8101 | |||
| c548a35939 | |||
| 777f4aa3fd | |||
| c0c226c580 | |||
| 40d234d1c4 | |||
| bc0d759d39 | |||
| b3497cdca8 | |||
| cc0f698c8b | |||
| b0123db3e7 | |||
| c9a32cc390 | |||
| 46d9e1f82a | |||
| 9596d6ca8e | |||
| 65315ed559 | |||
| 57bce6b8e5 | |||
| 403d0ea433 | |||
| 595cfb3ed1 | |||
| 2c689c584d | |||
| 84eaa1bf29 | |||
| 20e01762b8 | |||
| 08aec6fa9b | |||
| f51d19b39a | |||
| 8bfb3ade55 | |||
| 3847813351 | |||
| 67761b1027 | |||
| 7cca8f86b2 | |||
| 39976ec3d6 | |||
| a155aef596 | |||
| b24bfafb39 | |||
| 31ce46f147 | |||
| ce43a5d2e6 | |||
| 0d007e5737 | |||
| c0dac1a1db | |||
| ec7244042d | |||
| 88275e95e2 | |||
| add8566d4f | |||
| c5495ad14f | |||
| 94f1c68c7b | |||
| 3e67515f69 | |||
| 2091b8a03d | |||
| 235acf538f | |||
| 45404aaabd | |||
| 2727276a09 | |||
| cb6aa83269 | |||
| 39daa9e61f | |||
| 8313a62324 | |||
| c1d718a0f9 | |||
| 6e5174750f | |||
| 1cfb30f35e | |||
| ddfc615a6a | |||
| f53ad8c206 | |||
| 20645fed13 | |||
| d3c2e20359 | |||
| 46f693addf | |||
| 008ee8564b | |||
| b234015a32 | |||
| bb69d8dd04 | |||
| b02eaf928d | |||
| 2c4ff547fe | |||
| ca78cd030b | |||
| 51a12d61e1 | |||
| 661e5e2403 | |||
| ae8d015a78 | |||
| 59096d69ed | |||
| 66e1227182 | |||
| 19bdf41655 | |||
| 0acca63ccd | |||
| 6d2e876381 | |||
| 13f13191c4 | |||
| 86500cb4a0 | |||
| f7e5421f18 | |||
| c7bc8360ba | |||
| d91527a91c | |||
| 9e760ba655 | |||
| 9a2585d23f | |||
| 83723dd416 | |||
| 7597143b1b | |||
| 0cb4377830 | |||
| fbf2569a7e | |||
| 290406609b | |||
| 417c389b0a | |||
| 1af44eadfc | |||
| 364010ae63 | |||
| 7fb78237fb | |||
| c120bc10ed | |||
| 9c81ad0eec | |||
| bb564248d9 | |||
| 3deb988a06 | |||
| ae3e698d9e | |||
| 2735d7e343 | |||
| f4cc0ca360 | |||
| 99b7dbb6f3 | |||
| e3ca5244fe | |||
| a0b78a5e3d | |||
| 81b299865c | |||
| 3027753225 | |||
| 13997ee757 | |||
| 8c09fe72e6 | |||
| 6e9169242a | |||
| 91389ef09b | |||
| 921b503057 | |||
| efceedc924 | |||
| cad26211b3 | |||
| 36259bc83b | |||
| 024ede48a8 | |||
| b44c3bad62 | |||
| 0741f4334b | |||
| 46f20a75ec | |||
| 34ea20eedd | |||
| 08a0e451e7 | |||
| 53eb70e693 | |||
| 1b8a72d24a | |||
| 04840bac7b | |||
| 0a97b53f60 | |||
| 4d3f2968c1 | |||
| d5f3457c43 | |||
| 0c76b93db0 | |||
| 197f9ca216 | |||
| c8af6dbbb2 | |||
| 0a444f5ee7 | |||
| f0172f9adc | |||
| 5c9754baf4 | |||
| ef5bde9091 | |||
| a4efb57452 | |||
| 58aa0ab5be | |||
| 32b2713732 | |||
| cb21392d1e | |||
| 149cdbca48 | |||
| 73e4d6fc93 | |||
| 08bc4f5170 | |||
| 813baee504 | |||
| 74e524e98c | |||
| a8f5155acd | |||
| dd06195035 | |||
| 19ea23895b | |||
| 61444db46d | |||
| 54e991891d | |||
| ba735dd350 | |||
| 6b1913fd5b | |||
| c6f6aa9186 | |||
| ef51c44e54 | |||
| 5dc911776c | |||
| 9757e81500 | |||
| 46f8506c39 | |||
| f1ccfa86c0 | |||
| 5b2a9c0e43 | |||
| 81a6cf282b | |||
| 984edc196b | |||
| e5fff0b538 | |||
| 26c3c488e0 | |||
| 62bb6aac05 | |||
| 1a1e8ae56f | |||
| 7a8e25ab39 | |||
| 7b47a747bf | |||
| c4b66f5995 | |||
| 97cc9ca6c8 | |||
| 252b9ef560 | |||
| 77d038cef9 | |||
| 6ce5d305f1 | |||
| 2d0eb136fe | |||
| 4c03d9f658 | |||
| c5c4d6c04e | |||
| c7f468a0bc | |||
| 41b670616c | |||
| f62de41a95 | |||
| e6bdedfaea | |||
| e2e33a1b13 | |||
| 2266dadcba | |||
| 149f05f20c | |||
| 539b3c68de | |||
| 185eb9d1d3 | |||
| 9525505865 | |||
| a91e8dd062 | |||
| 5ce3d6d4b3 | |||
| facf816458 | |||
| afadc5e171 | |||
| a91eb15837 | |||
| cd74e417a9 | |||
| 7ca6eb0e2f | |||
| 78600f1c24 | |||
| 7aa6f31e67 | |||
| e91dc72424 | |||
| f9e2c1f1fa | |||
| bc49daf1be | |||
| dc07d2732b | |||
| 2f76bb8446 | |||
| cc286f9c41 | |||
| 42ca1926e1 | |||
| 007a52f0b5 | |||
| 7caadec1ec | |||
| 0f3f2a350b | |||
| bfe044f3f6 | |||
| 4eda278bc0 | |||
| 3379987a74 | |||
| c6b2cba3aa | |||
| a6538947d0 | |||
| 54e97b9adc | |||
| 4ebd1deed4 | |||
| af2195798f | |||
| c7a04075f4 | |||
| ebf988eaba | |||
| 0cd9f97e70 | |||
| 40d9b296da | |||
| 3f8dee89bb | |||
| 82d265e457 | |||
| 6aa63d3a7b | |||
| fdc76c80cf | |||
| a574eac4e6 | |||
| beb6c4857d | |||
| 8e5b4b0ecc | |||
| a92c6de926 | |||
| e38f4121b9 | |||
| bd40ad7dda | |||
| 767df37286 | |||
| fc33be65ab | |||
| a4639d3f1a | |||
| 405f8367df | |||
| dbf3a1e64d | |||
| 82d5c4436e | |||
| e541026656 | |||
| 8be8c23213 | |||
| 54b0519f09 | |||
| 41a2f3ed78 | |||
| 8dd1b74f96 | |||
| b9613fa72d | |||
| 295504d7d9 | |||
| ea00c503ee | |||
| 162980da67 | |||
| f2cd0f2a56 | |||
| d38d2f9b1b | |||
| 22e59d991c | |||
| 1ffd9b50a8 | |||
| 1268f83f5e | |||
| ce0ac2460c | |||
| e9615d4d64 | |||
| 48a6857738 | |||
| b489adf7c7 | |||
| 1cfe2ee99a | |||
| 9888d5f4c8 | |||
| ac1c68c7c1 | |||
| 4a3304a20e | |||
| f8a9171e12 | |||
| 79abef597b | |||
| 5593804a6f | |||
| abb6fabf39 | |||
| 1566fc07b4 | |||
| b0e986b4f9 | |||
| fb0dc31b98 | |||
| 1188a2e3c6 | |||
| 56a97f28b9 | |||
| 1c36acf6db | |||
| f07fd9c5e6 | |||
| 27a24b45b3 | |||
| c567342aaa | |||
| d9b7dda449 | |||
| 99f2482b39 | |||
| aadc9e394d | |||
| 3fec176fc1 | |||
| 680397b44f | |||
| f94691bb0e | |||
| e1c30b93ec | |||
| ec2a85f8d8 | |||
| a6e4edcb61 | |||
| 8559843f2d | |||
| c58b27b5a2 | |||
| 95687438f9 | |||
| 14de8ea270 | |||
| ce64cb46e7 | |||
| 97babd38cc | |||
| d8b7e99044 | |||
| 2bf7de07f3 | |||
| fd75174d6d | |||
| 1cbb1b8200 | |||
| 6c61b5219f | |||
| 7575ae29d9 | |||
| 745901131e | |||
| 53b58ef35a | |||
| 2cc916c8c1 | |||
| 58a4ff987f | |||
| d506feac27 | |||
| 4aeaa25d1a | |||
| b9cf1b4aa8 | |||
| ec7f195a2e | |||
| 1b7f24bae4 | |||
| 3939d2c5a7 | |||
| 2ee81093a0 | |||
| ed6792800b | |||
| bc5fc23f38 | |||
| 36f8674417 | |||
| 153b374191 | |||
| f573930ddf | |||
| d6ac3c4018 | |||
| e9afbaecdb | |||
| c761677bed | |||
| f188f239b5 | |||
| 3c458b9f16 | |||
| 5a269afd2f | |||
| 43b232ad45 | |||
| e4b155b12f | |||
| cf7692fa9a | |||
| bff46cf6d5 | |||
| 58a615b548 | |||
| 870199398c | |||
| c946e34144 | |||
| 7ccad5bf08 | |||
| 6821718b8d | |||
| e6a56e8157 | |||
| 71afe72f37 | |||
| f9d22b3d6f | |||
| 53e6b4014c | |||
| c05b1a2131 | |||
| f6d6b9a370 | |||
| 6c2bb797ad | |||
| ddd634c825 | |||
| 1bcb630619 | |||
| a75c9830e5 | |||
| 0e04d168e7 | |||
| d1a7227f4c | |||
| a8665271b0 | |||
| f7c19c4483 | |||
| df1331811c | |||
| aa5b81d0e5 | |||
| 38aa6bf660 | |||
| c2be767df1 | |||
| 9ba7b66d05 | |||
| 48b8e10795 | |||
| 2d0fbf40a8 | |||
| ebe680fb8b | |||
| 0c806022f2 | |||
| 9b0eac7617 | |||
| d84f7dadf5 | |||
| c7d8e8e0f0 | |||
| 08882a5167 | |||
| b745ae8e15 | |||
| 2a72c8380c | |||
| cc008568a0 | |||
| c5b5465bab | |||
| 0a7e5c7dc7 | |||
| d62221b796 | |||
| 3e0a698d32 | |||
| c37b0f3071 | |||
| 0fcd523d6b | |||
| ccf6e7bb7e | |||
| d211ea6ffc | |||
| a5bd532e47 | |||
| ddfb64f1a4 | |||
| 5198c9e2b5 | |||
| b39f685a90 | |||
| b2501ccba1 | |||
| 3f4b0475bc | |||
| f43cd8d90a | |||
| 66bdd41b29 | |||
| c84fc3a200 | |||
| 1f44d63865 | |||
| c4b329744e | |||
| dda588b28f | |||
| 283232630c | |||
| cd5d5011c6 | |||
| 217c0b1b67 | |||
| 4f0018d655 | |||
| 5ac8379693 | |||
| 72d0ab0d94 | |||
| 3e05634713 | |||
| 87e0997377 | |||
| d1b29ec228 | |||
| aad6cef831 | |||
| 2bd78110a7 | |||
| 6458dfd39b | |||
| e342ed1c2c | |||
| f6ad118044 | |||
| 5dc090828c | |||
| f1611bbf0f | |||
| d65609b3d2 | |||
| b3d63e9f22 | |||
| dc8612a167 | |||
| 1fbd3c1dae | |||
| fba2ecc384 | |||
| 3048127024 | |||
| 017afda5a4 | |||
| 54bcd99d17 | |||
| 7ba7afe680 | |||
| d9cffc1a34 | |||
| 781a8389d0 | |||
| 32e273df6e | |||
| cbd58a1dd8 | |||
| beb574c38f | |||
| 8e05394203 | |||
| e2c0723a23 | |||
| 7973549819 | |||
| 8e6f7a07e5 | |||
| aadeac3f34 | |||
| 422545ffe2 | |||
| 649caea538 | |||
| e7260a24e4 | |||
| 08e1a371b7 | |||
| 105f38e97f | |||
| ff1d26b75b | |||
| 43bc49303c | |||
| 5c7143b1a0 | |||
| 900fea58a1 | |||
| 3f8582df78 | |||
| bbcc196e9f | |||
| 3423f00c15 | |||
| 42fe174a69 | |||
| c1c87a2454 | |||
| d35566cdf5 | |||
| c2aa863c2a | |||
| aa1a327ac1 | |||
| b7a1ef6664 | |||
| fc7fd2aed8 | |||
| 2c4aba1557 | |||
| 703ec78974 | |||
| fc36f9d632 | |||
| 44797477ba | |||
| a739e2c51b | |||
| 1160286bc7 | |||
| e4cf9d5fda | |||
| 58bf48d8ac | |||
| 57a9577016 | |||
| 7c26b7aa94 | |||
| 0555d4b86e | |||
| c59597d8f0 | |||
| 0286894338 | |||
| ec06e03641 | |||
| 5f466110ad | |||
| 579eaccf50 | |||
| a86ff5c6e4 | |||
| c64c9fb5b2 | |||
| c945dc89ad | |||
| a9f177b980 | |||
| b85bd09778 | |||
| 62cc726070 | |||
| 959c5be424 | |||
| 5daa7c7bc9 | |||
| 43262cea6a | |||
| af39da27aa | |||
| 06b56e57ad | |||
| 545df1b1fa | |||
| 8a3f017468 | |||
| 980055d4c0 | |||
| 53f09e6143 | |||
| 23d702eeb5 | |||
| 3a419c0959 | |||
| 97e44fba1e | |||
| ac93a97e85 | |||
| 34bc347140 | |||
| e8b1258f09 | |||
| caa92e973d | |||
| 95c8ee3bf6 | |||
| 0af2d068ea | |||
| f12402e024 | |||
| 6ec5c165f5 | |||
| 686754faa0 | |||
| 2f97b39f18 | |||
| 0e62f97ed7 | |||
| ea210d816d | |||
| c200a2ffbf | |||
| 10905a7f0a | |||
| fad005cccf | |||
| 7bb1a86f48 | |||
| a3f8910268 | |||
| 1bf2825f80 | |||
| ab64e8bb14 | |||
| c1ed488b7c | |||
| 00c9744c40 | |||
| f73e8197ce | |||
| d953c75b33 | |||
| 191e82caf3 | |||
| 8b0af57c35 | |||
| 7a5de6bad0 | |||
| 2a0da6e794 | |||
| 38b057888f | |||
| b14b7afd39 | |||
| fb6b1464a3 | |||
| 328cf0e9b7 | |||
| ebb6a57ee8 | |||
| 62893ffb7c | |||
| 0e1db4ddb1 | |||
| 699762707a | |||
| efc92dfc71 | |||
| 321995a704 | |||
| d1ff654fc6 | |||
| 842d056fd7 | |||
| 58a794e8a7 | |||
| 3fbec7fb13 | |||
| 81194fbcab | |||
| f79498bc22 | |||
| a32105e156 | |||
| 65a6e30986 | |||
| 2eeb05e7af | |||
| ef07d109cf | |||
| d27b049110 | |||
| ba9924cc99 | |||
| 5a57c58563 | |||
| 66e29aa275 | |||
| 9d465b3156 | |||
| 127ea2b84c | |||
| db1950621e | |||
| b134c8f2d9 | |||
| fc9988f682 | |||
| f259604274 | |||
| 32053fb2a8 | |||
| 97d7d51fae | |||
| 327a30215e | |||
| 9c0784d59f | |||
| f63b6e5c0d | |||
| 606d6a50be | |||
| 6abea34d56 | |||
| 744e6a2576 | |||
| dff7860002 | |||
| 0ac2c5bd9d | |||
| adfedf11ce | |||
| 8fc5fe4c18 | |||
| 02b2c036ba | |||
| 9ac8f9d966 | |||
| ad6e45da23 | |||
| 94c8512c11 | |||
| 3776955d7b | |||
| 5981f96916 | |||
| ad5bdbe22d | |||
| fc717870f1 | |||
| f9a32ebce3 | |||
| 271b38c51c | |||
| a74f00a5fd | |||
| 98087d8889 | |||
| 1849eec874 | |||
| 85cb01b0d5 | |||
| f6e5078028 | |||
| 22b06e2a3b | |||
| 5e00e3128b | |||
| 5de31dd7bb | |||
| 06e2342d36 | |||
| 287157016f | |||
| 5f020414a0 | |||
| 1eeed9174a | |||
| abb9c5ce6f | |||
| 6312e251f6 | |||
| 2131f9fe44 | |||
| 997afc0e84 | |||
| eff81b718d | |||
| 76cb664d5d | |||
| 5a998c9dc0 | |||
| dfc14c26f9 | |||
| fccd4b481a | |||
| 5d5aa05f08 | |||
| dc42dd8bd4 | |||
| c24d186476 | |||
| c68d91997f | |||
| f571992692 | |||
| 21815584ac | |||
| ad4716cd79 | |||
| e67c879472 | |||
| 6977d97332 | |||
| d1279ccc9a | |||
| 0da4375857 | |||
| 3e695a37f0 | |||
| 377d8c4ed5 | |||
| e48b94c91b | |||
| 8c85e7351c | |||
| d510483f31 | |||
| 54e9797566 | |||
| 5ffb223a0d | |||
| f65b43b578 | |||
| 727d46e8d3 | |||
| 04016ff879 | |||
| 2105391c89 | |||
| 71c0bacf9c | |||
| af5080b422 | |||
| 70edab78a4 | |||
| 47eaf46bb4 | |||
| 5ea18aa018 | |||
| ac4ec9c390 | |||
| 04a0d6bea9 | |||
| be334165ba | |||
| 13f7116552 | |||
| b529adefcb | |||
| 3afd1add40 | |||
| 6a232fee94 | |||
| a9df82cbab | |||
| a197bbc21a | |||
| 0610229157 | |||
| 5ec0616a1e | |||
| 81a0ff1d44 | |||
| 3c4b4adfb4 | |||
| 545e483397 | |||
| 309973e37f | |||
| 71534e065b | |||
| ff019542f8 | |||
| a7a99cc4ec | |||
| 5b5b75142f | |||
| d8b915f8a5 | |||
| 83e7c0b077 | |||
| 4738a23fc6 | |||
| 7c6bd1804b | |||
| f949fa5087 | |||
| 700a09ed86 | |||
| 1b3d6fb2fc | |||
| 3446505c27 | |||
| 34c2c736ad | |||
| c75711642a | |||
| eef4988177 | |||
| 05207700fe | |||
| 0c75ab2b5a | |||
| 8850616584 | |||
| e6b782ee64 | |||
| 3003ca4ed2 | |||
| d2b6584ef0 | |||
| 1ac18b3819 | |||
| 3d69e259be | |||
| 021bac8f83 | |||
| 2f98f0c75d | |||
| e7945df218 | |||
| 8694606441 | |||
| 468f482db9 | |||
| e2fb415a59 | |||
| 34720db33a | |||
| 146634f75d | |||
| 6f19985c73 | |||
| 0507812178 | |||
| 368ec6a30d | |||
| c1268afb68 | |||
| 1c1703d606 | |||
| 3e18c5e1db | |||
| fbc3c4bfc4 | |||
| 0b8a3d6f9f | |||
| f0a2473763 | |||
| 91f21c1896 | |||
| 9808e672c5 | |||
| 7e310a9a9c | |||
| 4843cc729f | |||
| 335e2a572f | |||
| 12e49ceabf | |||
| f23f396c0a | |||
| 94b92cc0d7 | |||
| 448f87666d | |||
| 8c0cec70de | |||
| 05eba5195e | |||
| e5c54242bc | |||
| f7f669bff3 | |||
| 0a490d148a | |||
| bee14895d7 | |||
| 8def96d03c | |||
| dab4e76f44 | |||
| ac81b30e8e | |||
| 689ddebdb8 | |||
| 2b0d9dd9d3 | |||
| b335f0aabe | |||
| bdfa255439 | |||
| bc3875ecbf | |||
| 59f516df9c | |||
| 0c86f60752 | |||
| 91deb1d7da | |||
| 1714ddb444 | |||
| 35326e7d17 | |||
| b2dc050c32 | |||
| eb58f1786a | |||
| 16ce229b57 | |||
| 93954f60c7 | |||
| dc533368a8 | |||
| e9a54d1fe2 | |||
| cfd7af2793 | |||
| f8310b1fac | |||
| 8a125e8a4f | |||
| b975cc79b1 | |||
| 171ebf4473 | |||
| 5cb9824da4 | |||
| 6ef5ad5854 | |||
| 18edd60763 | |||
| ea1da54202 | |||
| 7497e89afd | |||
| 8ed165766f | |||
| 8c98e9dece | |||
| a082e0be63 | |||
| 6f0df4fdc9 | |||
| d85f496702 | |||
| ef24664eac | |||
| bfb554a930 | |||
| 0ff52979ea | |||
| eb1c4a6688 | |||
| 47d42c5456 | |||
| 297a4f3518 | |||
| d678f6fed1 | |||
| 3583d6e5f5 | |||
| e84e0c10e1 | |||
| b6c1ebd079 | |||
| 42190d3498 | |||
| 00bc6808d8 | |||
| 1e90621545 | |||
| 06b204fc38 | |||
| ac95d45f95 | |||
| 16e3241a94 | |||
| 1760161aa3 | |||
| c57e5f837c | |||
| 024884d85d | |||
| 50562ae901 | |||
| c8d0711889 | |||
| 4338200088 | |||
| 5ea4ed44a4 | |||
| b1a1611a3a | |||
| 9af88002b0 | |||
| a6386dda96 | |||
| 352b3aeb6f | |||
| 5d6b787404 | |||
| 3e36bce7ad | |||
| 5d4cbadf6e | |||
| 6d10c45a18 | |||
| 4c04b72d44 | |||
| dd15702ca6 | |||
| c6bfb5a562 | |||
| bfa71e93d5 | |||
| 1a048d0b7c | |||
| 6039f85631 | |||
| c843d8c28d | |||
| e7b05f109f | |||
| 5d2c4e0fc9 | |||
| ac0da8667c | |||
| cc81fa1a56 | |||
| 954bf200d2 | |||
| 7bf8ff9347 | |||
| 1eba691750 | |||
| c20b17b12e | |||
| b734c87946 | |||
| 5e25f25fc7 | |||
| 80582f61ec | |||
| 9a43597f6f | |||
| 2993900cc6 | |||
| 39efdca0b8 | |||
| 2dcaabf3f2 | |||
| af9798772f | |||
| 4ddcea7bc7 | |||
| 6087b39ccd | |||
| b77120f742 | |||
| 0acae7c28d | |||
| 0cb0e950f7 | |||
| 951dc3861a | |||
| 0483656258 | |||
| 34a0000d3c | |||
| 426eb3c6c2 | |||
| 4c8cae36c1 | |||
| 5cd2ceeac3 | |||
| 979eb7a9cf | |||
| c9d60e4d4f | |||
| 948d8e7b4a | |||
| 2f06f00d2f | |||
| 45841657a0 | |||
| e481fdb986 | |||
| 44c358af2b | |||
| d57ce6dc4a | |||
| e9b81795b7 | |||
| 6c7e149c93 | |||
| db173acf77 | |||
| deae73f6be | |||
| 7ac43b5e1e | |||
| 514b659677 | |||
| 06d642b494 | |||
| 12b46bdfc8 | |||
| e98f61ae6f | |||
| 44cc3f1dd5 | |||
| 6e510c56a2 | |||
| b181a86fa9 | |||
| fbb28d74cd | |||
| bf9bf70761 | |||
| f7a5038912 | |||
| f62df8d58e | |||
| d0f6302038 | |||
| d7198e4705 | |||
| 8ea4ba6aab | |||
| e604a54dd8 | |||
| 85207733d5 | |||
| 3385d04d95 | |||
| ec597d964c | |||
| abf9faa05a | |||
| e2412c223a | |||
| edc4bd4928 | |||
| 90be75db5e | |||
| ee0a503bbb | |||
| eed1d9601c | |||
| ce3d5fc808 | |||
| 09db593d28 | |||
| 25cdfd199a | |||
| 92495b1cf0 | |||
| 039fabc916 | |||
| f7a73f2bcb | |||
| a6731fd284 | |||
| 5db8288b0a | |||
| aea4c434dd | |||
| 35dfe799c0 | |||
| 5087a84dc1 | |||
| bda92b6982 | |||
| 732cb102a3 | |||
| cf7dc0778b | |||
| 75b2afad09 | |||
| e85ffd1483 | |||
| 5abf2ebaa3 | |||
| b0164a1ddd | |||
| 371fee0614 | |||
| 28f56693a9 | |||
| 9ebfad7d05 | |||
| acbd3d8378 | |||
| 4997e5b3bf | |||
| 5e86621f37 | |||
| 84f2da5313 | |||
| f164473d25 | |||
| 8804295df6 | |||
| 8c3c6ea56e | |||
| 7f5f61f5b0 | |||
| 6d79b453de | |||
| 894f070fee | |||
| e115f87f65 | |||
| 6068619c43 | |||
| cb547e40fb | |||
| 502186b1e3 | |||
| a051382e6c | |||
| 4e3451bdf9 | |||
| 9f891d19c2 | |||
| 923107e3ea | |||
| a1d39c047e | |||
| 5b439c1603 | |||
| c3308fa6e9 | |||
| 19e1a3576a | |||
| 532b482fed | |||
| 6c34a4cd8d | |||
| de348acff7 | |||
| ce63423c66 | |||
| 293c3096b0 | |||
| 3db2a06f52 | |||
| 064d83d2c4 | |||
| a1a9171c7c | |||
| b0ce8242be | |||
| c08e52b994 | |||
| b454c017a2 | |||
| 9a6a8cc646 | |||
| 28cbc39b5f | |||
| 1b24c8eb16 | |||
| 80bd386564 | |||
| ddfac76b58 | |||
| bb22ef61ff | |||
| 4b9349fbcb | |||
| 7d13dd647a | |||
| a1a290671d | |||
| 0c99b2b6a6 | |||
| cce34c9d9a | |||
| 1e34913d1a | |||
| f419c1afb9 | |||
| 4b2242336a | |||
| 30ab42a47b | |||
| 34c9648b47 | |||
| 0aea4c6eed | |||
| ff43225f11 | |||
| 585351bb11 | |||
| 58ac3d8148 | |||
| 00a05f6f15 | |||
| a800542a14 | |||
| 65a5775d5d | |||
| 2001015f9e | |||
| cd3b03433f | |||
| 547fb9b44f | |||
| 78d76197cf | |||
| e351d2669d | |||
| 9209782401 | |||
| c406632299 | |||
| 23fc091667 | |||
| 6e6d70fcd3 | |||
| 56fef06b22 | |||
| 4897b803b6 | |||
| 6c698e935e | |||
| 1645eae18d | |||
| 5adbc2c6ca | |||
| e3b1f0d4e6 | |||
| bc88253c70 | |||
| 1d45bf345c | |||
| c61ec71ee1 | |||
| 35272c1339 | |||
| 93e057dfb2 | |||
| aef5c88a3f | |||
| 591bdd313c | |||
| 3f9caf9918 | |||
| 246decdf7c | |||
| 0bc8141dc7 | |||
| 6e8e8b9d49 | |||
| c8ff6afe6e | |||
| 714740da28 | |||
| 45b759fa75 | |||
| 2445f05767 | |||
| 22578a4e3f | |||
| 10a42b7fcf | |||
| 0498eb2c51 | |||
| d384711759 | |||
| 5e0c422c30 | |||
| 73cc182dad | |||
| 7932657fb2 | |||
| 50bacee70a | |||
| 1c0219f4bf | |||
| 4522d9aeb5 | |||
| a25d43b710 | |||
| 18261eab69 | |||
| 3b984d0850 | |||
| d72d898f3f | |||
| 03bc58eb96 | |||
| 17427a0071 | |||
| 39704e3625 | |||
| 6ef7459d46 | |||
| a6448676f7 | |||
| 4cf6f9f4a5 | |||
| 162b67bf25 | |||
| ccc90dd3a6 | |||
| 237639b9a1 | |||
| 37b89fe3a2 | |||
| 860bb0071b | |||
| 56fd800e77 | |||
| 1a95e43f9f | |||
| 9817aa549e | |||
| c38bd87a7d | |||
| 21e46b3835 | |||
| 6a4508b4a9 | |||
| 33d3e03ffb | |||
| 98c3804529 | |||
| 4f88bb988a | |||
| 5a4eeb2de2 | |||
| abf99285cf | |||
| e83a2bd5f8 | |||
| 445a56f563 | |||
| aa434048f3 | |||
| 1b043abfe5 | |||
| b08395ee27 | |||
| a23342f682 | |||
| 93a4978e68 | |||
| 0d845677c4 | |||
| ab10103e41 | |||
| 0d17046170 | |||
| 880e618e30 | |||
| 176abc2428 | |||
| 061bc520c6 | |||
| 9c9d6ecd70 | |||
| d9f5e2e42b | |||
| 0c1659cde0 | |||
| 53feb60b63 | |||
| 8c2700b92c | |||
| 298d575696 | |||
| 931138083f | |||
| f2a814e41c | |||
| d07965a3c0 | |||
| 9e1f5c3ac8 | |||
| 569a50e97a | |||
| 80e7e3a487 | |||
| 5d73617af3 | |||
| 8169e3a6ba | |||
| a7b48f4f52 | |||
| 89bf22bcf8 | |||
| ae99ce2702 | |||
| 61937d6d42 | |||
| e618a1e1ad | |||
| 513a229e64 | |||
| f834aa6d0b | |||
| 35d8b13d41 | |||
| 989e0a03e4 | |||
| c6cb77f4ef | |||
| af1a11e848 | |||
| 4bcff4a574 | |||
| 36f65423e0 | |||
| ef11c931a7 | |||
| 732a9954b7 | |||
| 2b5b904d8d | |||
| 6ca16d07e6 | |||
| 4f113f032d | |||
| e572412f1e | |||
| dd9e9f054c | |||
| 4ee7381959 | |||
| d11a8b906a | |||
| 9fdd96c889 | |||
| d776a3df32 | |||
| ebf06841a0 | |||
| 616b09b4b2 | |||
| dccd91e56b | |||
| 59c543da34 | |||
| 7c933fa0f3 | |||
| 8294caa8ba | |||
| a7637767cd | |||
| 2dccd41f41 | |||
| 2dfec28dc9 | |||
| fe527eece2 | |||
| d459ea898c | |||
| 19cfca3df8 | |||
| 3d3a6e27d2 | |||
| 10884452fd | |||
| 6d4c2a8141 | |||
| 66f4d98ff9 | |||
| a00028131f | |||
| 7f2b973638 | |||
| 144bfb01ad | |||
| 84d0da6308 | |||
| 0df3bc37a0 | |||
| a0b43def22 | |||
| 602c98ead4 | |||
| 4b64917654 | |||
| 030ba71126 | |||
| eb4d08be68 | |||
| b642dc6cbd | |||
| 112bfdd3d0 | |||
| 79f83308d8 | |||
| 5df467a254 | |||
| 7c4d82b28c | |||
| 6b7d1c4277 | |||
| a0ae53d53c | |||
| bd79ef2817 | |||
| 69e2296c23 | |||
| 7d3a7c30ca | |||
| bea19f326c | |||
| ba694add0c | |||
| f137a398dc | |||
| 15ac8ff2e9 | |||
| 1213dcaeac | |||
| 2ebcd1fe96 | |||
| 943d123ca9 | |||
| 79c29dc349 | |||
| 746b5fbe1a | |||
| 365c195091 | |||
| d89a500a5f | |||
| 085732fb2c | |||
| eab7654883 | |||
| 5488657984 | |||
| 1a256716db | |||
| 2b9c76e876 | |||
| 5ae8a3477e | |||
| 209e970c00 | |||
| ae96fb9eef | |||
| 401f2b5e6f | |||
| e2da0b884d | |||
| bcf390b888 | |||
| 144e8f0cfe | |||
| 84d744a80b | |||
| 5430ca71a3 | |||
| 4665d5d42e | |||
| 275918d079 | |||
| a83093519f | |||
| 2e14929eb1 | |||
| a0b7cdc30e | |||
| ab5c9ad143 | |||
| 4154225e71 | |||
| 3856af3e18 | |||
| 80e7ebcbe9 | |||
| abdf02eac8 | |||
| 746aadd8a2 | |||
| ac4496040f | |||
| d810096030 | |||
| 4727017be7 | |||
| b2dae15ee6 | |||
| 56e112ff81 | |||
| 6f5926e18e | |||
| b1f4773b10 | |||
| e5d33fb80d | |||
| b8545d27a1 | |||
| 70ac30473b | |||
| 4774e97ba2 | |||
| de7378c722 | |||
| e2b3ed1b0e | |||
| 99d38feb1c | |||
| a561f6a3f9 | |||
| 6eee1525ee | |||
| 02d38bed01 | |||
| b96bad2688 | |||
| 12ca93e2c9 | |||
| d9b9542883 | |||
| 9e04cff806 | |||
| 16600328cc | |||
| 85d7d8a450 | |||
| f358b5d87b | |||
| fa02280292 | |||
| 8ea53b6876 | |||
| 4d6e994555 | |||
| 10581c51fb | |||
| 2cf6b573a7 |
@@ -0,0 +1,8 @@
|
||||
Thank you for reporting issues and contributing ideas and features to DIYLC repository!
|
||||
|
||||
Before you proceed, please read the following:
|
||||
|
||||
* If you are reporting a bug, please attach the latest application log file together with description of steps that lead to the issue. They can be found in the user directory under `.diylc/logs` directory. On Windows 7 and later, it's located in `c:/Users/<your username>/.diylc/logs`. On Linux and MacOS, it's typically in `/Users/<your username>/.diylc/logs`.
|
||||
* If you are having issues starting the application under MacOS, make sure that 3rd party apps are allowed on your Mac. This document covers how to do it - https://support.apple.com/en-us/HT202491.
|
||||
* Try to look for similar unresolved issues that are already reported to avoid duplicates.
|
||||
* Make sure that you are running the latest version of DIYLC.
|
||||
@@ -0,0 +1,3 @@
|
||||
.idea
|
||||
*.iml
|
||||
*.eml
|
||||
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
@@ -1,22 +0,0 @@
|
||||
<map>
|
||||
<entry>
|
||||
<string>lastPath</string>
|
||||
<string>C:\Documents and Settings\Branislav Stojkovic\Desktop\oldFiles</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>zoom</string>
|
||||
<double>1.0</double>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>metric</string>
|
||||
<boolean>true</boolean>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>showTemplatesAtStartup</string>
|
||||
<boolean>false</boolean>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>default.org.diylc.components.semiconductors.TransistorTO92:Orientation</string>
|
||||
<org.diylc.common.Orientation>DEFAULT</org.diylc.common.Orientation>
|
||||
</entry>
|
||||
</map>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,74 +0,0 @@
|
||||
package org.diylc;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.log4j.PropertyConfigurator;
|
||||
import org.diylc.presenter.Presenter;
|
||||
import org.diylc.swing.gui.MainFrame;
|
||||
import org.diylc.swing.gui.TemplateDialog;
|
||||
|
||||
import com.diyfever.gui.miscutils.ConfigurationManager;
|
||||
import com.diyfever.gui.miscutils.PropertyInjector;
|
||||
|
||||
/**
|
||||
* Main class that runs DIYLC.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @see Presenter
|
||||
* @see MainFrame
|
||||
*/
|
||||
public class DIYLCStarter {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(Presenter.class);
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
URL url = DIYLCStarter.class.getResource("log4j.properties");
|
||||
Properties properties = new Properties();
|
||||
try {
|
||||
properties.load(url.openStream());
|
||||
PropertyConfigurator.configure(properties);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not initialize log4j configuration", e);
|
||||
}
|
||||
|
||||
LOG.info("Starting DIYLC with working directory " + System.getProperty("user.dir"));
|
||||
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not set Look&Feel", e);
|
||||
}
|
||||
|
||||
MainFrame mainFrame = new MainFrame();
|
||||
mainFrame.setLocationRelativeTo(null);
|
||||
mainFrame.setVisible(true);
|
||||
|
||||
boolean showTemplates = ConfigurationManager.getInstance().readBoolean(
|
||||
TemplateDialog.SHOW_TEMPLATES_KEY, true);
|
||||
if (showTemplates) {
|
||||
TemplateDialog templateDialog = new TemplateDialog(mainFrame, mainFrame.getPresenter());
|
||||
if (!templateDialog.getFiles().isEmpty()) {
|
||||
templateDialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
url = DIYLCStarter.class.getResource("/config.properties");
|
||||
properties = new Properties();
|
||||
try {
|
||||
LOG.info("Injecting default properties.");
|
||||
properties.load(new FileInputStream("config.properties"));
|
||||
PropertyInjector.injectProperties(properties);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not read config.properties file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
public class BadPositionException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import org.diylc.core.CreationMethod;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/**
|
||||
* Entity class used to describe a component type.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @see IDIYComponent
|
||||
*/
|
||||
public class ComponentType {
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private CreationMethod creationMethod;
|
||||
private String category;
|
||||
private String namePrefix;
|
||||
private String author;
|
||||
private Icon icon;
|
||||
private Class<? extends IDIYComponent<?>> instanceClass;
|
||||
private double zOrder;
|
||||
private boolean stretchable;
|
||||
|
||||
public ComponentType(String name, String description, CreationMethod creationMethod,
|
||||
String category, String namePrefix, String author, Icon icon,
|
||||
Class<? extends IDIYComponent<?>> instanceClass, double zOrder, boolean stretchable) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.creationMethod = creationMethod;
|
||||
this.category = category;
|
||||
this.namePrefix = namePrefix;
|
||||
this.author = author;
|
||||
this.icon = icon;
|
||||
this.instanceClass = instanceClass;
|
||||
this.zOrder = zOrder;
|
||||
this.stretchable = stretchable;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public CreationMethod getCreationMethod() {
|
||||
return creationMethod;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public String getNamePrefix() {
|
||||
return namePrefix;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public Class<? extends IDIYComponent<?>> getInstanceClass() {
|
||||
return instanceClass;
|
||||
}
|
||||
|
||||
public double getZOrder() {
|
||||
return zOrder;
|
||||
}
|
||||
|
||||
public boolean isStretchable() {
|
||||
return stretchable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
public enum Display {
|
||||
|
||||
NAME, VALUE;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* Enumerates all options that can be used when drawing a project.
|
||||
*
|
||||
* @see IPlugInPort#draw(java.awt.Graphics2D, java.util.Set, IComponentFiler)
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum DrawOption {
|
||||
|
||||
/**
|
||||
* Selection rectangle will be drawn when needed and selected components may
|
||||
* be rendered differently.
|
||||
*/
|
||||
SELECTION,
|
||||
/**
|
||||
* Selected zoom level will be applied to scale the {@link Graphics} before
|
||||
* drawing.
|
||||
*/
|
||||
ZOOM,
|
||||
/**
|
||||
* Grid lines are drawn.
|
||||
*/
|
||||
GRID,
|
||||
/**
|
||||
* Control points are drawn.
|
||||
*/
|
||||
CONTROL_POINTS,
|
||||
/**
|
||||
* Anti-aliasing is used when drawing.
|
||||
*/
|
||||
ANTIALIASING;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import org.diylc.core.Project;
|
||||
|
||||
/**
|
||||
* Enumerates all possible events between {@link IPlugInPort} and
|
||||
* {@link IPlugIn}. Some events overlap so be careful which ones you subscribe
|
||||
* for and how you process them.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum EventType {
|
||||
|
||||
/**
|
||||
* Called when zoom level changes. Typically only one parameter of type
|
||||
* {@link Double} is passed with new zoom level.
|
||||
*/
|
||||
ZOOM_CHANGED,
|
||||
/**
|
||||
* Called when a new project is loaded. New {@link Project} is the first
|
||||
* parameter. Boolean flag is the second parameter and it's true when new
|
||||
* project is loaded, false when the same project has been either reloaded
|
||||
* or loaded with undo/redo operations.
|
||||
*/
|
||||
PROJECT_LOADED,
|
||||
/**
|
||||
* Called when either current file name or modified flag are changed. The
|
||||
* first parameter is the current file name, the second one is a boolean
|
||||
* modified flag.
|
||||
*/
|
||||
FILE_STATUS_CHANGED,
|
||||
/**
|
||||
* Called when selection rectangle is changed. Object of type
|
||||
* {@link Rectangle} is the only parameter and it contains the new selection
|
||||
* rectangle.
|
||||
*/
|
||||
SELECTION_RECT_CHANGED,
|
||||
/**
|
||||
* Called when component selection is changed. New
|
||||
* {@link ComponentSelection} is attached as a parameter.
|
||||
*/
|
||||
SELECTION_CHANGED,
|
||||
/**
|
||||
* Called when selection size changes, together with a {@link Point2D}
|
||||
* object containing selection size (x = width, y = height). Size is
|
||||
* expressed in the default measure (cm for metric, inches for imperial).
|
||||
*/
|
||||
REPAINT,
|
||||
/**
|
||||
* Called when new component slot has been changed. The only parameter is
|
||||
* {@link ComponentType} and may be null.
|
||||
*/
|
||||
SLOT_CHANGED,
|
||||
/**
|
||||
* Called when the current project has been modified. Two instances of
|
||||
* {@link Project} are passed as parameters, one before and one after the
|
||||
* change. The third parameter is a string containing change description.
|
||||
*/
|
||||
PROJECT_MODIFIED,
|
||||
/**
|
||||
* Called when control points under the cursor are changed. A single
|
||||
* parameter is passed, an instance of
|
||||
* <code>Map<IDIYComponent<?>, Set<Integer>></code> containing all the
|
||||
* components and indices of their control points that are under the cursor.
|
||||
*/
|
||||
AVAILABLE_CTRL_POINTS_CHANGED,
|
||||
/**
|
||||
* Called when mouse cursor is moved. Point object is passed, containing the
|
||||
* current cursor location (not taking zoom into account).
|
||||
*/
|
||||
MOUSE_MOVED,
|
||||
/**
|
||||
* Called when a layer status is changed. The first parameter is a set of indices of locked layers. All layers not included are considered unlocked.
|
||||
*/
|
||||
LAYER_STATE_CHANGED,
|
||||
/**
|
||||
* Called to update the status message. New status message is passed as a first parameter.
|
||||
*/
|
||||
STATUS_MESSAGE_CHANGED;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
public enum GridType {
|
||||
|
||||
LINES, CROSSHAIR, DOT, NONE;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public interface IComponentFiler {
|
||||
|
||||
boolean testComponent(IDIYComponent<?> component);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
import com.diyfever.gui.simplemq.IMessageListener;
|
||||
|
||||
/**
|
||||
* Interface for plug-ins.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IPlugIn extends IMessageListener<EventType> {
|
||||
|
||||
/**
|
||||
* Method that connects the plug-in with {@link IPlugInPort}. Called by the
|
||||
* application when plug-in is installed.
|
||||
*
|
||||
* @param plugInPort
|
||||
*/
|
||||
void connect(IPlugInPort plugInPort);
|
||||
}
|
||||
@@ -1,331 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.Project;
|
||||
|
||||
import com.diyfever.gui.simplemq.IMessageListener;
|
||||
import com.diyfever.gui.simplemq.MessageDispatcher;
|
||||
import com.diyfever.gui.update.VersionNumber;
|
||||
|
||||
/**
|
||||
* Interface for communication between plug-ins and the application. Plug-ins
|
||||
* may acquire information or make changes through this interface. Application
|
||||
* events are dispatched to plug-ins through {@link MessageDispatcher}
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @see IPlugIn
|
||||
* @see MessageDispatcher
|
||||
* @see IMessageListener
|
||||
* @see EventType
|
||||
*/
|
||||
public interface IPlugInPort {
|
||||
|
||||
public static final String CHECK_BOX_MENU_ITEM = "org.diylc.checkBoxMenuItem";
|
||||
|
||||
/**
|
||||
* Returns size of the canvas that takes project dimensions into account as
|
||||
* well as zoom level. Each dimension is calculated as the product of the
|
||||
* actual size and the number of pixels per unit. If <code>useZoom</code> is
|
||||
* set to true, the result is scaled by zoom factor.
|
||||
*
|
||||
* @param useZoom
|
||||
*
|
||||
* @return canvas dimensions
|
||||
*/
|
||||
Dimension getCanvasDimensions(boolean useZoom);
|
||||
|
||||
/**
|
||||
* Returns an instance of {@link Cursor} that should be used at the
|
||||
* specified location.
|
||||
*
|
||||
* Note: point coordinates are scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
* @return cursor
|
||||
*/
|
||||
Cursor getCursorAt(Point point);
|
||||
|
||||
/**
|
||||
* Returns an instance of currently loaded project.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Project getCurrentProject();
|
||||
|
||||
/**
|
||||
* Loads specified {@link Project}.
|
||||
*
|
||||
* @param project
|
||||
* @param freshStart
|
||||
*/
|
||||
void loadProject(Project project, boolean freshStart);
|
||||
|
||||
/**
|
||||
* Creates a new project.
|
||||
*/
|
||||
void createNewProject();
|
||||
|
||||
/**
|
||||
* Loads a project from the specified file.
|
||||
*
|
||||
* @param fileName
|
||||
*/
|
||||
void loadProjectFromFile(String fileName);
|
||||
|
||||
/**
|
||||
* Saves the current project into the specified file.
|
||||
*
|
||||
* @param fileName
|
||||
*/
|
||||
void saveProjectToFile(String fileName);
|
||||
|
||||
/**
|
||||
* @return the current file name.
|
||||
*/
|
||||
String getCurrentFileName();
|
||||
|
||||
/**
|
||||
* @return true if the current project is modified.
|
||||
*/
|
||||
boolean isProjectModified();
|
||||
|
||||
/**
|
||||
* Shows a user dialog if there are changes to confirm that it's safe to
|
||||
* proceed.
|
||||
*
|
||||
* @return true, if file actions (new, open, close) can be taken
|
||||
*/
|
||||
boolean allowFileAction();
|
||||
|
||||
/**
|
||||
* Returns all available {@link ComponentType}s classified by category.
|
||||
* Result is a {@link Map} between category name to a {@link List} of all
|
||||
* {@link ComponentType}s that share that category name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Map<String, List<ComponentType>> getComponentTypes();
|
||||
|
||||
/**
|
||||
* Draws project on the provided {@link Graphics2D}. If the provided filter
|
||||
* is not null, it will be used to filter the components that are shown.
|
||||
*
|
||||
* @param g2d
|
||||
* @param drawOptions
|
||||
* specific drawing options
|
||||
* @param filter
|
||||
*/
|
||||
void draw(Graphics2D g2d, Set<DrawOption> drawOptions, IComponentFiler filter);
|
||||
|
||||
Double[] getAvailableZoomLevels();
|
||||
|
||||
/**
|
||||
* Returns current zoom level where <code>zoomLevel = 1.0d</code> means
|
||||
* 100%.
|
||||
*
|
||||
* @return current zoom level
|
||||
*/
|
||||
double getZoomLevel();
|
||||
|
||||
/**
|
||||
* Changes current zoom level where <code>zoomLevel = 1.0d</code> means 100%
|
||||
*
|
||||
* @param zoomLevel
|
||||
* new zoom leve
|
||||
*/
|
||||
void setZoomLevel(double zoomLevel);
|
||||
|
||||
/**
|
||||
* Notifies the presenter that mouse is clicked.
|
||||
*
|
||||
* Note: point coordinates are display based, i.e. scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
* @param ctrlDown
|
||||
* @param shiftDown
|
||||
* @param altDown
|
||||
*/
|
||||
void mouseClicked(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown);
|
||||
|
||||
/**
|
||||
* Notifies the presenter that mouse is moved.
|
||||
*
|
||||
* Note: point coordinates are display based, i.e. scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
* @param ctrlDown
|
||||
* @param shiftDown
|
||||
* @param altDown
|
||||
*/
|
||||
void mouseMoved(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown);
|
||||
|
||||
/**
|
||||
* Returns the current {@link ComponentTransferable}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<IDIYComponent<?>> getSelectedComponents();
|
||||
|
||||
/**
|
||||
* Selects all components in the project.
|
||||
*/
|
||||
void selectAll();
|
||||
|
||||
/**
|
||||
* Notification that drag has been started from the specified point.
|
||||
*
|
||||
* Note: point coordinates are scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
* @param ctrlDown
|
||||
* @param shiftDown
|
||||
* @param altDown
|
||||
*/
|
||||
void dragStarted(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown);
|
||||
|
||||
/**
|
||||
* Checks if it's possible to drop over the specified point.
|
||||
*
|
||||
* Note: point coordinates are scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
* @return
|
||||
*/
|
||||
boolean dragOver(Point point);
|
||||
|
||||
/**
|
||||
* Notification that drag has been ended in the specified point.
|
||||
*
|
||||
* Note: point coordinates are scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
*/
|
||||
void dragEnded(Point point);
|
||||
|
||||
/**
|
||||
* Returns current version number.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
VersionNumber getCurrentVersionNumber();
|
||||
|
||||
/**
|
||||
* Adds a list of components to the project.
|
||||
*
|
||||
* @param components
|
||||
*/
|
||||
void pasteComponents(List<IDIYComponent<?>> components);
|
||||
|
||||
/**
|
||||
* Deletes all the selected components from the project.
|
||||
*/
|
||||
void deleteSelectedComponents();
|
||||
|
||||
/**
|
||||
* Sets default value for the specified property name for currently selected
|
||||
* component types.
|
||||
*
|
||||
* @param propertyName
|
||||
* display name for property
|
||||
* @param value
|
||||
* new default value, must not be null
|
||||
*/
|
||||
void setSelectionDefaultPropertyValue(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Sets default value for the specified property name for projects.
|
||||
*
|
||||
* @param propertyName
|
||||
* display name for property
|
||||
* @param value
|
||||
* new default value, must not be null
|
||||
*/
|
||||
void setProjectDefaultPropertyValue(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* @return a list of properties that are mutual for all the selected
|
||||
* components. Resulting list may be empty if selected components do
|
||||
* not have mutual properties or can be null if the selection is
|
||||
* empty.
|
||||
*/
|
||||
List<PropertyWrapper> getMutualSelectionProperties();
|
||||
|
||||
/**
|
||||
* Applies specified properties to all the selected components. If some of
|
||||
* the properties are not applicable to some of the selected components an
|
||||
* exception will be thrown.
|
||||
*
|
||||
* @param properties
|
||||
*/
|
||||
void applyPropertiesToSelection(List<PropertyWrapper> properties);
|
||||
|
||||
/**
|
||||
* @return a list of editable properties of the current project.
|
||||
*/
|
||||
List<PropertyWrapper> getProjectProperties();
|
||||
|
||||
/**
|
||||
* Applies specified properties to the current project.
|
||||
*
|
||||
* @param properties
|
||||
*/
|
||||
void applyPropertiesToProject(List<PropertyWrapper> properties);
|
||||
|
||||
/**
|
||||
* Sets the new component slot. Specified component type will be used to
|
||||
* instantiate new component.
|
||||
*/
|
||||
void setNewComponentTypeSlot(ComponentType componentType);
|
||||
|
||||
/**
|
||||
* Changes default size notation, true for metric, false for imperial.
|
||||
*
|
||||
* @param isMetric
|
||||
*/
|
||||
void setMetric(boolean isMetric);
|
||||
|
||||
/**
|
||||
* Groups all selected components.
|
||||
*/
|
||||
void groupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Ungroups all selected components.
|
||||
*/
|
||||
void ungroupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Locks or unlocks the specified layer. All components within +- 0.5 range
|
||||
* will be affected by the change as well.
|
||||
*
|
||||
* @param layerZOrder
|
||||
* @param locked
|
||||
*/
|
||||
void setLayerLocked(int layerZOrder, boolean locked);
|
||||
|
||||
/**
|
||||
* @return selection size expressed in either inches or centimeters, based
|
||||
* on the user preference.
|
||||
*/
|
||||
Point2D calculateSelectionDimension();
|
||||
|
||||
/**
|
||||
* Sends each of the selected components one step back.
|
||||
*/
|
||||
void sendSelectionToBack();
|
||||
|
||||
/**
|
||||
* Brings each of the selected components one step to front.
|
||||
*/
|
||||
void bringSelectionToFront();
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
/**
|
||||
* Abstract layer between the app and platform worker thread implementation.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public interface ITask<T> {
|
||||
|
||||
/**
|
||||
* Runs in background thread.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
T doInBackground() throws Exception;
|
||||
|
||||
/**
|
||||
* Called if background thread fails.
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
void failed(Exception e);
|
||||
|
||||
/**
|
||||
* Called if background thread is executed correctly, the result is passed
|
||||
* as a parameter.
|
||||
*
|
||||
* @param result
|
||||
*/
|
||||
void complete(T result);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Stroke;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Repository for object that may be reused, such as {@link Stroke} or
|
||||
* {@link AlphaComposite}.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ObjectCache {
|
||||
|
||||
private static ObjectCache instance;
|
||||
|
||||
public static ObjectCache getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ObjectCache();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ObjectCache() {
|
||||
}
|
||||
|
||||
private Map<Integer, Stroke> basicStrokeMap = new HashMap<Integer, Stroke>();
|
||||
|
||||
public Stroke fetchBasicStroke(int width) {
|
||||
if (basicStrokeMap.containsKey(width)) {
|
||||
return basicStrokeMap.get(width);
|
||||
}
|
||||
Stroke stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
|
||||
basicStrokeMap.put(width, stroke);
|
||||
return stroke;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
public enum Orientation {
|
||||
|
||||
DEFAULT, _90, _180, _270;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this == DEFAULT) {
|
||||
return "Default";
|
||||
} else {
|
||||
return name().replace("_", "") + " degrees clockwise";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
public enum Power {
|
||||
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
|
||||
/**
|
||||
* Entity class for editable properties extracted from component objects.
|
||||
* Represents a single editable property together with it's current value.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class PropertyWrapper implements Cloneable {
|
||||
|
||||
private String name;
|
||||
private Class<?> type;
|
||||
private Object value;
|
||||
private Method setter;
|
||||
private Method getter;
|
||||
private boolean defaultable;
|
||||
private IPropertyValidator validator;
|
||||
|
||||
public PropertyWrapper(String name, Class<?> type, Method getter, Method setter,
|
||||
boolean defaultable, IPropertyValidator validator) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
this.defaultable = defaultable;
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
public void readFrom(Object object) throws IllegalArgumentException, IllegalAccessException,
|
||||
InvocationTargetException {
|
||||
this.value = getter.invoke(object);
|
||||
}
|
||||
|
||||
// public void readUniqueFrom(IDIYComponent component)
|
||||
// throws IllegalArgumentException, IllegalAccessException,
|
||||
// InvocationTargetException {
|
||||
// Object newValue = getter.invoke(component);
|
||||
// if (!newValue.equals(value)) {
|
||||
// this.value = null;
|
||||
// }
|
||||
// }
|
||||
|
||||
public void writeTo(Object object) throws IllegalArgumentException, IllegalAccessException,
|
||||
InvocationTargetException {
|
||||
setter.invoke(object, value);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean isDefaultable() {
|
||||
return defaultable;
|
||||
}
|
||||
|
||||
public IPropertyValidator getValidator() {
|
||||
return validator;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Object clone() throws CloneNotSupportedException {
|
||||
// // Try to invoke clone method on value if possible.
|
||||
// try {
|
||||
// Method cloneMethod = value.getClass().getMethod("clone");
|
||||
// return new Property(name, type, cloneMethod.invoke(value));
|
||||
// } catch (Exception e) {
|
||||
// }
|
||||
// return new Property(name, type, value);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (defaultable ? 1231 : 1237);
|
||||
result = prime * result + ((getter == null) ? 0 : getter.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((setter == null) ? 0 : setter.hashCode());
|
||||
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
PropertyWrapper other = (PropertyWrapper) obj;
|
||||
if (defaultable != other.defaultable)
|
||||
return false;
|
||||
if (getter == null) {
|
||||
if (other.getter != null)
|
||||
return false;
|
||||
} else if (!getter.equals(other.getter))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (setter == null) {
|
||||
if (other.setter != null)
|
||||
return false;
|
||||
} else if (!setter.equals(other.setter))
|
||||
return false;
|
||||
if (type == null) {
|
||||
if (other.type != null)
|
||||
return false;
|
||||
} else if (!type.equals(other.type))
|
||||
return false;
|
||||
if (value == null) {
|
||||
if (other.value != null)
|
||||
return false;
|
||||
} else if (!value.equals(other.value))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + " = " + value;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.diylc.common;
|
||||
|
||||
public enum ResistorColorCode {
|
||||
|
||||
NONE, _4_BAND, _5_BAND;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (name().startsWith("_")) {
|
||||
return name().substring(1).replace("_", " ").toLowerCase();
|
||||
}
|
||||
return name().substring(0, 1).toUpperCase() + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package org.diylc.components;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
|
||||
/**
|
||||
* Abstract implementation of {@link IDIYComponent} that contains component name
|
||||
* and toString.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class AbstractComponent<T> implements IDIYComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected String name = "";
|
||||
|
||||
public static Color SELECTION_COLOR = Color.red;
|
||||
public static Color LABEL_COLOR = Color.black;
|
||||
public static Color LABEL_COLOR_SELECTED = Color.red;
|
||||
public static Font LABEL_FONT = new Font("Tahoma", Font.PLAIN, 12);
|
||||
|
||||
@EditableProperty(defaultable = false)
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canControlPointOverlap(int index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest odd number, i.e. x when x is odd, or x + 1 when x is
|
||||
* even.
|
||||
*
|
||||
* @param x
|
||||
* @return
|
||||
*/
|
||||
protected int getClosestOdd(int x) {
|
||||
return (x / 2) * 2 + 1;
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
package org.diylc.components;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.geom.CubicCurve2D;
|
||||
|
||||
import org.diylc.common.ObjectCache;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IDrawingObserver;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.VisibilityPolicy;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static Color GUIDELINE_COLOR = Color.blue;
|
||||
public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
|
||||
|
||||
protected Point[] controlPoints = new Point[] { new Point(0, 0),
|
||||
new Point(DEFAULT_SIZE.convertToPixels() / 2, 0),
|
||||
new Point(DEFAULT_SIZE.convertToPixels() / 2, DEFAULT_SIZE.convertToPixels()),
|
||||
new Point(DEFAULT_SIZE.convertToPixels(), DEFAULT_SIZE.convertToPixels()) };
|
||||
|
||||
protected Color color = getDefaultColor();
|
||||
|
||||
/**
|
||||
* Draws the specified curve onto graphics.
|
||||
*
|
||||
* @param curve
|
||||
* @param g2d
|
||||
* @param componentState
|
||||
*/
|
||||
protected abstract void drawCurve(CubicCurve2D curve, Graphics2D g2d,
|
||||
ComponentState componentState);
|
||||
|
||||
/**
|
||||
* @return default color.
|
||||
*/
|
||||
protected abstract Color getDefaultColor();
|
||||
|
||||
@Override
|
||||
public void drawIcon(Graphics2D g2d, int width, int height) {
|
||||
g2d.setColor(getDefaultColor().darker());
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3));
|
||||
CubicCurve2D curve = new CubicCurve2D.Double(1, height - 1, width / 4, height / 3,
|
||||
3 * width / 4, 2 * height / 3, width - 1, 1);
|
||||
g2d.draw(curve);
|
||||
g2d.setColor(getDefaultColor());
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||
g2d.draw(curve);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D g2d, ComponentState componentState, Project project,
|
||||
IDrawingObserver drawingObserver) {
|
||||
if (componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING) {
|
||||
// Do not track guidelines.
|
||||
drawingObserver.stopTracking();
|
||||
g2d.setStroke(Constants.DASHED_STROKE);
|
||||
g2d.setColor(GUIDELINE_COLOR);
|
||||
g2d.drawLine(controlPoints[0].x, controlPoints[0].y, controlPoints[1].x,
|
||||
controlPoints[1].y);
|
||||
g2d.drawLine(controlPoints[1].x, controlPoints[1].y, controlPoints[2].x,
|
||||
controlPoints[2].y);
|
||||
g2d.drawLine(controlPoints[2].x, controlPoints[2].y, controlPoints[3].x,
|
||||
controlPoints[3].y);
|
||||
drawingObserver.startTracking();
|
||||
}
|
||||
CubicCurve2D curve = new CubicCurve2D.Double(controlPoints[0].x, controlPoints[0].y,
|
||||
controlPoints[1].x, controlPoints[1].y, controlPoints[2].x, controlPoints[2].y,
|
||||
controlPoints[3].x, controlPoints[3].y);
|
||||
|
||||
Composite oldComposite = g2d.getComposite();
|
||||
if (alpha < MAX_ALPHA) {
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha
|
||||
/ MAX_ALPHA));
|
||||
}
|
||||
// g2d.setColor(color.darker());
|
||||
// g2d.setStroke(new BasicStroke(thickness));
|
||||
// g2d.draw(path);
|
||||
// g2d.setColor(color);
|
||||
// g2d.setStroke(new BasicStroke(thickness - 2));
|
||||
// g2d.draw(path);
|
||||
drawCurve(curve, g2d, componentState);
|
||||
g2d.setComposite(oldComposite);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getControlPointCount() {
|
||||
return controlPoints.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isControlPointSticky(int index) {
|
||||
return index == 0 || index == 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
|
||||
return VisibilityPolicy.WHEN_SELECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canControlPointOverlap(int index) {
|
||||
// Only shape control points may overlap.
|
||||
return index == 1 || index == 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point getControlPoint(int index) {
|
||||
return controlPoints[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlPoint(Point point, int index) {
|
||||
controlPoints[index].setLocation(point);
|
||||
}
|
||||
|
||||
@EditableProperty
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
package org.diylc.components;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
import org.diylc.common.Display;
|
||||
import org.diylc.common.ObjectCache;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IDrawingObserver;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.VisibilityPolicy;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
|
||||
/**
|
||||
* Base class for all leaded components such as resistors or capacitors. Has two
|
||||
* control points and draws leads between them. Also, it positions and draws the
|
||||
* shape of the component as specified by a child class.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static Color LEAD_COLOR = Color.decode("#236B8E");
|
||||
public static Size LEAD_THICKNESS = new Size(0.6d, SizeUnit.mm);
|
||||
public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
|
||||
|
||||
protected Size length;
|
||||
protected Size width;
|
||||
protected Point[] points = new Point[] {
|
||||
new Point((int) (-DEFAULT_SIZE.convertToPixels() / 2), 0),
|
||||
new Point(DEFAULT_SIZE.convertToPixels() / 2, 0) };
|
||||
protected Color bodyColor = Color.white;
|
||||
protected Color borderColor = Color.black;
|
||||
protected Color labelColor = LABEL_COLOR;
|
||||
protected Display display = Display.NAME;
|
||||
|
||||
protected AbstractLeadedComponent() {
|
||||
super();
|
||||
try {
|
||||
this.length = getDefaultLength().clone();
|
||||
this.width = getDefaultWidth().clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// This should never happen because Size supports cloning.
|
||||
} catch (NullPointerException e) {
|
||||
// This will happen if components do not have any shape.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D g2d, ComponentState componentState, Project project,
|
||||
IDrawingObserver drawingObserver) {
|
||||
double distance = points[0].distance(points[1]);
|
||||
Shape shape = getBodyShape();
|
||||
if (shape == null) {
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(
|
||||
getLeadThickness().convertToPixels()));
|
||||
g2d.setColor(shouldShadeLeads() ? getLeadColor(componentState).darker()
|
||||
: getLeadColor(componentState));
|
||||
g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y);
|
||||
if (shouldShadeLeads()) {
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(
|
||||
getLeadThickness().convertToPixels() - 2));
|
||||
g2d.setColor(getLeadColor(componentState));
|
||||
g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Rectangle shapeRect = shape.getBounds();
|
||||
double leadLenght = (distance - shapeRect.width) / 2;
|
||||
Double theta = Math.atan2(points[1].y - points[0].y, points[1].x - points[0].x);
|
||||
// Transform graphics to draw the body in the right place and at the
|
||||
// right angle.
|
||||
g2d.translate((points[0].x + points[1].x - shapeRect.width) / 2,
|
||||
(points[0].y + points[1].y - shapeRect.height) / 2);
|
||||
g2d.rotate(theta, shapeRect.width / 2, shapeRect.height / 2);
|
||||
// Draw body.
|
||||
Composite oldComposite = g2d.getComposite();
|
||||
if (alpha < MAX_ALPHA) {
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha
|
||||
/ MAX_ALPHA));
|
||||
}
|
||||
g2d.setColor(bodyColor);
|
||||
g2d.fill(shape);
|
||||
decorateComponentBody(g2d);
|
||||
g2d.setComposite(oldComposite);
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||
g2d.setColor(componentState == ComponentState.SELECTED
|
||||
|| componentState == ComponentState.DRAGGING ? SELECTION_COLOR : borderColor);
|
||||
g2d.draw(shape);
|
||||
// Draw leads.
|
||||
int leadThickness = getClosestOdd(getLeadThickness().convertToPixels());
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
|
||||
g2d.setColor(shouldShadeLeads() ? getLeadColor(componentState).darker()
|
||||
: getLeadColor(componentState));
|
||||
g2d.drawLine((int) (shapeRect.width - distance) / 2, (int) shapeRect.height / 2,
|
||||
(int) ((shapeRect.width - distance) / 2 + leadLenght) - leadThickness / 2,
|
||||
(int) shapeRect.height / 2);
|
||||
g2d.drawLine((int) (shapeRect.width + distance) / 2, (int) shapeRect.height / 2,
|
||||
(int) ((shapeRect.width + distance) / 2 - leadLenght) + leadThickness / 2,
|
||||
(int) shapeRect.height / 2);
|
||||
if (shouldShadeLeads()) {
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
|
||||
g2d.setColor(getLeadColor(componentState));
|
||||
g2d.drawLine((int) (shapeRect.width - distance) / 2, (int) shapeRect.height / 2,
|
||||
(int) ((shapeRect.width - distance) / 2 + leadLenght) - leadThickness / 2,
|
||||
(int) shapeRect.height / 2);
|
||||
g2d.drawLine((int) (shapeRect.width + distance) / 2, (int) shapeRect.height / 2,
|
||||
(int) ((shapeRect.width + distance) / 2 - leadLenght) + leadThickness / 2,
|
||||
(int) shapeRect.height / 2);
|
||||
}
|
||||
// Do not track the label because that area was already covered.
|
||||
drawingObserver.stopTracking();
|
||||
// Draw label.
|
||||
g2d.setFont(LABEL_FONT);
|
||||
g2d.setColor(componentState == ComponentState.SELECTED ? LABEL_COLOR_SELECTED : labelColor);
|
||||
FontMetrics fontMetrics = g2d.getFontMetrics();
|
||||
String label = display == Display.NAME ? getName() : getValue().toString();
|
||||
// Adjust label angle if needed to make sure that it's readable.
|
||||
if ((theta >= Math.PI / 2 && theta <= Math.PI)
|
||||
|| (theta < -Math.PI / 2 && theta > -Math.PI)) {
|
||||
g2d.rotate(Math.PI, shapeRect.width / 2, shapeRect.height / 2);
|
||||
}
|
||||
Rectangle2D textRect = fontMetrics.getStringBounds(label, g2d);
|
||||
g2d.drawString(label, (int) (shapeRect.width - textRect.getWidth()) / 2,
|
||||
(int) (shapeRect.height - textRect.getHeight()) / 2 + fontMetrics.getAscent());
|
||||
}
|
||||
|
||||
protected void decorateComponentBody(Graphics2D g2d) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
protected boolean shouldShadeLeads() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return default component length.
|
||||
*/
|
||||
protected abstract Size getDefaultLength();
|
||||
|
||||
/**
|
||||
* Returns default component width.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract Size getDefaultWidth();
|
||||
|
||||
/**
|
||||
* @return shape that represents component body. Shape should not be
|
||||
* transformed and should be referenced to (0, 0).
|
||||
*/
|
||||
protected abstract Shape getBodyShape();
|
||||
|
||||
/**
|
||||
* @return default lead thickness. Override this method to change it.
|
||||
*/
|
||||
protected Size getLeadThickness() {
|
||||
return LEAD_THICKNESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return default lead color. Override this method to change it.
|
||||
*/
|
||||
protected Color getLeadColor(ComponentState componentState) {
|
||||
return componentState == ComponentState.SELECTED
|
||||
|| componentState == ComponentState.DRAGGING ? SELECTION_COLOR : LEAD_COLOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getControlPointCount() {
|
||||
return points.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point getControlPoint(int index) {
|
||||
return (Point) points[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isControlPointSticky(int index) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
|
||||
return VisibilityPolicy.ALWAYS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlPoint(Point point, int index) {
|
||||
points[index].setLocation(point);
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Color")
|
||||
public Color getBodyColor() {
|
||||
return bodyColor;
|
||||
}
|
||||
|
||||
public void setBodyColor(Color bodyColor) {
|
||||
this.bodyColor = bodyColor;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Border")
|
||||
public Color getBorderColor() {
|
||||
return borderColor;
|
||||
}
|
||||
|
||||
public void setBorderColor(Color borderColor) {
|
||||
this.borderColor = borderColor;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Length", defaultable = true)
|
||||
public Size getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setLength(Size length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Width", defaultable = true)
|
||||
public Size getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(Size width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
@EditableProperty
|
||||
public Display getDisplay() {
|
||||
return display;
|
||||
}
|
||||
|
||||
public void setDisplay(Display display) {
|
||||
this.display = display;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package org.diylc.components;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
public abstract class AbstractSinglePointComponent extends AbstractComponent<Void> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected Point point = new Point(0, 0);
|
||||
|
||||
@Override
|
||||
public int getControlPointCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point getControlPoint(int index) {
|
||||
return point;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlPoint(Point point, int index) {
|
||||
this.point.setLocation(point);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public Void getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setValue(Void value) {
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package org.diylc.components;
|
||||
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
|
||||
public abstract class AbstractTransparentComponent<T> extends AbstractComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static byte MAX_ALPHA = 127;
|
||||
|
||||
protected byte alpha = MAX_ALPHA;
|
||||
|
||||
@EditableProperty
|
||||
public Byte getAlpha() {
|
||||
return alpha;
|
||||
}
|
||||
|
||||
public void setAlpha(Byte alpha) {
|
||||
this.alpha = alpha;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
/**
|
||||
* Validator that allows all values.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class AllowAllValidator implements IPropertyValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object value) throws ValidationException {
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
/**
|
||||
* Enumerates all possible states that a component can be in.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum ComponentState {
|
||||
|
||||
NORMAL, SELECTED, LOCKED, DRAGGING
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
public enum CreationMethod {
|
||||
|
||||
SINGLE_CLICK, POINT_BY_POINT;
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.diylc.core.annotations.ComponentDescriptor;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
|
||||
/**
|
||||
* Interface for component instance. Implementation classes of this interface
|
||||
* will be instantiated by the application when component is added to the
|
||||
* canvas. <br>
|
||||
* <br>
|
||||
* <b>Implementing classes should meet the following: </b>
|
||||
* <ul>
|
||||
* <li>Must have an empty constructor.</li>
|
||||
* <li>Class should be annotated with {@link ComponentDescriptor}.</li>
|
||||
* <li>Getters for properties editable by users should be annotated with
|
||||
* {@link EditableProperty}.</li>
|
||||
* <li>Component configuration should be stored int <code>public static</code>
|
||||
* fields so they can be set through config file.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @param <T>
|
||||
* type of component values, e.g. Resistance for resistors or String
|
||||
* for transistors.
|
||||
*/
|
||||
public interface IDIYComponent<T> extends Serializable {
|
||||
|
||||
public static final int CHASSIS = 1;
|
||||
public static final int BOARD = 2;
|
||||
public static final int TRACE = 3;
|
||||
public static final int COMPONENT = 4;
|
||||
public static final int TEXT = 5;
|
||||
|
||||
/**
|
||||
* @return component instance name.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Updates component instance name.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
void setName(String name);
|
||||
|
||||
/**
|
||||
* @return component value.
|
||||
*/
|
||||
T getValue();
|
||||
|
||||
/**
|
||||
* Updates component value.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
void setValue(T value);
|
||||
|
||||
/**
|
||||
* @return number of control points for this component instance. May vary
|
||||
* between two instances of the same type, e.g. DIL IC with 8 and 16
|
||||
* pins will have 8 or 16 pins although they are of the same type.
|
||||
*/
|
||||
int getControlPointCount();
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return control point at the specified index.
|
||||
*/
|
||||
Point getControlPoint(int index);
|
||||
|
||||
/**
|
||||
* Updates the control point at the specified index.
|
||||
*
|
||||
* @param point
|
||||
* @param index
|
||||
*/
|
||||
void setControlPoint(Point point, int index);
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return true, if the specified control point may stick to control points
|
||||
* of other components.
|
||||
*/
|
||||
boolean isControlPointSticky(int index);
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return true, if the specified control point may overlap with other
|
||||
* control points <b>of the same component</b>. The other control
|
||||
* point must be able to overlap too.
|
||||
*/
|
||||
boolean canControlPointOverlap(int index);
|
||||
|
||||
VisibilityPolicy getControlPointVisibilityPolicy(int index);
|
||||
|
||||
/**
|
||||
* Draws the component onto the {@link Graphics2D}.
|
||||
*
|
||||
* @param g2d
|
||||
* @param componentState
|
||||
* @param project
|
||||
* @param drawingObserver
|
||||
*/
|
||||
void draw(Graphics2D g2d, ComponentState componentState, Project project,
|
||||
IDrawingObserver drawingObserver);
|
||||
|
||||
/**
|
||||
* Draws icon representation of the component. This should not depend on
|
||||
* component state, i.e. it should be treated as a static method.
|
||||
*
|
||||
* @param g2d
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
void drawIcon(Graphics2D g2d, int width, int height);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
/**
|
||||
* Interface for tracking component drawing process. Components may use it to
|
||||
* stop or restart tracking. Anything drawn while tracking is stopped will not
|
||||
* be added to the mouse hot-spot area.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IDrawingObserver {
|
||||
|
||||
void stopTracking();
|
||||
|
||||
void startTracking();
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
/**
|
||||
* Interface for validating property value changes.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IPropertyValidator {
|
||||
|
||||
/**
|
||||
* @param value
|
||||
* @throws ValidationException
|
||||
* if validation fails. Message will contain the reason.
|
||||
*/
|
||||
void validate(Object value) throws ValidationException;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
|
||||
/**
|
||||
* Base interface for the main GUI component.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IView {
|
||||
|
||||
public static final int ERROR_MESSAGE = 0;
|
||||
public static final int INFORMATION_MESSAGE = 1;
|
||||
public static final int WARNING_MESSAGE = 2;
|
||||
public static final int QUESTION_MESSAGE = 3;
|
||||
public static final int PLAIN_MESSAGE = -1;
|
||||
public static final int DEFAULT_OPTION = -1;
|
||||
public static final int YES_NO_OPTION = 0;
|
||||
public static final int YES_NO_CANCEL_OPTION = 1;
|
||||
public static final int OK_CANCEL_OPTION = 2;
|
||||
public static final int YES_OPTION = 0;
|
||||
public static final int NO_OPTION = 1;
|
||||
public static final int CANCEL_OPTION = 2;
|
||||
public static final int OK_OPTION = 0;
|
||||
|
||||
void showMessage(String message, String title, int messageType);
|
||||
|
||||
int showConfirmDialog(String message, String title, int optionType, int messageType);
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.core.annotations.PositiveMeasureValidator;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
|
||||
/**
|
||||
* Entity class that defines a project. Contains project properties and a
|
||||
* collection of components.This class is serialized to file. Some filed getters
|
||||
* are tagged with {@link EditableProperty} to enable for user to edit them.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class Project implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static String DEFAULT_TITLE = "New Project";
|
||||
public static Size DEFAULT_WIDTH = new Size(29d, SizeUnit.cm);
|
||||
public static Size DEFAULT_HEIGHT = new Size(21d, SizeUnit.cm);
|
||||
public static Size DEFAULT_GRID_SPACING = new Size(0.1d, SizeUnit.in);
|
||||
|
||||
private String title;
|
||||
private String author;
|
||||
private String description;
|
||||
private Size width;
|
||||
private Size height;
|
||||
private Size gridSpacing;
|
||||
private List<IDIYComponent<?>> components;
|
||||
private Set<Set<IDIYComponent<?>>> groups;
|
||||
private Set<Integer> lockedLayers;
|
||||
|
||||
public Project() {
|
||||
components = new ArrayList<IDIYComponent<?>>();
|
||||
groups = new HashSet<Set<IDIYComponent<?>>>();
|
||||
lockedLayers = new HashSet<Integer>();
|
||||
title = DEFAULT_TITLE;
|
||||
author = System.getProperty("user.name");
|
||||
width = DEFAULT_WIDTH;
|
||||
height = DEFAULT_HEIGHT;
|
||||
gridSpacing = DEFAULT_GRID_SPACING;
|
||||
}
|
||||
|
||||
@EditableProperty(defaultable = false)
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@EditableProperty
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
@EditableProperty(defaultable = false)
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@EditableProperty
|
||||
public Size getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(Size width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
@EditableProperty
|
||||
public Size getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(Size height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Grid spacing", validatorClass = SpacingValidator.class)
|
||||
public Size getGridSpacing() {
|
||||
return gridSpacing;
|
||||
}
|
||||
|
||||
public void setGridSpacing(Size gridSpacing) {
|
||||
this.gridSpacing = gridSpacing;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of components sorted by z-order ascending.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<IDIYComponent<?>> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of grouped components.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<Set<IDIYComponent<?>>> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
public Set<Integer> getLockedLayers() {
|
||||
return lockedLayers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((author == null) ? 0 : author.hashCode());
|
||||
result = prime * result + ((components == null) ? 0 : components.hashCode());
|
||||
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||
result = prime * result + ((height == null) ? 0 : height.hashCode());
|
||||
result = prime * result + ((title == null) ? 0 : title.hashCode());
|
||||
result = prime * result + ((width == null) ? 0 : width.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Project other = (Project) obj;
|
||||
if (author == null) {
|
||||
if (other.author != null)
|
||||
return false;
|
||||
} else if (!author.equals(other.author))
|
||||
return false;
|
||||
if (components == null) {
|
||||
if (other.components != null)
|
||||
return false;
|
||||
} else if (!components.equals(other.components))
|
||||
return false;
|
||||
if (description == null) {
|
||||
if (other.description != null)
|
||||
return false;
|
||||
} else if (!description.equals(other.description))
|
||||
return false;
|
||||
if (height == null) {
|
||||
if (other.height != null)
|
||||
return false;
|
||||
} else if (!height.equals(other.height))
|
||||
return false;
|
||||
if (title == null) {
|
||||
if (other.title != null)
|
||||
return false;
|
||||
} else if (!title.equals(other.title))
|
||||
return false;
|
||||
if (width == null) {
|
||||
if (other.width != null)
|
||||
return false;
|
||||
} else if (!width.equals(other.width))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public static class SpacingValidator extends PositiveMeasureValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object value) throws ValidationException {
|
||||
super.validate(value);
|
||||
Size size = (Size) value;
|
||||
if (size.compareTo(new Size(1d, SizeUnit.mm)) < 0) {
|
||||
throw new ValidationException("must be greater than 1mm");
|
||||
}
|
||||
if (size.compareTo(new Size(1d, SizeUnit.in)) > 0) {
|
||||
throw new ValidationException("must be less than 1in");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Project clone() throws CloneNotSupportedException {
|
||||
// List<IDIYComponent> clonedComponents = new
|
||||
// ArrayList<IDIYComponent>();
|
||||
// for (IDIYComponent component : components) {
|
||||
// clonedComponents.add(component.clone());
|
||||
// }
|
||||
// Project project = new Project(title, author, description,
|
||||
// width.clone(), height.clone(), clonedComponents);
|
||||
// return project;
|
||||
// }
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
package org.diylc.core;
|
||||
|
||||
public class ValidationException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ValidationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
/**
|
||||
* Enumerates control point visibility policies.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum VisibilityPolicy {
|
||||
|
||||
/**
|
||||
* Control point should be rendered all the time.
|
||||
*/
|
||||
ALWAYS,
|
||||
/**
|
||||
* Control point should be rendered only when the component is selected.
|
||||
*/
|
||||
WHEN_SELECTED,
|
||||
/**
|
||||
* Control point should not be rendered regardless of component selection.
|
||||
*/
|
||||
NEVER;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package org.diylc.core.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.diylc.core.CreationMethod;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/**
|
||||
* Annotation for {@link IDIYComponent} implementation. Describes component
|
||||
* properties.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ComponentDescriptor {
|
||||
|
||||
/**
|
||||
* @return component type name.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* @return component type description.
|
||||
*/
|
||||
String description();
|
||||
|
||||
/**
|
||||
* @return method that should be used to create a component. If
|
||||
* <code>CreationMethod.POINT_BY_POINT</code> is used, user will
|
||||
* have to select ending points before the component is created.
|
||||
*/
|
||||
CreationMethod creationMethod() default CreationMethod.SINGLE_CLICK;
|
||||
|
||||
/**
|
||||
* @return component category, e.g. "Passive", "Semiconductors", etc.
|
||||
*/
|
||||
String category();
|
||||
|
||||
/**
|
||||
* @return component author name.
|
||||
*/
|
||||
String author();
|
||||
|
||||
/**
|
||||
* @return prefix that will be used to generate component instance names,
|
||||
* e.g. "R" for resistors or "Q" for transistors.
|
||||
*/
|
||||
String instanceNamePrefix();
|
||||
|
||||
/**
|
||||
* @return Z-order of the component.
|
||||
*/
|
||||
double zOrder();
|
||||
|
||||
/**
|
||||
* @return when false, moving one control point will cause all the others to
|
||||
* move together with it.
|
||||
*/
|
||||
boolean stretchable() default true;
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.diylc.core.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.diylc.core.AllowAllValidator;
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
|
||||
/**
|
||||
* Used to annotate editable component property. Editable property XYZ must have
|
||||
* both getter and setter named <code>getXYZ</code> and <code>setXYZ</code>
|
||||
* respectively and this annotation must be placed on the getter method.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface EditableProperty {
|
||||
|
||||
/**
|
||||
* Returns property name. If left blank property name will be extracted from
|
||||
* the getter name, e.g. getter <code>getXYZ</code> will induce property
|
||||
* name <code>XYZ</code>. <br>
|
||||
* Default value is blank.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* If true, application may set default value for this property. <br>
|
||||
* Default value is true.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean defaultable() default true;
|
||||
|
||||
/**
|
||||
* Class of validator to use to
|
||||
* @return
|
||||
*/
|
||||
Class<? extends IPropertyValidator> validatorClass() default AllowAllValidator.class;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.diylc.core.annotations;
|
||||
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
import org.diylc.core.ValidationException;
|
||||
import org.diylc.core.measures.AbstractMeasure;
|
||||
|
||||
public class PositiveMeasureValidator implements IPropertyValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object value) throws ValidationException {
|
||||
if (value instanceof AbstractMeasure) {
|
||||
AbstractMeasure measure = (AbstractMeasure) value;
|
||||
if (measure.getValue() <= 0) {
|
||||
throw new ValidationException("must be greater than zero.");
|
||||
}
|
||||
} else {
|
||||
throw new ValidationException("wrong data type, measure expected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.Format;
|
||||
|
||||
public class AbstractMeasure<T extends Enum<? extends Unit>> implements Serializable, Cloneable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected static final Format format = new DecimalFormat("0.####");
|
||||
|
||||
protected Double value;
|
||||
protected T unit;
|
||||
|
||||
public AbstractMeasure() {
|
||||
}
|
||||
|
||||
public AbstractMeasure(Double value, T unit) {
|
||||
super();
|
||||
this.value = value;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public T getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public void setUnit(T multiplier) {
|
||||
this.unit = multiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((unit == null) ? 0 : unit.hashCode());
|
||||
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
AbstractMeasure<?> other = (AbstractMeasure<?>) obj;
|
||||
if (unit == null) {
|
||||
if (other.unit != null)
|
||||
return false;
|
||||
} else if (!unit.equals(other.unit))
|
||||
return false;
|
||||
if (value == null) {
|
||||
if (other.value != null)
|
||||
return false;
|
||||
} else if (!value.equals(other.value))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return format.format(value) + " " + unit;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
public class Capacitance extends AbstractMeasure<CapacitanceUnit> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public Capacitance() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public Capacitance(Double value, CapacitanceUnit unit) {
|
||||
super(value, unit);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public Capacitance clone() throws CloneNotSupportedException {
|
||||
return new Capacitance(value, unit);
|
||||
}
|
||||
|
||||
public static Capacitance parseCapacitance(String value) {
|
||||
for (CapacitanceUnit unit : CapacitanceUnit.values()) {
|
||||
if (value.toLowerCase().endsWith(unit.toString().toLowerCase())) {
|
||||
value = value.substring(0, value.length() - unit.toString().length() - 1).trim();
|
||||
return new Capacitance(Double.parseDouble(value), unit);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Could not parse capacitance: " + value);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
public enum CapacitanceUnit implements Unit {
|
||||
|
||||
pF(1, "pF"), nF(1e3, "nF"), uF(1e6, "\u03bcF"), mF(1e9, "mF"), F(1e12, "F");
|
||||
|
||||
double factor;
|
||||
String display;
|
||||
|
||||
private CapacitanceUnit(double factor, String display) {
|
||||
this.factor = factor;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFactor() {
|
||||
return factor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return display;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
public class Inductance extends AbstractMeasure<InductanceUnit> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public Inductance() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public Inductance(Double value, InductanceUnit unit) {
|
||||
super(value, unit);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inductance clone() throws CloneNotSupportedException {
|
||||
return new Inductance(value, unit);
|
||||
}
|
||||
|
||||
public static Inductance parseCapacitance(String value) {
|
||||
for (InductanceUnit unit : InductanceUnit.values()) {
|
||||
if (value.toLowerCase().endsWith(unit.toString().toLowerCase())) {
|
||||
value = value.substring(0, value.length() - unit.toString().length() - 1).trim();
|
||||
return new Inductance(Double.parseDouble(value), unit);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Could not parse inductance: " + value);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
public enum InductanceUnit implements Unit {
|
||||
|
||||
pH(1, "pH"), nH(1e3, "nH"), uH(1e6, "\u03bcH"), mH(1e9, "mH"), H(1e12, "H");
|
||||
|
||||
double factor;
|
||||
String display;
|
||||
|
||||
private InductanceUnit(double factor, String display) {
|
||||
this.factor = factor;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFactor() {
|
||||
return factor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return display;
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import org.diylc.common.ResistorColorCode;
|
||||
|
||||
public class Resistance extends AbstractMeasure<ResistanceUnit> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Color[] COLOR_DIGITS = new Color[] { Color.black, Color.decode("#8B4513"),
|
||||
Color.red, Color.orange, Color.yellow, Color.decode("#76EE00"), Color.blue,
|
||||
Color.decode("#91219E"), Color.lightGray, Color.white };
|
||||
private static final Color[] COLOR_MULTIPLIER = new Color[] { Color.lightGray.brighter(),
|
||||
Color.decode("#FFB90F"), Color.black, Color.decode("#8B4513"), Color.red, Color.orange,
|
||||
Color.yellow, Color.decode("#76EE00"), Color.blue };
|
||||
|
||||
public Resistance() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public Resistance(Double value, ResistanceUnit multiplier) {
|
||||
super(value, multiplier);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resistance clone() throws CloneNotSupportedException {
|
||||
return new Resistance(value, unit);
|
||||
}
|
||||
|
||||
public Color[] getColorCode(ResistorColorCode resistorColorCode) {
|
||||
Color[] bands;
|
||||
double base = getValue() * getUnit().getFactor();
|
||||
int multiplier = 0;
|
||||
while (base > (resistorColorCode == ResistorColorCode._4_BAND ? 99 : 999)) {
|
||||
multiplier += 1;
|
||||
base /= 10;
|
||||
}
|
||||
while (base < (resistorColorCode == ResistorColorCode._4_BAND ? 10 : 100)) {
|
||||
multiplier -= 1;
|
||||
base *= 10;
|
||||
}
|
||||
if (multiplier > 6 || multiplier < -2) {
|
||||
// Out of range.
|
||||
return new Color[] {};
|
||||
}
|
||||
switch (resistorColorCode) {
|
||||
case _4_BAND:
|
||||
bands = new Color[3];
|
||||
bands[0] = COLOR_DIGITS[(int) Math.round(base / 10)];
|
||||
bands[1] = COLOR_DIGITS[(int) Math.round(base % 10)];
|
||||
bands[2] = COLOR_MULTIPLIER[multiplier + 2];
|
||||
break;
|
||||
case _5_BAND:
|
||||
bands = new Color[4];
|
||||
bands[0] = COLOR_DIGITS[(int) Math.round(base / 100)];
|
||||
bands[1] = COLOR_DIGITS[(int) Math.round(base / 10 % 10)];
|
||||
bands[2] = COLOR_DIGITS[(int) Math.round(base % 10)];
|
||||
bands[3] = COLOR_MULTIPLIER[multiplier + 2];
|
||||
break;
|
||||
default:
|
||||
bands = new Color[] {};
|
||||
}
|
||||
return bands;
|
||||
}
|
||||
|
||||
public static Resistance parseResistance(String value) {
|
||||
for (ResistanceUnit unit : ResistanceUnit.values()) {
|
||||
if (value.toLowerCase().endsWith(unit.toString().toLowerCase())) {
|
||||
value = value.substring(0, value.length() - unit.toString().length() - 1).trim();
|
||||
return new Resistance(Double.parseDouble(value), unit);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Could not parse resistance: " + value);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
public enum ResistanceUnit implements Unit {
|
||||
|
||||
R(1, "\u03a9"), K(1e3, "K"), M(1e6, "M");
|
||||
|
||||
double factor;
|
||||
String display;
|
||||
|
||||
private ResistanceUnit(double factor, String display) {
|
||||
this.factor = factor;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFactor() {
|
||||
return factor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return display;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
public class Size extends AbstractMeasure<SizeUnit> implements Comparable<Size> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public Size() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public Size(Double value, SizeUnit unit) {
|
||||
super(value, unit);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public int convertToPixels() {
|
||||
// double factor = getUnit().getFactor() / SizeUnit.in.getFactor();
|
||||
// int grids = (int) (factor * getValue() * Constants.GRIDS_PER_INCH);
|
||||
// double remainder = (factor * getValue() * Constants.GRIDS_PER_INCH) - grids;
|
||||
// return (int) Math.round(Constants.PIXELS_PER_INCH / Constants.GRIDS_PER_INCH
|
||||
// * (grids + remainder));
|
||||
return (int) (getValue() * getUnit().getFactor() / SizeUnit.in.getFactor() * Constants.PIXELS_PER_INCH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size clone() throws CloneNotSupportedException {
|
||||
return new Size(value, unit);
|
||||
}
|
||||
|
||||
public static Size parseSize(String value) {
|
||||
for (SizeUnit unit : SizeUnit.values()) {
|
||||
if (value.toLowerCase().endsWith(unit.toString().toLowerCase())) {
|
||||
value = value.substring(0, value.length() - unit.toString().length() - 1).trim();
|
||||
return new Size(Double.parseDouble(value), unit);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Could not parse size: " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Size o) {
|
||||
return new Double(value * unit.getFactor()).compareTo(o.getValue() * o.getUnit().getFactor());
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
public enum SizeUnit implements Unit {
|
||||
|
||||
mm(1d), cm(10d), m(1e4d), in(25.4d), ft(25.4d * 12), yd(9144d);
|
||||
|
||||
double factor;
|
||||
|
||||
private SizeUnit(double factor) {
|
||||
this.factor = factor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFactor() {
|
||||
return factor;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.diylc.core.measures;
|
||||
|
||||
public interface Unit {
|
||||
|
||||
double getFactor();
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package org.diylc.images;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
/**
|
||||
* Loads image resources as Icons.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum IconLoader {
|
||||
|
||||
Delete("delete.png"), Add("add.png"), FolderOut("folder_out.png"), Garbage("garbage.png"), DiskBlue(
|
||||
"disk_blue.png"), SaveAs("save_as.png"), Exit("exit.png"), DocumentPlainYellow(
|
||||
"document_plain_yellow.png"), PhotoScenery("photo_scenery.png"), LightBulbOn(
|
||||
"lightbulb_on.png"), LightBulbOff("lightbulb_off.png"), NotebookAdd("notebook_add.png"), FormGreen(
|
||||
"form_green.png"), Gears("gears.png"), About("about.png"), WindowColors(
|
||||
"window_colors.png"), WindowGear("window_gear.png"), NavigateCheck("navigate_check.png"), Undo(
|
||||
"undo.png"), Error("error.png"), Warning("warning.png"), ZoomSmall("zoom_small.png"), MoveSmall(
|
||||
"move_small.png"), Print("print.png"), PDF("pdf.png"), Excel("excel.png"), CSV(
|
||||
"csv.png"), HTML("html.png"), Image("image.png"), Cut("cut.png"), Copy("copy.png"), Paste(
|
||||
"paste.png"), Selection("selection.png"), BOM("bom.png"), BlackBoard("blackboard.png"), IdCard(
|
||||
"id_card.png"), IdCardAdd("id_card_add.png"), Chest("chest.png"), Upload("upload.png"), Wrench(
|
||||
"wrench.png"), Group("group.png"), Ungroup("ungroup.png"), TraceMask("trace_mask.png"), Faq(
|
||||
"faq.png"), Component("component.png"), Plugin("plugin.png"), Manual("manual.png"), Donate(
|
||||
"donate.png"), Bug("bug.png"), IconLarge("icon_large.png"), IconMedium(
|
||||
"icon_medium.png"), IconSmall("icon_small.png"), DocumentEdit("document_edit.png"), EditComponent(
|
||||
"edit_component.png"), Size("size.png"), Front("front.png"), Back("back.png");
|
||||
|
||||
protected String name;
|
||||
|
||||
private IconLoader(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
java.net.URL imgURL = getClass().getResource(name);
|
||||
if (imgURL != null) {
|
||||
return new ImageIcon(imgURL, name);
|
||||
} else {
|
||||
System.err.println("Couldn't find file: " + name);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Image getImage() {
|
||||
BufferedImage img = null;
|
||||
try {
|
||||
img = ImageIO.read(getClass().getResourceAsStream(name));
|
||||
} catch (IOException e) {
|
||||
System.err.println("Couldn't find file: " + name);
|
||||
}
|
||||
return img;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
import org.diylc.core.measures.Size;
|
||||
|
||||
public class CalcUtils {
|
||||
|
||||
/**
|
||||
* Rounds the number to the closest grid line.
|
||||
*
|
||||
* @param x
|
||||
* @return
|
||||
*/
|
||||
public static int roundToGrid(int x, Size gridSpacing) {
|
||||
int grid = gridSpacing.convertToPixels();
|
||||
return (Math.round(1f * x / grid) * grid);
|
||||
}
|
||||
|
||||
public static void snapPointToGrid(Point point, Size gridSpacing) {
|
||||
int x = roundToGrid(point.x, gridSpacing);
|
||||
int y = roundToGrid(point.y, gridSpacing);
|
||||
point.setLocation(x, y);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.diylc.common.ComponentType;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public class ComparatorFactory {
|
||||
|
||||
private static ComparatorFactory instance;
|
||||
|
||||
private Comparator<IDIYComponent<?>> componentNameComparator;
|
||||
private Comparator<ComponentType> componentTypeComparator;
|
||||
private Comparator<PropertyWrapper> propertyNameComparator;
|
||||
private Comparator<IDIYComponent<?>> componentZOrderComparator;
|
||||
|
||||
public static ComparatorFactory getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ComparatorFactory();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public Comparator<IDIYComponent<?>> getComponentNameComparator() {
|
||||
if (componentNameComparator == null) {
|
||||
componentNameComparator = new Comparator<IDIYComponent<?>>() {
|
||||
|
||||
@Override
|
||||
public int compare(IDIYComponent<?> o1, IDIYComponent<?> o2) {
|
||||
String name1 = o1.getName();
|
||||
String name2 = o2.getName();
|
||||
if (name1 == null || name2 == null) {
|
||||
return 0;
|
||||
}
|
||||
return name1.compareToIgnoreCase(name2);
|
||||
}
|
||||
};
|
||||
}
|
||||
return componentNameComparator;
|
||||
}
|
||||
|
||||
public Comparator<ComponentType> getComponentTypeComparator() {
|
||||
if (componentTypeComparator == null) {
|
||||
componentTypeComparator = new Comparator<ComponentType>() {
|
||||
|
||||
@Override
|
||||
public int compare(ComponentType o1, ComponentType o2) {
|
||||
return o1.getName().compareToIgnoreCase(o2.getName());
|
||||
}
|
||||
};
|
||||
}
|
||||
return componentTypeComparator;
|
||||
}
|
||||
|
||||
public Comparator<PropertyWrapper> getPropertyNameComparator() {
|
||||
if (propertyNameComparator == null) {
|
||||
propertyNameComparator = new Comparator<PropertyWrapper>() {
|
||||
|
||||
@Override
|
||||
public int compare(PropertyWrapper o1, PropertyWrapper o2) {
|
||||
return o1.getName().compareToIgnoreCase(o2.getName());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
return propertyNameComparator;
|
||||
}
|
||||
|
||||
public Comparator<IDIYComponent<?>> getComponentZOrderComparator() {
|
||||
if (componentZOrderComparator == null) {
|
||||
componentZOrderComparator = new Comparator<IDIYComponent<?>>() {
|
||||
|
||||
@Override
|
||||
public int compare(IDIYComponent<?> o1, IDIYComponent<?> o2) {
|
||||
ComponentType type1 = ComponentProcessor.getInstance()
|
||||
.extractComponentTypeFrom(
|
||||
(Class<? extends IDIYComponent<?>>) o1.getClass());
|
||||
ComponentType type2 = ComponentProcessor.getInstance()
|
||||
.extractComponentTypeFrom(
|
||||
(Class<? extends IDIYComponent<?>>) o2.getClass());
|
||||
return new Double(type1.getZOrder()).compareTo(type2.getZOrder());
|
||||
}
|
||||
};
|
||||
}
|
||||
return componentZOrderComparator;
|
||||
}
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.ComponentType;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.core.CreationMethod;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
import org.diylc.core.annotations.ComponentDescriptor;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
|
||||
import com.rits.cloning.Cloner;
|
||||
|
||||
/**
|
||||
* Utility class with component processing methods.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ComponentProcessor {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(ComponentProcessor.class);
|
||||
|
||||
private static ComponentProcessor instance;
|
||||
|
||||
private Map<String, List<PropertyWrapper>> propertyCache;
|
||||
private Map<String, IPropertyValidator> propertyValidatorCache;
|
||||
private Map<String, ComponentType> componentTypeMap;
|
||||
|
||||
private Cloner cloner;
|
||||
|
||||
public static ComponentProcessor getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ComponentProcessor();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ComponentProcessor() {
|
||||
super();
|
||||
this.cloner = new Cloner();
|
||||
this.propertyCache = new HashMap<String, List<PropertyWrapper>>();
|
||||
this.componentTypeMap = new HashMap<String, ComponentType>();
|
||||
this.propertyValidatorCache = new HashMap<String, IPropertyValidator>();
|
||||
}
|
||||
|
||||
public ComponentType extractComponentTypeFrom(Class<? extends IDIYComponent<?>> clazz) {
|
||||
if (componentTypeMap.containsKey(clazz.getName())) {
|
||||
return componentTypeMap.get(clazz.getName());
|
||||
}
|
||||
String name;
|
||||
String description;
|
||||
CreationMethod creationMethod;
|
||||
String category;
|
||||
String namePrefix;
|
||||
String author;
|
||||
Icon icon;
|
||||
double zOrder;
|
||||
boolean stretchable;
|
||||
if (clazz.isAnnotationPresent(ComponentDescriptor.class)) {
|
||||
ComponentDescriptor annotation = clazz.getAnnotation(ComponentDescriptor.class);
|
||||
name = annotation.name();
|
||||
description = annotation.description();
|
||||
creationMethod = annotation.creationMethod();
|
||||
category = annotation.category();
|
||||
namePrefix = annotation.instanceNamePrefix();
|
||||
author = annotation.author();
|
||||
zOrder = annotation.zOrder();
|
||||
stretchable = annotation.stretchable();
|
||||
} else {
|
||||
name = clazz.getSimpleName();
|
||||
description = "";
|
||||
creationMethod = CreationMethod.SINGLE_CLICK;
|
||||
category = "Uncategorized";
|
||||
namePrefix = "Unknown";
|
||||
author = "Unknown";
|
||||
zOrder = IDIYComponent.COMPONENT;
|
||||
stretchable = true;
|
||||
}
|
||||
icon = null;
|
||||
// Draw component icon.
|
||||
try {
|
||||
IDIYComponent<?> componentInstance = (IDIYComponent<?>) clazz.newInstance();
|
||||
Image image = new BufferedImage(Presenter.ICON_SIZE, Presenter.ICON_SIZE,
|
||||
java.awt.image.BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2d = (Graphics2D) image.getGraphics();
|
||||
g2d
|
||||
.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
componentInstance.drawIcon(g2d, Presenter.ICON_SIZE, Presenter.ICON_SIZE);
|
||||
icon = new ImageIcon(image);
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
ComponentType componentType = new ComponentType(name, description, creationMethod,
|
||||
category, namePrefix, author, icon, clazz, zOrder, stretchable);
|
||||
componentTypeMap.put(clazz.getName(), componentType);
|
||||
return componentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts all editable properties from the component class.
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
public List<PropertyWrapper> extractProperties(Class<?> clazz) {
|
||||
if (propertyCache.containsKey(clazz.getName())) {
|
||||
return cloner.deepClone(propertyCache.get(clazz.getName()));
|
||||
}
|
||||
List<PropertyWrapper> properties = new ArrayList<PropertyWrapper>();
|
||||
for (Method method : clazz.getMethods()) {
|
||||
if (method.getName().startsWith("get")) {
|
||||
try {
|
||||
if (method.isAnnotationPresent(EditableProperty.class)
|
||||
&& !method.isAnnotationPresent(Deprecated.class)) {
|
||||
EditableProperty annotation = method.getAnnotation(EditableProperty.class);
|
||||
String name;
|
||||
if (annotation.name().equals("")) {
|
||||
name = method.getName().substring(3);
|
||||
} else {
|
||||
name = annotation.name();
|
||||
}
|
||||
IPropertyValidator validator = getPropertyValidator(annotation
|
||||
.validatorClass());
|
||||
Method setter = clazz.getMethod("set" + method.getName().substring(3),
|
||||
method.getReturnType());
|
||||
PropertyWrapper property = new PropertyWrapper(name,
|
||||
method.getReturnType(), method, setter, annotation.defaultable(),
|
||||
validator);
|
||||
properties.add(property);
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
LOG.debug("No matching setter found for \"" + method.getName()
|
||||
+ "\". Skipping...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
propertyCache.put(clazz.getName(), properties);
|
||||
return cloner.deepClone(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns properties mutual for all the selected components.
|
||||
*
|
||||
* @param selectedComponents
|
||||
* @return
|
||||
*/
|
||||
public List<PropertyWrapper> getMutualSelectionProperties(
|
||||
List<IDIYComponent<?>> selectedComponents) throws Exception {
|
||||
if (selectedComponents.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
List<PropertyWrapper> properties = new ArrayList<PropertyWrapper>();
|
||||
IDIYComponent<?> firstComponent = selectedComponents.get(0);
|
||||
properties.addAll(extractProperties(firstComponent.getClass()));
|
||||
// Initialize values
|
||||
for (PropertyWrapper property : properties) {
|
||||
property.readFrom(firstComponent);
|
||||
}
|
||||
for (int i = 1; i < selectedComponents.size(); i++) {
|
||||
IDIYComponent<?> component = selectedComponents.get(i);
|
||||
List<PropertyWrapper> newProperties = extractProperties(component.getClass());
|
||||
for (PropertyWrapper property : newProperties) {
|
||||
property.readFrom(component);
|
||||
}
|
||||
properties.retainAll(newProperties);
|
||||
// for (PropertyWrapper property : properties) {
|
||||
// try {
|
||||
// property.readUniqueFrom(component);
|
||||
// } catch (Exception e) {
|
||||
// // TODO Auto-generated catch block
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
Collections.sort(properties, ComparatorFactory.getInstance().getPropertyNameComparator());
|
||||
return properties;
|
||||
}
|
||||
|
||||
private IPropertyValidator getPropertyValidator(Class<? extends IPropertyValidator> clazz) {
|
||||
if (propertyValidatorCache.containsKey(clazz.getName())) {
|
||||
return propertyValidatorCache.get(clazz.getName());
|
||||
}
|
||||
IPropertyValidator validator;
|
||||
try {
|
||||
validator = clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not instantiate validator for " + clazz.getName(), e);
|
||||
return null;
|
||||
}
|
||||
propertyValidatorCache.put(clazz.getName(), validator);
|
||||
return validator;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import org.diylc.common.ComponentType;
|
||||
import org.diylc.common.IComponentFiler;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public class ComponentZOrderFiler implements IComponentFiler {
|
||||
|
||||
private int zOrder;
|
||||
|
||||
public ComponentZOrderFiler(int zOrder) {
|
||||
super();
|
||||
this.zOrder = zOrder;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean testComponent(IDIYComponent<?> component) {
|
||||
ComponentType componentType = ComponentProcessor.getInstance().extractComponentTypeFrom(
|
||||
(Class<? extends IDIYComponent<?>>) component.getClass());
|
||||
return Math.round(componentType.getZOrder()) == zOrder;
|
||||
}
|
||||
}
|
||||
@@ -1,345 +0,0 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Area;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.DrawOption;
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.GridType;
|
||||
import org.diylc.common.IComponentFiler;
|
||||
import org.diylc.common.ObjectCache;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.VisibilityPolicy;
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
import com.diyfever.gui.miscutils.ConfigurationManager;
|
||||
import com.diyfever.gui.simplemq.MessageDispatcher;
|
||||
|
||||
/**
|
||||
* Utility that deals with painting {@link Project} on the {@link Graphics2D}
|
||||
* and keeps areas taken by each drawn component.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class DrawingManager {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(DrawingManager.class);
|
||||
|
||||
public static int CONTROL_POINT_SIZE = 7;
|
||||
|
||||
public static final String ANTIALIASING_KEY = "anti-aliasing";
|
||||
public static final String ZOOM_KEY = "zoom";
|
||||
public static boolean DEBUG_COMPONENT_AREAS = false;
|
||||
|
||||
public static Color GRID_COLOR = new Color(240, 240, 240);
|
||||
public static Color CONTROL_POINT_COLOR = Color.black;
|
||||
public static Color SELECTED_CONTROL_POINT_COLOR = Color.green;
|
||||
|
||||
// Keeps Area object of each drawn component.
|
||||
private Map<IDIYComponent<?>, Area> componentAreaMap;
|
||||
// Maps components to the last state they are drawn in. Also, used to
|
||||
// determine which components are invalidated when they are not in the map.
|
||||
private Map<IDIYComponent<?>, ComponentState> lastDrawnStateMap;
|
||||
|
||||
private Composite slotComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
|
||||
private Composite lockedComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
|
||||
private List<IDIYComponent<?>> failedComponents = new ArrayList<IDIYComponent<?>>();
|
||||
|
||||
private double zoomLevel = 1d;// ConfigurationManager.getInstance().readDouble(ZOOM_KEY,
|
||||
// 1d);
|
||||
|
||||
private MessageDispatcher<EventType> messageDispatcher;
|
||||
|
||||
public DrawingManager(MessageDispatcher<EventType> messageDispatcher) {
|
||||
super();
|
||||
this.messageDispatcher = messageDispatcher;
|
||||
componentAreaMap = new HashMap<IDIYComponent<?>, Area>();
|
||||
lastDrawnStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints the project onto the canvas and returns the list of components
|
||||
* that failed to draw.
|
||||
*
|
||||
* @param g2d
|
||||
* @param project
|
||||
* @param drawOptions
|
||||
* @param filter
|
||||
* @param selectionRect
|
||||
* @param selectedComponents
|
||||
* @param lockedComponents
|
||||
* @param groupedComponents
|
||||
* @param controlPointSlot
|
||||
* @param componentSlot
|
||||
* @param dragInProgress
|
||||
* @return
|
||||
*/
|
||||
public List<IDIYComponent<?>> drawProject(Graphics2D g2d, Project project,
|
||||
Set<DrawOption> drawOptions, IComponentFiler filter, Rectangle selectionRect,
|
||||
List<IDIYComponent<?>> selectedComponents, Set<IDIYComponent<?>> lockedComponents,
|
||||
Set<IDIYComponent<?>> groupedComponents, List<Point> controlPointSlot,
|
||||
IDIYComponent<?> componentSlot, boolean dragInProgress) {
|
||||
failedComponents.clear();
|
||||
if (project == null) {
|
||||
return failedComponents;
|
||||
}
|
||||
G2DWrapper g2dWrapper = new G2DWrapper(g2d);
|
||||
|
||||
if (drawOptions.contains(DrawOption.ANTIALIASING)
|
||||
&& ConfigurationManager.getInstance().readBoolean(ANTIALIASING_KEY, true)) {
|
||||
g2d
|
||||
.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
}
|
||||
|
||||
double zoom = 1d;
|
||||
if (drawOptions.contains(DrawOption.ZOOM)) {
|
||||
zoom = zoomLevel;
|
||||
} else {
|
||||
zoom = 1 / Constants.PIXEL_SIZE;
|
||||
}
|
||||
|
||||
// AffineTransform initialTx = g2d.getTransform();
|
||||
Dimension d = getCanvasDimensions(project, zoom, true);
|
||||
|
||||
g2dWrapper.setColor(Constants.CANVAS_COLOR);
|
||||
g2dWrapper.fillRect(0, 0, d.width, d.height);
|
||||
g2d.setClip(new Rectangle(new Point(0, 0), d));
|
||||
|
||||
GridType gridType = (GridType) ConfigurationManager.getInstance().readObject(
|
||||
ANTIALIASING_KEY, GridType.LINES);
|
||||
if (drawOptions.contains(DrawOption.GRID) && gridType != GridType.NONE) {
|
||||
double zoomStep = project.getGridSpacing().convertToPixels() * zoom;
|
||||
if (gridType == GridType.CROSSHAIR) {
|
||||
g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
|
||||
10f, new float[] { (float) zoomStep / 2, (float) zoomStep / 2 },
|
||||
(float) zoomStep / 4));
|
||||
} else if (gridType == GridType.DOT) {
|
||||
g2d.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
|
||||
10f, new float[] { 1f, (float) zoomStep - 1 }, 0f));
|
||||
}
|
||||
|
||||
g2dWrapper.setColor(GRID_COLOR);
|
||||
for (double i = zoomStep; i < d.width; i += zoomStep) {
|
||||
g2dWrapper.drawLine((int) i, 0, (int) i, d.height - 1);
|
||||
}
|
||||
for (double j = zoomStep; j < d.height; j += zoomStep) {
|
||||
g2dWrapper.drawLine(0, (int) j, d.width - 1, (int) j);
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.abs(1.0 - zoom) > 1e-4) {
|
||||
g2dWrapper.scale(zoom, zoom);
|
||||
}
|
||||
|
||||
// Composite mainComposite = g2d.getComposite();
|
||||
// Composite alphaComposite =
|
||||
// AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
|
||||
|
||||
// g2dWrapper.resetTx();
|
||||
|
||||
// componentAreaMap.clear();
|
||||
for (IDIYComponent<?> component : project.getComponents()) {
|
||||
// Do not draw the component if it's filtered out.
|
||||
if (filter != null && !filter.testComponent(component)) {
|
||||
continue;
|
||||
}
|
||||
ComponentState state = ComponentState.NORMAL;
|
||||
if (drawOptions.contains(DrawOption.SELECTION)
|
||||
&& selectedComponents.contains(component)) {
|
||||
if (dragInProgress) {
|
||||
state = ComponentState.DRAGGING;
|
||||
} else {
|
||||
state = ComponentState.SELECTED;
|
||||
}
|
||||
}
|
||||
// Do not track the area if component is not invalidated and was
|
||||
// drawn in the same state.
|
||||
boolean trackArea = lastDrawnStateMap.get(component) != state;
|
||||
g2dWrapper.startedDrawingComponent();
|
||||
if (!trackArea) {
|
||||
g2dWrapper.stopTracking();
|
||||
}
|
||||
// Draw locked components in a new composite.
|
||||
if (lockedComponents.contains(component)) {
|
||||
g2d.setComposite(lockedComposite);
|
||||
}
|
||||
// Draw the component through the g2dWrapper.
|
||||
try {
|
||||
component.draw(g2dWrapper, state, project, g2dWrapper);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error drawing " + component.getName(), e);
|
||||
failedComponents.add(component);
|
||||
}
|
||||
Area area = g2dWrapper.finishedDrawingComponent();
|
||||
if (trackArea) {
|
||||
componentAreaMap.put(component, area);
|
||||
lastDrawnStateMap.put(component, state);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw control points.
|
||||
if (drawOptions.contains(DrawOption.CONTROL_POINTS)) {
|
||||
// Draw unselected points first to make sure they are below.
|
||||
for (IDIYComponent<?> component : project.getComponents()) {
|
||||
for (int i = 0; i < component.getControlPointCount(); i++) {
|
||||
VisibilityPolicy visibilityPolicy = component
|
||||
.getControlPointVisibilityPolicy(i);
|
||||
if ((groupedComponents.contains(component)
|
||||
&& (visibilityPolicy == VisibilityPolicy.ALWAYS || (selectedComponents
|
||||
.contains(component) && visibilityPolicy == VisibilityPolicy.WHEN_SELECTED)) || (!groupedComponents
|
||||
.contains(component)
|
||||
&& !selectedComponents.contains(component) && component
|
||||
.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS))) {
|
||||
g2dWrapper.setColor(CONTROL_POINT_COLOR);
|
||||
|
||||
Point controlPoint = component.getControlPoint(i);
|
||||
int pointSize = CONTROL_POINT_SIZE - 2;
|
||||
g2dWrapper.fillOval(controlPoint.x - pointSize / 2, controlPoint.y
|
||||
- pointSize / 2, pointSize, pointSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Then draw the selected ones.
|
||||
for (IDIYComponent<?> component : selectedComponents) {
|
||||
for (int i = 0; i < component.getControlPointCount(); i++) {
|
||||
if (!groupedComponents.contains(component)
|
||||
&& (component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.WHEN_SELECTED || component
|
||||
.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS)) {
|
||||
|
||||
Point controlPoint = component.getControlPoint(i);
|
||||
int pointSize = CONTROL_POINT_SIZE;
|
||||
|
||||
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
|
||||
g2dWrapper.fillOval(controlPoint.x - pointSize / 2, controlPoint.y
|
||||
- pointSize / 2, pointSize, pointSize);
|
||||
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
|
||||
g2dWrapper.fillOval(controlPoint.x - CONTROL_POINT_SIZE / 2 + 1,
|
||||
controlPoint.y - CONTROL_POINT_SIZE / 2 + 1,
|
||||
CONTROL_POINT_SIZE - 2, CONTROL_POINT_SIZE - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw component slot in a separate composite.
|
||||
if (componentSlot != null) {
|
||||
g2dWrapper.startedDrawingComponent();
|
||||
g2dWrapper.setComposite(slotComposite);
|
||||
try {
|
||||
componentSlot.draw(g2dWrapper, ComponentState.NORMAL, project, g2dWrapper);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error drawing " + componentSlot.getName(), e);
|
||||
failedComponents.add(componentSlot);
|
||||
}
|
||||
g2dWrapper.finishedDrawingComponent();
|
||||
}
|
||||
|
||||
// Draw control points of the component in the slot.
|
||||
if (controlPointSlot != null) {
|
||||
for (Point point : controlPointSlot) {
|
||||
if (point != null) {
|
||||
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
|
||||
g2dWrapper.fillOval(point.x - CONTROL_POINT_SIZE / 2, point.y
|
||||
- CONTROL_POINT_SIZE / 2, CONTROL_POINT_SIZE, CONTROL_POINT_SIZE);
|
||||
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
|
||||
g2dWrapper.fillOval(point.x - CONTROL_POINT_SIZE / 2 + 1, point.y
|
||||
- CONTROL_POINT_SIZE / 2 + 1, CONTROL_POINT_SIZE - 2,
|
||||
CONTROL_POINT_SIZE - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go back to the original transformation and zoom in to draw the
|
||||
// selection rectangle and other similar elements.
|
||||
// g2d.setTransform(initialTx);
|
||||
// if ((drawOptions.contains(DrawOption.ZOOM)) && (Math.abs(1.0 -
|
||||
// zoomLevel) > 1e-4)) {
|
||||
// g2d.scale(zoomLevel, zoomLevel);
|
||||
// }
|
||||
|
||||
// At the end draw selection rectangle if needed.
|
||||
if (drawOptions.contains(DrawOption.SELECTION) && (selectionRect != null)) {
|
||||
g2d.setColor(Color.white);
|
||||
g2d.draw(selectionRect);
|
||||
g2d.setColor(Color.black);
|
||||
g2d.setStroke(Constants.DASHED_STROKE);
|
||||
g2d.draw(selectionRect);
|
||||
}
|
||||
|
||||
// Draw component area for test
|
||||
if (DEBUG_COMPONENT_AREAS) {
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||
g2d.setColor(Color.red);
|
||||
for (Area area : componentAreaMap.values()) {
|
||||
g2d.draw(area);
|
||||
}
|
||||
}
|
||||
|
||||
return failedComponents;
|
||||
}
|
||||
|
||||
public double getZoomLevel() {
|
||||
return zoomLevel;
|
||||
}
|
||||
|
||||
public void setZoomLevel(double zoomLevel) {
|
||||
this.zoomLevel = zoomLevel;
|
||||
fireZoomChanged();
|
||||
// ConfigurationManager.getInstance().writeValue(ZOOM_KEY, zoomLevel);
|
||||
}
|
||||
|
||||
public void invalidateComponent(IDIYComponent<?> component) {
|
||||
componentAreaMap.remove(component);
|
||||
lastDrawnStateMap.remove(component);
|
||||
}
|
||||
|
||||
public Area getComponentArea(IDIYComponent<?> component) {
|
||||
return componentAreaMap.get(component);
|
||||
}
|
||||
|
||||
public List<IDIYComponent<?>> findComponentsAt(Point point, Project project) {
|
||||
List<IDIYComponent<?>> components = new ArrayList<IDIYComponent<?>>();
|
||||
for (int i = 0; i < project.getComponents().size(); i++) {
|
||||
Area area = componentAreaMap.get(project.getComponents().get(i));
|
||||
if (area != null && area.contains(point)) {
|
||||
components.add(project.getComponents().get(i));
|
||||
}
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
||||
public Dimension getCanvasDimensions(Project project, Double zoomLevel, boolean useZoom) {
|
||||
double width = project.getWidth().convertToPixels();
|
||||
int height = project.getHeight().convertToPixels();
|
||||
if (useZoom) {
|
||||
width *= zoomLevel;
|
||||
height *= zoomLevel;
|
||||
} else {
|
||||
width /= Constants.PIXEL_SIZE;
|
||||
height /= Constants.PIXEL_SIZE;
|
||||
}
|
||||
return new Dimension((int) width, (int) height);
|
||||
}
|
||||
|
||||
public void fireZoomChanged() {
|
||||
messageDispatcher.dispatchMessage(EventType.ZOOM_CHANGED, zoomLevel);
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
}
|
||||
}
|
||||
@@ -1,672 +0,0 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.RenderingHints.Key;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Arc2D;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.CubicCurve2D;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.awt.image.renderable.RenderableImage;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.diylc.core.IDrawingObserver;
|
||||
|
||||
/**
|
||||
* {@link Graphics2D} wrapper that keeps track of all drawing actions and
|
||||
* creates an {@link Area} that corresponds to drawn objects. Before each
|
||||
* component is drawn, {@link #startedDrawingComponent()} should be called.
|
||||
* After the component is drawn, area may be retrieved using
|
||||
* {@link #finishedDrawingComponent()}. Graphics configuration (color, font,
|
||||
* etc) is reset between each two components.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||
|
||||
public static int LINE_SENSITIVITY_MARGIN = 2;
|
||||
public static int CURVE_SENSITIVITY = 6;
|
||||
|
||||
private boolean drawingComponent = false;
|
||||
private boolean trackingAllowed = true;
|
||||
|
||||
private Graphics2D canvasGraphics;
|
||||
private Stroke originalStroke;
|
||||
private Color originalColor;
|
||||
private Composite originalComposite;
|
||||
private AffineTransform originalTx;
|
||||
private Font originalFont;
|
||||
private AffineTransform currentTx;
|
||||
private Area currentArea;
|
||||
private Shape lastShape;
|
||||
|
||||
/**
|
||||
* Creates a wrapper around specified {@link Graphics2D} object.
|
||||
*
|
||||
* @param canvasGraphics
|
||||
*/
|
||||
public G2DWrapper(Graphics2D canvasGraphics) {
|
||||
super();
|
||||
this.canvasGraphics = canvasGraphics;
|
||||
currentArea = new Area();
|
||||
currentTx = new AffineTransform();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears out the current area and caches canvas settings.
|
||||
*/
|
||||
public void startedDrawingComponent() {
|
||||
drawingComponent = true;
|
||||
currentArea = new Area();
|
||||
originalStroke = canvasGraphics.getStroke();
|
||||
originalColor = canvasGraphics.getColor();
|
||||
originalTx = canvasGraphics.getTransform();
|
||||
originalComposite = canvasGraphics.getComposite();
|
||||
originalFont = canvasGraphics.getFont();
|
||||
currentTx = new AffineTransform();
|
||||
lastShape = null;
|
||||
startTracking();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts {@link Graphics2D} settings and returns area drawn by component
|
||||
* in the meantime.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Area finishedDrawingComponent() {
|
||||
drawingComponent = false;
|
||||
canvasGraphics.setStroke(originalStroke);
|
||||
canvasGraphics.setColor(originalColor);
|
||||
canvasGraphics.setTransform(originalTx);
|
||||
canvasGraphics.setComposite(originalComposite);
|
||||
canvasGraphics.setFont(originalFont);
|
||||
return currentArea;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTracking() {
|
||||
this.trackingAllowed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopTracking() {
|
||||
this.trackingAllowed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends shape interior to the current component area.
|
||||
*
|
||||
* @param s
|
||||
*/
|
||||
private void appendShape(Shape s) {
|
||||
if (!drawingComponent || !trackingAllowed) {
|
||||
return;
|
||||
}
|
||||
Rectangle2D bounds = s.getBounds2D();
|
||||
// Only cache the shape if it's not 1D.
|
||||
if (bounds.getWidth() > 1 && bounds.getHeight() > 1) {
|
||||
Area area = new Area(s);
|
||||
area.transform(currentTx);
|
||||
currentArea.add(area);
|
||||
lastShape = s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends shape outline to the current component area.
|
||||
*
|
||||
* @param s
|
||||
*/
|
||||
private void appendShapeOutline(Shape s) {
|
||||
// Do not add shape outline if the same shape has been filled recently.
|
||||
if (!drawingComponent || !trackingAllowed || s.equals(lastShape)) {
|
||||
return;
|
||||
}
|
||||
lastShape = s;
|
||||
PathIterator pathIterator = s.getPathIterator(null);
|
||||
double thickness;
|
||||
if (getStroke() instanceof BasicStroke) {
|
||||
thickness = ((BasicStroke) getStroke()).getLineWidth() + 2 * LINE_SENSITIVITY_MARGIN;
|
||||
} else {
|
||||
thickness = 2 * LINE_SENSITIVITY_MARGIN;
|
||||
}
|
||||
Point2D prevPoint = null;
|
||||
while (!pathIterator.isDone()) {
|
||||
double[] coord = new double[6];
|
||||
int type = pathIterator.currentSegment(coord);
|
||||
switch (type) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
prevPoint = new Point2D.Double(coord[0], coord[1]);
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
// Represent straight line with a rectangle.
|
||||
Point2D nextPoint = new Point2D.Double(coord[0], coord[1]);
|
||||
Double theta = Math.atan2(nextPoint.getY() - prevPoint.getY(), nextPoint.getX()
|
||||
- prevPoint.getX());
|
||||
double width = Math.sqrt(Math.pow(nextPoint.getX() - prevPoint.getX(), 2)
|
||||
+ Math.pow(nextPoint.getY() - prevPoint.getY(), 2));
|
||||
double midX = (prevPoint.getX() + nextPoint.getX()) / 2;
|
||||
double midY = (prevPoint.getY() + nextPoint.getY()) / 2;
|
||||
Rectangle2D rect = new Rectangle2D.Double(midX - width / 2, midY - thickness / 2,
|
||||
width, thickness);
|
||||
Area area = new Area(rect);
|
||||
area.transform(AffineTransform.getRotateInstance(theta, midX, midY));
|
||||
appendShape(area);
|
||||
// Set the prev point to line end
|
||||
prevPoint = nextPoint;
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
CubicCurve2D cubicCurve = new CubicCurve2D.Double(prevPoint.getX(), prevPoint
|
||||
.getY(), coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]);
|
||||
addCubicCurveArea(cubicCurve);
|
||||
prevPoint = new Point2D.Double(coord[4], coord[5]);
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
QuadCurve2D quadCurve = new QuadCurve2D.Double(prevPoint.getX(), prevPoint.getY(),
|
||||
coord[0], coord[1], coord[2], coord[3]);
|
||||
addQuadCurveArea(quadCurve);
|
||||
prevPoint = new Point2D.Double(coord[3], coord[3]);
|
||||
break;
|
||||
}
|
||||
pathIterator.next();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a cubic curve to the component area. It uses subdivision to
|
||||
* approximate the curve with a series of straight lines.
|
||||
*
|
||||
* @param curve
|
||||
*/
|
||||
private void addCubicCurveArea(CubicCurve2D curve) {
|
||||
// When end points are close enough, approximate the curve with a
|
||||
// straight line.
|
||||
if (curve.getFlatness() < CURVE_SENSITIVITY) {
|
||||
appendShapeOutline(new Line2D.Double(curve.getP1(), curve.getP2()));
|
||||
} else {
|
||||
CubicCurve2D leftSubcurve = new CubicCurve2D.Double();
|
||||
CubicCurve2D rightSubcurve = new CubicCurve2D.Double();
|
||||
curve.subdivide(leftSubcurve, rightSubcurve);
|
||||
addCubicCurveArea(leftSubcurve);
|
||||
addCubicCurveArea(rightSubcurve);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a quad curve to the component area. It uses subdivision to
|
||||
* approximate the curve with a series of straight lines.
|
||||
*
|
||||
* @param curve
|
||||
*/
|
||||
private void addQuadCurveArea(QuadCurve2D curve) {
|
||||
// When end points are close enough, approximate the curve with a
|
||||
// straight line.
|
||||
if (curve.getFlatness() < CURVE_SENSITIVITY) {
|
||||
appendShapeOutline(new Line2D.Double(curve.getP1(), curve.getP2()));
|
||||
} else {
|
||||
QuadCurve2D leftSubcurve = new QuadCurve2D.Double();
|
||||
QuadCurve2D rightSubcurve = new QuadCurve2D.Double();
|
||||
curve.subdivide(leftSubcurve, rightSubcurve);
|
||||
addQuadCurveArea(leftSubcurve);
|
||||
addQuadCurveArea(rightSubcurve);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRenderingHints(Map<?, ?> hints) {
|
||||
canvasGraphics.addRenderingHints(hints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clip(Shape s) {
|
||||
canvasGraphics.clip(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Shape s) {
|
||||
canvasGraphics.draw(s);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShapeOutline(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGlyphVector(GlyphVector g, float x, float y) {
|
||||
canvasGraphics.drawGlyphVector(g, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
|
||||
// FIXME: process map
|
||||
return canvasGraphics.drawImage(img, xform, obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
|
||||
canvasGraphics.drawImage(img, op, x, y);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
|
||||
canvasGraphics.drawRenderableImage(img, xform);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
|
||||
canvasGraphics.drawRenderedImage(img, xform);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(String str, int x, int y) {
|
||||
canvasGraphics.drawString(str, x, y);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
FontMetrics fontMetrics = canvasGraphics.getFontMetrics();
|
||||
Rectangle2D rect = fontMetrics.getStringBounds(str, canvasGraphics);
|
||||
appendShape(new Rectangle2D.Double(rect.getX() + x, rect.getY() + y, rect.getWidth(),
|
||||
rect.getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(String str, float x, float y) {
|
||||
canvasGraphics.drawString(str, x, y);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
FontMetrics fontMetrics = canvasGraphics.getFontMetrics();
|
||||
Rectangle2D rect = fontMetrics.getStringBounds(str, canvasGraphics);
|
||||
appendShape(new Rectangle2D.Double(rect.getX() + x, rect.getY() + y, rect.getWidth(),
|
||||
rect.getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(AttributedCharacterIterator iterator, int x, int y) {
|
||||
canvasGraphics.drawString(iterator, x, y);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(AttributedCharacterIterator iterator, float x, float y) {
|
||||
canvasGraphics.drawString(iterator, x, y);
|
||||
// FIXME: process map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill(Shape s) {
|
||||
canvasGraphics.fill(s);
|
||||
appendShape(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getBackground() {
|
||||
return canvasGraphics.getBackground();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Composite getComposite() {
|
||||
return canvasGraphics.getComposite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return canvasGraphics.getDeviceConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontRenderContext getFontRenderContext() {
|
||||
return canvasGraphics.getFontRenderContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paint getPaint() {
|
||||
return canvasGraphics.getPaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRenderingHint(Key hintKey) {
|
||||
return canvasGraphics.getRenderingHint(hintKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderingHints getRenderingHints() {
|
||||
return canvasGraphics.getRenderingHints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stroke getStroke() {
|
||||
return canvasGraphics.getStroke();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getTransform() {
|
||||
return canvasGraphics.getTransform();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
|
||||
return canvasGraphics.hit(rect, s, onStroke);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(double theta) {
|
||||
canvasGraphics.rotate(theta);
|
||||
currentTx.rotate(theta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(double theta, double x, double y) {
|
||||
canvasGraphics.rotate(theta, x, y);
|
||||
currentTx.rotate(theta, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scale(double sx, double sy) {
|
||||
canvasGraphics.scale(sx, sy);
|
||||
currentTx.scale(sx, sy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground(Color color) {
|
||||
canvasGraphics.setBackground(color);
|
||||
// FIXME: fix map
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComposite(Composite comp) {
|
||||
canvasGraphics.setComposite(comp);
|
||||
// FIXME: check this.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaint(Paint paint) {
|
||||
canvasGraphics.setPaint(paint);
|
||||
// FIXME: check this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderingHint(Key hintKey, Object hintValue) {
|
||||
canvasGraphics.setRenderingHint(hintKey, hintValue);
|
||||
// FIXME: check this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderingHints(Map<?, ?> hints) {
|
||||
canvasGraphics.setRenderingHints(hints);
|
||||
// FIXME: check this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStroke(Stroke s) {
|
||||
canvasGraphics.setStroke(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransform(AffineTransform Tx) {
|
||||
canvasGraphics.setTransform(Tx);
|
||||
currentTx = Tx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shear(double shx, double shy) {
|
||||
canvasGraphics.shear(shx, shy);
|
||||
currentTx.shear(shx, shy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(AffineTransform Tx) {
|
||||
canvasGraphics.transform(Tx);
|
||||
currentTx.concatenate(Tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(int x, int y) {
|
||||
canvasGraphics.translate(x, y);
|
||||
currentTx.translate(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(double tx, double ty) {
|
||||
canvasGraphics.translate(tx, ty);
|
||||
currentTx.translate(tx, ty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRect(int x, int y, int width, int height) {
|
||||
canvasGraphics.clearRect(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clipRect(int x, int y, int width, int height) {
|
||||
canvasGraphics.clipRect(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyArea(int x, int y, int width, int height, int dx, int dy) {
|
||||
canvasGraphics.copyArea(x, y, width, height, dx, dy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics create() {
|
||||
return canvasGraphics.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
canvasGraphics.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
|
||||
canvasGraphics.drawArc(x, y, width, height, startAngle, arcAngle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
|
||||
boolean result = canvasGraphics.drawImage(img, x, y, observer);
|
||||
appendShape(new Rectangle2D.Double(x, y, img.getWidth(observer), img.getHeight(observer)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return canvasGraphics.drawImage(img, x, y, bgcolor, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return canvasGraphics.drawImage(img, x, y, width, height, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor,
|
||||
ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return canvasGraphics.drawImage(img, x, y, width, height, bgcolor, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
|
||||
int sx2, int sy2, ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return canvasGraphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
|
||||
int sx2, int sy2, Color bgcolor, ImageObserver observer) {
|
||||
// FIXME: map
|
||||
return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLine(int x1, int y1, int x2, int y2) {
|
||||
canvasGraphics.drawLine(x1, y1, x2, y2);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShapeOutline(new Line2D.Double(x1, y1, x2, y2));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOval(int x, int y, int width, int height) {
|
||||
canvasGraphics.drawOval(x, y, width, height);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShapeOutline(new Ellipse2D.Double(x, y, width, height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolygon(int[] points, int[] points2, int points3) {
|
||||
canvasGraphics.drawPolygon(points, points2, points3);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShapeOutline(new Polygon(points, points2, points3));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolyline(int[] points, int[] points2, int points3) {
|
||||
canvasGraphics.drawPolyline(points, points2, points3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
|
||||
canvasGraphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShapeOutline(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
|
||||
canvasGraphics.fillArc(x, y, width, height, startAngle, arcAngle);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShape(new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.PIE));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillOval(int x, int y, int width, int height) {
|
||||
canvasGraphics.fillOval(x, y, width, height);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShape(new Ellipse2D.Double(x, y, width, height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillPolygon(int[] points, int[] points2, int points3) {
|
||||
canvasGraphics.fillPolygon(points, points2, points3);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShape(new Polygon(points, points2, points3));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRect(int x, int y, int width, int height) {
|
||||
canvasGraphics.drawRect(x, y, width, height);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShapeOutline(new Rectangle(x, y, width, height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRect(int x, int y, int width, int height) {
|
||||
canvasGraphics.fillRect(x, y, width, height);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShape(new Rectangle(x, y, width, height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
|
||||
canvasGraphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
|
||||
if (drawingComponent && trackingAllowed) {
|
||||
appendShape(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getClip() {
|
||||
return canvasGraphics.getClip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getClipBounds() {
|
||||
return canvasGraphics.getClipBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColor() {
|
||||
return canvasGraphics.getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Font getFont() {
|
||||
return canvasGraphics.getFont();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontMetrics getFontMetrics(Font f) {
|
||||
return canvasGraphics.getFontMetrics(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClip(Shape clip) {
|
||||
canvasGraphics.setClip(clip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClip(int x, int y, int width, int height) {
|
||||
canvasGraphics.setClip(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(Color c) {
|
||||
canvasGraphics.setColor(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFont(Font font) {
|
||||
canvasGraphics.setFont(font);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaintMode() {
|
||||
canvasGraphics.setPaintMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setXORMode(Color c1) {
|
||||
canvasGraphics.setXORMode(c1);
|
||||
}
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.ComponentType;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.measures.Size;
|
||||
|
||||
import com.diyfever.gui.miscutils.ConfigurationManager;
|
||||
import com.rits.cloning.Cloner;
|
||||
|
||||
/**
|
||||
* Manages component instantiation.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class InstantiationManager {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(InstantiationManager.class);
|
||||
|
||||
private Cloner cloner;
|
||||
|
||||
private ComponentType componentTypeSlot;
|
||||
private IDIYComponent<?> componentSlot;
|
||||
private Point firstControlPoint;
|
||||
private Point potentialControlPoint;
|
||||
|
||||
public InstantiationManager() {
|
||||
cloner = new Cloner();
|
||||
}
|
||||
|
||||
public ComponentType getComponentTypeSlot() {
|
||||
return componentTypeSlot;
|
||||
}
|
||||
|
||||
public IDIYComponent<?> getComponentSlot() {
|
||||
return componentSlot;
|
||||
}
|
||||
|
||||
public Point getFirstControlPoint() {
|
||||
return firstControlPoint;
|
||||
}
|
||||
|
||||
public Point getPotentialControlPoint() {
|
||||
return potentialControlPoint;
|
||||
}
|
||||
|
||||
public void setComponentTypeSlot(ComponentType componentTypeSlot, Project currentProject)
|
||||
throws Exception {
|
||||
this.componentTypeSlot = componentTypeSlot;
|
||||
if (componentTypeSlot == null) {
|
||||
this.componentSlot = null;
|
||||
} else {
|
||||
switch (componentTypeSlot.getCreationMethod()) {
|
||||
case POINT_BY_POINT:
|
||||
this.componentSlot = null;
|
||||
break;
|
||||
case SINGLE_CLICK:
|
||||
this.componentSlot = instantiateComponent(componentTypeSlot, new Point(0, 0),
|
||||
currentProject);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.firstControlPoint = null;
|
||||
this.potentialControlPoint = null;
|
||||
}
|
||||
|
||||
public void instatiatePointByPoint(Point scaledPoint, Project currentProject) throws Exception {
|
||||
firstControlPoint = scaledPoint;
|
||||
componentSlot = instantiateComponent(componentTypeSlot, firstControlPoint, currentProject);
|
||||
|
||||
// Set the other control point to the same location, we'll
|
||||
// move it later when mouse moves.
|
||||
componentSlot.setControlPoint(firstControlPoint, 0);
|
||||
componentSlot.setControlPoint(firstControlPoint, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates component in the slot with the new second control point.
|
||||
*
|
||||
* @param scaledPoint
|
||||
* @return true, if any change is made
|
||||
*/
|
||||
public boolean updatePointByPoint(Point scaledPoint) {
|
||||
boolean changeMade = !scaledPoint.equals(potentialControlPoint);
|
||||
potentialControlPoint = scaledPoint;
|
||||
if (componentSlot != null) {
|
||||
componentSlot.setControlPoint(scaledPoint, 1);
|
||||
}
|
||||
return changeMade;
|
||||
}
|
||||
|
||||
public boolean updateSingleClick(Point scaledPoint, boolean snapToGrid, Size gridSpacing) {
|
||||
if (potentialControlPoint == null) {
|
||||
potentialControlPoint = new Point(0, 0);
|
||||
}
|
||||
int dx = scaledPoint.x - potentialControlPoint.x;
|
||||
int dy = scaledPoint.y - potentialControlPoint.y;
|
||||
if (snapToGrid) {
|
||||
dx = CalcUtils.roundToGrid(dx, gridSpacing);
|
||||
dy = CalcUtils.roundToGrid(dy, gridSpacing);
|
||||
}
|
||||
// Only repaint if there's an actual change.
|
||||
if (dx == 0 && dy == 0) {
|
||||
return false;
|
||||
}
|
||||
potentialControlPoint.translate(dx, dy);
|
||||
if (componentSlot == null) {
|
||||
LOG.error("Component slot should not be null!");
|
||||
} else {
|
||||
Point p = new Point();
|
||||
for (int i = 0; i < componentSlot.getControlPointCount(); i++) {
|
||||
p.setLocation(componentSlot.getControlPoint(i));
|
||||
p.translate(dx, dy);
|
||||
componentSlot.setControlPoint(p, i);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public IDIYComponent<?> instantiateComponent(ComponentType componentType, Point point,
|
||||
Project currentProject) throws Exception {
|
||||
LOG.info("Instatiating component of type: " + componentType.getInstanceClass().getName());
|
||||
|
||||
// Instantiate the component.
|
||||
IDIYComponent<?> component = componentType.getInstanceClass().newInstance();
|
||||
|
||||
// Find the next available componentName for the component.
|
||||
int i = 0;
|
||||
boolean exists = true;
|
||||
while (exists) {
|
||||
i++;
|
||||
String name = componentType.getNamePrefix() + i;
|
||||
exists = false;
|
||||
for (IDIYComponent<?> c : currentProject.getComponents()) {
|
||||
if (c.getName().equals(name)) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
component.setName(componentType.getNamePrefix() + i);
|
||||
|
||||
// Translate them to the desired location.
|
||||
if (point != null) {
|
||||
for (int j = 0; j < component.getControlPointCount(); j++) {
|
||||
Point controlPoint = new Point(component.getControlPoint(j));
|
||||
controlPoint.translate(point.x, point.y);
|
||||
// snapPointToGrid(controlPoint);
|
||||
component.setControlPoint(controlPoint, j);
|
||||
}
|
||||
}
|
||||
|
||||
fillWithDefaultProperties(component);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds any properties that have default values and injects default values.
|
||||
* Typically it should be used for {@link IDIYComponent} and {@link Project}
|
||||
* objects.
|
||||
*
|
||||
* @param object
|
||||
* @throws IllegalArgumentException
|
||||
* @throws IllegalAccessException
|
||||
* @throws InvocationTargetException
|
||||
*/
|
||||
public void fillWithDefaultProperties(Object object) throws IllegalArgumentException,
|
||||
IllegalAccessException, InvocationTargetException {
|
||||
// Extract properties.
|
||||
List<PropertyWrapper> properties = ComponentProcessor.getInstance().extractProperties(
|
||||
object.getClass());
|
||||
// Override with default values if available.
|
||||
for (PropertyWrapper property : properties) {
|
||||
Object defaultValue = ConfigurationManager.getInstance().readObject(
|
||||
Presenter.DEFAULTS_KEY_PREFIX + object.getClass().getName() + ":"
|
||||
+ property.getName(), null);
|
||||
if (defaultValue != null) {
|
||||
property.setValue(cloner.deepClone(defaultValue));
|
||||
property.writeTo(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,431 +0,0 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.Orientation;
|
||||
import org.diylc.components.boards.AbstractBoard;
|
||||
import org.diylc.components.boards.BlankBoard;
|
||||
import org.diylc.components.boards.PerfBoard;
|
||||
import org.diylc.components.boards.VeroBoard;
|
||||
import org.diylc.components.connectivity.CopperTrace;
|
||||
import org.diylc.components.connectivity.HookupWire;
|
||||
import org.diylc.components.connectivity.Jumper;
|
||||
import org.diylc.components.connectivity.SolderPad;
|
||||
import org.diylc.components.misc.Label;
|
||||
import org.diylc.components.passive.ElectrolyticRadial;
|
||||
import org.diylc.components.passive.RadialFilmCapacitor;
|
||||
import org.diylc.components.passive.Resistor;
|
||||
import org.diylc.components.semiconductors.DIL_IC;
|
||||
import org.diylc.components.semiconductors.DiodePlastic;
|
||||
import org.diylc.components.semiconductors.TransistorTO92;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.measures.Capacitance;
|
||||
import org.diylc.core.measures.Resistance;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.utils.Constants;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.diyfever.gui.simplemq.MessageDispatcher;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.io.xml.DomDriver;
|
||||
|
||||
public class ProjectFileManager {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(ProjectFileManager.class);
|
||||
|
||||
// private static final int V1_PIXELS_PER_INCH = 200;
|
||||
private static final Size V1_GRID_SPACING = new Size(0.1d, SizeUnit.in);
|
||||
private static final Map<String, Color> V1_COLOR_MAP = new HashMap<String, Color>();
|
||||
static {
|
||||
V1_COLOR_MAP.put("red", Color.red);
|
||||
V1_COLOR_MAP.put("blue", Color.blue);
|
||||
V1_COLOR_MAP.put("white", Color.white);
|
||||
V1_COLOR_MAP.put("green", Color.green.darker());
|
||||
V1_COLOR_MAP.put("black", Color.black);
|
||||
V1_COLOR_MAP.put("yellow", Color.yellow);
|
||||
}
|
||||
|
||||
private XStream xStream;
|
||||
|
||||
private String currentFileName = null;
|
||||
private boolean modified = false;
|
||||
|
||||
private MessageDispatcher<EventType> messageDispatcher;
|
||||
|
||||
public ProjectFileManager(MessageDispatcher<EventType> messageDispatcher) {
|
||||
super();
|
||||
this.xStream = new XStream(new DomDriver());
|
||||
xStream.autodetectAnnotations(true);
|
||||
this.messageDispatcher = messageDispatcher;
|
||||
}
|
||||
|
||||
public void startNewFile() {
|
||||
currentFileName = null;
|
||||
modified = false;
|
||||
fireFileStatusChanged();
|
||||
}
|
||||
|
||||
public void serializeProjectToFile(Project project, String fileName) throws IOException {
|
||||
LOG.info(String.format("saveProjectToFile(%s)", fileName));
|
||||
FileOutputStream fos;
|
||||
fos = new FileOutputStream(fileName);
|
||||
xStream.toXML(project, fos);
|
||||
fos.close();
|
||||
this.currentFileName = fileName;
|
||||
this.modified = false;
|
||||
fireFileStatusChanged();
|
||||
}
|
||||
|
||||
public Project deserializeProjectFromFile(String fileName, List<String> warnings)
|
||||
throws SAXException, IOException, ParserConfigurationException {
|
||||
LOG.info(String.format("loadProjectFromFile(%s)", fileName));
|
||||
Project project;
|
||||
File file = new File(fileName);
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
Document doc = db.parse(file);
|
||||
doc.getDocumentElement().normalize();
|
||||
if (doc.getDocumentElement().getNodeName().equalsIgnoreCase(Project.class.getName())) {
|
||||
project = parseV3File(fileName);
|
||||
} else {
|
||||
if (!doc.getDocumentElement().getNodeName().equalsIgnoreCase("layout")) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not open DIY file. Root node is not named 'Layout'.");
|
||||
}
|
||||
String formatVersion = doc.getDocumentElement().getAttribute("formatVersion");
|
||||
if (formatVersion == null || formatVersion.trim().isEmpty()) {
|
||||
LOG.debug("Detected v1 file.");
|
||||
project = parseV1File(doc.getDocumentElement(), warnings);
|
||||
} else if (formatVersion.equals("2.0")) {
|
||||
LOG.debug("Detected v2 file.");
|
||||
project = parseV2File(doc.getDocumentElement());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown file format version: " + formatVersion);
|
||||
}
|
||||
}
|
||||
Collections.sort(warnings);
|
||||
this.currentFileName = fileName;
|
||||
this.modified = false;
|
||||
return project;
|
||||
}
|
||||
|
||||
public void notifyFileChange() {
|
||||
this.modified = true;
|
||||
fireFileStatusChanged();
|
||||
}
|
||||
|
||||
public String getCurrentFileName() {
|
||||
return currentFileName;
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return modified;
|
||||
}
|
||||
|
||||
public void fireFileStatusChanged() {
|
||||
messageDispatcher.dispatchMessage(EventType.FILE_STATUS_CHANGED, getCurrentFileName(),
|
||||
isModified());
|
||||
}
|
||||
|
||||
private Project parseV1File(Element root, List<String> warnings) {
|
||||
Project project = new Project();
|
||||
project.setTitle(root.getAttribute("Project"));
|
||||
project.setAuthor(root.getAttribute("Credits"));
|
||||
project.setGridSpacing(V1_GRID_SPACING);
|
||||
String type = root.getAttribute("Type");
|
||||
|
||||
// Create the board.
|
||||
int width = Integer.parseInt(root.getAttribute("Width")) + 1;
|
||||
int height = Integer.parseInt(root.getAttribute("Height")) + 1;
|
||||
int boardWidth = (int) (width * Constants.PIXELS_PER_INCH * V1_GRID_SPACING.getValue());
|
||||
int boardHeight = (int) (height * Constants.PIXELS_PER_INCH * V1_GRID_SPACING.getValue());
|
||||
int projectWidth = project.getWidth().convertToPixels();
|
||||
int projectHeight = project.getHeight().convertToPixels();
|
||||
int x = (projectWidth - boardWidth) / 2;
|
||||
int y = (projectHeight - boardHeight) / 2;
|
||||
AbstractBoard board;
|
||||
if (type.equalsIgnoreCase("pcb")) {
|
||||
board = new BlankBoard();
|
||||
board.setBoardColor(Color.white);
|
||||
board.setBorderColor(Color.black);
|
||||
} else if (type.equalsIgnoreCase("perfboard")) {
|
||||
board = new PerfBoard();
|
||||
} else if (type.equalsIgnoreCase("stripboard")) {
|
||||
board = new VeroBoard();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unrecognized board type: " + type);
|
||||
}
|
||||
board.setName("Main board");
|
||||
Point referencePoint = new Point(roundToGrid(x, V1_GRID_SPACING), roundToGrid(y,
|
||||
V1_GRID_SPACING));
|
||||
board.setControlPoint(referencePoint, 0);
|
||||
board.setControlPoint(new Point(roundToGrid(x + boardWidth, V1_GRID_SPACING), roundToGrid(y
|
||||
+ boardHeight, V1_GRID_SPACING)), 1);
|
||||
project.getComponents().add(board);
|
||||
|
||||
NodeList childNodes = root.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String nodeName = node.getNodeName();
|
||||
String nameAttr = node.getAttributes().getNamedItem("Name").getNodeValue();
|
||||
Node valueNode = node.getAttributes().getNamedItem("Value");
|
||||
String valueAttr = valueNode == null ? null : valueNode.getNodeValue();
|
||||
int x1Attr = Integer.parseInt(node.getAttributes().getNamedItem("X1")
|
||||
.getNodeValue());
|
||||
int y1Attr = Integer.parseInt(node.getAttributes().getNamedItem("Y1")
|
||||
.getNodeValue());
|
||||
Point point1 = convertV1CoordinatesToV3Point(referencePoint, x1Attr, y1Attr);
|
||||
Point point2 = null;
|
||||
Integer x2Attr = null;
|
||||
Integer y2Attr = null;
|
||||
Color color = null;
|
||||
if (node.getAttributes().getNamedItem("Color") != null) {
|
||||
String colorAttr = node.getAttributes().getNamedItem("Color").getNodeValue();
|
||||
color = V1_COLOR_MAP.get(colorAttr.toLowerCase());
|
||||
}
|
||||
if (node.getAttributes().getNamedItem("X2") != null
|
||||
&& node.getAttributes().getNamedItem("Y2") != null) {
|
||||
x2Attr = Integer.parseInt(node.getAttributes().getNamedItem("X2")
|
||||
.getNodeValue());
|
||||
y2Attr = Integer.parseInt(node.getAttributes().getNamedItem("Y2")
|
||||
.getNodeValue());
|
||||
point2 = convertV1CoordinatesToV3Point(referencePoint, x2Attr, y2Attr);
|
||||
}
|
||||
IDIYComponent<?> component = null;
|
||||
if (nodeName.equalsIgnoreCase("text")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
Label label = new Label();
|
||||
label.setName(nameAttr);
|
||||
if (color != null) {
|
||||
label.setColor(color);
|
||||
}
|
||||
label.setText(valueAttr);
|
||||
label.setCenter(false);
|
||||
label.setControlPoint(convertV1CoordinatesToV3Point(referencePoint, x1Attr,
|
||||
y1Attr), 0);
|
||||
component = label;
|
||||
} else if (nodeName.equalsIgnoreCase("pad")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
SolderPad pad = new SolderPad();
|
||||
pad.setName(nameAttr);
|
||||
if (color != null) {
|
||||
pad.setColor(color);
|
||||
}
|
||||
pad.setControlPoint(convertV1CoordinatesToV3Point(referencePoint, x1Attr,
|
||||
y1Attr), 0);
|
||||
component = pad;
|
||||
} else if (nodeName.equalsIgnoreCase("trace")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
CopperTrace trace = new CopperTrace();
|
||||
trace.setName(nameAttr);
|
||||
if (color != null) {
|
||||
trace.setLeadColor(color);
|
||||
}
|
||||
trace.setControlPoint(point1, 0);
|
||||
trace.setControlPoint(point2, 1);
|
||||
component = trace;
|
||||
} else if (nodeName.equalsIgnoreCase("jumper")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
Jumper jumper = new Jumper();
|
||||
jumper.setName(nameAttr);
|
||||
jumper.setControlPoint(point1, 0);
|
||||
jumper.setControlPoint(point2, 1);
|
||||
component = jumper;
|
||||
} else if (nodeName.equalsIgnoreCase("wire")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
HookupWire wire = new HookupWire();
|
||||
Point midPoint = new Point((point1.x + point2.x) / 2, (point1.y + point2.y) / 2);
|
||||
wire.setName(nameAttr);
|
||||
wire.setControlPoint(point1, 0);
|
||||
wire.setControlPoint(midPoint, 1);
|
||||
wire.setControlPoint(midPoint, 2);
|
||||
wire.setControlPoint(point2, 3);
|
||||
component = wire;
|
||||
} else if (nodeName.equalsIgnoreCase("resistor")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
Resistor resistor = new Resistor();
|
||||
resistor.setName(nameAttr);
|
||||
try {
|
||||
resistor.setValue(Resistance.parseResistance(valueAttr));
|
||||
} catch (Exception e) {
|
||||
LOG.debug("Could not set value of " + nameAttr);
|
||||
}
|
||||
resistor.setLength(new Size(6d, SizeUnit.mm));
|
||||
resistor.setWidth(new Size(2d, SizeUnit.mm));
|
||||
resistor.setControlPoint(point1, 0);
|
||||
resistor.setControlPoint(point2, 1);
|
||||
component = resistor;
|
||||
} else if (nodeName.equalsIgnoreCase("capacitor")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
RadialFilmCapacitor capacitor = new RadialFilmCapacitor();
|
||||
capacitor.setName(nameAttr);
|
||||
try {
|
||||
capacitor.setValue(Capacitance.parseCapacitance(valueAttr));
|
||||
} catch (Exception e) {
|
||||
LOG.debug("Could not set value of " + nameAttr);
|
||||
}
|
||||
capacitor.setLength(new Size(6d, SizeUnit.mm));
|
||||
capacitor.setWidth(new Size(2d, SizeUnit.mm));
|
||||
capacitor.setControlPoint(point1, 0);
|
||||
capacitor.setControlPoint(point2, 1);
|
||||
component = capacitor;
|
||||
} else if (nodeName.equalsIgnoreCase("electrolyte")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
ElectrolyticRadial capacitor = new ElectrolyticRadial();
|
||||
capacitor.setName(nameAttr);
|
||||
try {
|
||||
capacitor.setValue(Capacitance.parseCapacitance(valueAttr));
|
||||
} catch (Exception e) {
|
||||
LOG.debug("Could not set value of " + nameAttr);
|
||||
}
|
||||
String sizeAttr = node.getAttributes().getNamedItem("Size").getNodeValue();
|
||||
if (sizeAttr.equalsIgnoreCase("small")) {
|
||||
capacitor.setLength(new Size(3d, SizeUnit.mm));
|
||||
} else if (sizeAttr.equalsIgnoreCase("medium")) {
|
||||
capacitor.setLength(new Size(5d, SizeUnit.mm));
|
||||
} else if (sizeAttr.equalsIgnoreCase("large")) {
|
||||
capacitor.setLength(new Size(7d, SizeUnit.mm));
|
||||
} else {
|
||||
capacitor.setLength(new Size(4d, SizeUnit.mm));
|
||||
}
|
||||
capacitor.setControlPoint(point1, 0);
|
||||
capacitor.setControlPoint(point2, 1);
|
||||
component = capacitor;
|
||||
} else if (nodeName.equalsIgnoreCase("diode")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
DiodePlastic capacitor = new DiodePlastic();
|
||||
capacitor.setName(nameAttr);
|
||||
try {
|
||||
capacitor.setValue(valueAttr);
|
||||
} catch (Exception e) {
|
||||
LOG.debug("Could not set value of " + nameAttr);
|
||||
}
|
||||
capacitor.setLength(new Size(6d, SizeUnit.mm));
|
||||
capacitor.setWidth(new Size(2d, SizeUnit.mm));
|
||||
capacitor.setControlPoint(point1, 0);
|
||||
capacitor.setControlPoint(point2, 1);
|
||||
component = capacitor;
|
||||
} else if (nodeName.equalsIgnoreCase("transistor")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
TransistorTO92 transistor = new TransistorTO92();
|
||||
transistor.setName(nameAttr);
|
||||
try {
|
||||
transistor.setValue(valueAttr);
|
||||
} catch (Exception e) {
|
||||
LOG.debug("Could not set value of " + nameAttr);
|
||||
}
|
||||
transistor.setControlPoint(point1, 0);
|
||||
if (point1.y > point2.y) {
|
||||
transistor.setOrientation(Orientation._180);
|
||||
} else if (point1.y < point2.y) {
|
||||
transistor.setOrientation(Orientation.DEFAULT);
|
||||
} else if (point1.x < point2.x) {
|
||||
transistor.setOrientation(Orientation._270);
|
||||
} else if (point1.x > point2.x) {
|
||||
transistor.setOrientation(Orientation._90);
|
||||
}
|
||||
// capacitor.setControlPoint(point2, 1);
|
||||
component = transistor;
|
||||
} else if (nodeName.equalsIgnoreCase("ic")) {
|
||||
LOG.debug("Recognized " + nodeName);
|
||||
DIL_IC ic = new DIL_IC();
|
||||
if (x1Attr + 3 == x2Attr) {
|
||||
if (y1Attr < y2Attr) {
|
||||
ic
|
||||
.setPinCount(DIL_IC.PinCount.valueOf("_" + 2
|
||||
* (y2Attr - y1Attr + 1)));
|
||||
} else {
|
||||
ic.setOrientation(Orientation._180);
|
||||
ic
|
||||
.setPinCount(DIL_IC.PinCount.valueOf("_" + 2
|
||||
* (y1Attr - y2Attr + 1)));
|
||||
}
|
||||
}
|
||||
ic.setName(nameAttr);
|
||||
// Translate control points.
|
||||
for (int j = 0; j < ic.getControlPointCount(); j++) {
|
||||
Point p = new Point(ic.getControlPoint(j));
|
||||
p.translate(point1.x, point1.y);
|
||||
ic.setControlPoint(p, j);
|
||||
}
|
||||
ic.setValue(valueAttr);
|
||||
component = ic;
|
||||
} else {
|
||||
String message = "Could not recognize component type " + nodeName;
|
||||
LOG.debug(message);
|
||||
if (!warnings.contains(message)) {
|
||||
warnings.add(message);
|
||||
}
|
||||
}
|
||||
if (component != null) {
|
||||
project.getComponents().add(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(project.getComponents(), ComparatorFactory.getInstance()
|
||||
.getComponentZOrderComparator());
|
||||
return project;
|
||||
}
|
||||
|
||||
private Point convertV1CoordinatesToV3Point(Point reference, int x, int y) {
|
||||
Point point = new Point(reference);
|
||||
point.translate((int) (x * Constants.PIXELS_PER_INCH * V1_GRID_SPACING.getValue()),
|
||||
(int) (y * Constants.PIXELS_PER_INCH * V1_GRID_SPACING.getValue()));
|
||||
return point;
|
||||
}
|
||||
|
||||
private Project parseV2File(Element root) {
|
||||
Project project = new Project();
|
||||
String projectName = root.getAttribute("projectName");
|
||||
String credits = root.getAttribute("credits");
|
||||
String width = root.getAttribute("width");
|
||||
String height = root.getAttribute("height");
|
||||
NodeList childNodes = root.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
if (node.getNodeName().equalsIgnoreCase("component")) {
|
||||
LOG.debug(node.getAttributes().getNamedItem("name").getNodeValue());
|
||||
} else {
|
||||
LOG.debug("Unrecognized node name found: " + node.getNodeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
private Project parseV3File(String fileName) throws IOException {
|
||||
Project project;
|
||||
FileInputStream fis = new FileInputStream(fileName);
|
||||
project = (Project) xStream.fromXML(fis);
|
||||
fis.close();
|
||||
return project;
|
||||
}
|
||||
|
||||
public int roundToGrid(int x, Size gridSpacing) {
|
||||
int grid = gridSpacing.convertToPixels();
|
||||
return (Math.round(1f * x / grid) * grid);
|
||||
}
|
||||
}
|
||||
@@ -1,792 +0,0 @@
|
||||
package org.diylc.swing;
|
||||
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.ClipboardOwner;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.print.PrinterException;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.ITask;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.images.IconLoader;
|
||||
import org.diylc.swing.gui.DialogFactory;
|
||||
import org.diylc.swing.gui.editor.PropertyEditorDialog;
|
||||
import org.diylc.swing.plugins.edit.ComponentTransferable;
|
||||
import org.diylc.swing.plugins.file.BomDialog;
|
||||
import org.diylc.swing.plugins.file.BomEntry;
|
||||
import org.diylc.swing.plugins.file.BomMaker;
|
||||
import org.diylc.swing.plugins.file.FileFilterEnum;
|
||||
|
||||
import com.diyfever.gui.ButtonDialog;
|
||||
import com.diyfever.gui.IDrawingProvider;
|
||||
import com.diyfever.gui.export.DrawingExporter;
|
||||
import com.rits.cloning.Cloner;
|
||||
|
||||
public class ActionFactory {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(ActionFactory.class);
|
||||
|
||||
private static ActionFactory instance;
|
||||
private static Cloner cloner = new Cloner();
|
||||
|
||||
public static ActionFactory getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ActionFactory();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ActionFactory() {
|
||||
}
|
||||
|
||||
// File menu actions.
|
||||
|
||||
public NewAction createNewAction(IPlugInPort plugInPort) {
|
||||
return new NewAction(plugInPort);
|
||||
}
|
||||
|
||||
public OpenAction createOpenAction(IPlugInPort plugInPort, ISwingUI swingUI) {
|
||||
return new OpenAction(plugInPort, swingUI);
|
||||
}
|
||||
|
||||
public SaveAction createSaveAction(IPlugInPort plugInPort, ISwingUI swingUI) {
|
||||
return new SaveAction(plugInPort, swingUI);
|
||||
}
|
||||
|
||||
public SaveAsAction createSaveAsAction(IPlugInPort plugInPort, ISwingUI swingUI) {
|
||||
return new SaveAsAction(plugInPort, swingUI);
|
||||
}
|
||||
|
||||
public CreateBomAction createBomAction(IPlugInPort plugInPort) {
|
||||
return new CreateBomAction(plugInPort);
|
||||
}
|
||||
|
||||
public ExportPDFAction createExportPDFAction(IDrawingProvider drawingProvider, ISwingUI swingUI) {
|
||||
return new ExportPDFAction(drawingProvider, swingUI);
|
||||
}
|
||||
|
||||
public ExportPNGAction createExportPNGAction(IDrawingProvider drawingProvider, ISwingUI swingUI) {
|
||||
return new ExportPNGAction(drawingProvider, swingUI);
|
||||
}
|
||||
|
||||
public PrintAction createPrintAction(IDrawingProvider drawingProvider) {
|
||||
return new PrintAction(drawingProvider);
|
||||
}
|
||||
|
||||
public ExitAction createExitAction(IPlugInPort plugInPort) {
|
||||
return new ExitAction(plugInPort);
|
||||
}
|
||||
|
||||
// Edit menu actions.
|
||||
|
||||
public CutAction createCutAction(IPlugInPort plugInPort, Clipboard clipboard,
|
||||
ClipboardOwner clipboardOwner) {
|
||||
return new CutAction(plugInPort, clipboard, clipboardOwner);
|
||||
}
|
||||
|
||||
public CopyAction createCopyAction(IPlugInPort plugInPort, Clipboard clipboard,
|
||||
ClipboardOwner clipboardOwner) {
|
||||
return new CopyAction(plugInPort, clipboard, clipboardOwner);
|
||||
}
|
||||
|
||||
public PasteAction createPasteAction(IPlugInPort plugInPort, Clipboard clipboard) {
|
||||
return new PasteAction(plugInPort, clipboard);
|
||||
}
|
||||
|
||||
public SelectAllAction createSelectAllAction(IPlugInPort plugInPort) {
|
||||
return new SelectAllAction(plugInPort);
|
||||
}
|
||||
|
||||
public GroupAction createGroupAction(IPlugInPort plugInPort) {
|
||||
return new GroupAction(plugInPort);
|
||||
}
|
||||
|
||||
public UngroupAction createUngroupAction(IPlugInPort plugInPort) {
|
||||
return new UngroupAction(plugInPort);
|
||||
}
|
||||
|
||||
public EditProjectAction createEditProjectAction(IPlugInPort plugInPort) {
|
||||
return new EditProjectAction(plugInPort);
|
||||
}
|
||||
|
||||
public EditSelectionAction createEditSelectionAction(IPlugInPort plugInPort) {
|
||||
return new EditSelectionAction(plugInPort);
|
||||
}
|
||||
|
||||
public DeleteSelectionAction createDeleteSelectionAction(IPlugInPort plugInPort) {
|
||||
return new DeleteSelectionAction(plugInPort);
|
||||
}
|
||||
|
||||
public SendToBackAction createSendToBackAction(IPlugInPort plugInPort) {
|
||||
return new SendToBackAction(plugInPort);
|
||||
}
|
||||
|
||||
public BringToFrontAction createBringToFrontAction(IPlugInPort plugInPort) {
|
||||
return new BringToFrontAction(plugInPort);
|
||||
}
|
||||
|
||||
// File menu actions.
|
||||
|
||||
public static class NewAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public NewAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "New");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_N,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.DocumentPlainYellow.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("NewAction triggered");
|
||||
if (!plugInPort.allowFileAction()) {
|
||||
return;
|
||||
}
|
||||
plugInPort.createNewProject();
|
||||
List<PropertyWrapper> properties = plugInPort.getProjectProperties();
|
||||
PropertyEditorDialog editor = DialogFactory.getInstance().createPropertyEditorDialog(
|
||||
properties, "Edit Project");
|
||||
editor.setVisible(true);
|
||||
if (ButtonDialog.OK.equals(editor.getSelectedButtonCaption())) {
|
||||
plugInPort.applyPropertiesToProject(properties);
|
||||
}
|
||||
// Save default values.
|
||||
for (PropertyWrapper property : editor.getDefaultedProperties()) {
|
||||
if (property.getValue() != null) {
|
||||
plugInPort.setProjectDefaultPropertyValue(property.getName(), property
|
||||
.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class OpenAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private ISwingUI swingUI;
|
||||
|
||||
public OpenAction(IPlugInPort plugInPort, ISwingUI swingUI) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
this.swingUI = swingUI;
|
||||
putValue(AbstractAction.NAME, "Open");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.FolderOut.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("OpenAction triggered");
|
||||
if (!plugInPort.allowFileAction()) {
|
||||
return;
|
||||
}
|
||||
final File file = DialogFactory.getInstance().showOpenDialog(
|
||||
FileFilterEnum.DIY.getFilter(), null, FileFilterEnum.DIY.getExtensions()[0],
|
||||
null);
|
||||
if (file != null) {
|
||||
swingUI.executeBackgroundTask(new ITask<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInBackground() throws Exception {
|
||||
LOG.debug("Opening from " + file.getAbsolutePath());
|
||||
plugInPort.loadProjectFromFile(file.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(Void result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Exception e) {
|
||||
swingUI.showMessage("Could not open file. " + e.getMessage(), "Error",
|
||||
ISwingUI.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SaveAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private ISwingUI swingUI;
|
||||
|
||||
public SaveAction(IPlugInPort plugInPort, ISwingUI swingUI) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
this.swingUI = swingUI;
|
||||
putValue(AbstractAction.NAME, "Save");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.DiskBlue.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("SaveAction triggered");
|
||||
if (plugInPort.getCurrentFileName() == null) {
|
||||
final File file = DialogFactory.getInstance().showSaveDialog(
|
||||
FileFilterEnum.DIY.getFilter(), null,
|
||||
FileFilterEnum.DIY.getExtensions()[0], null);
|
||||
if (file != null) {
|
||||
swingUI.executeBackgroundTask(new ITask<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInBackground() throws Exception {
|
||||
LOG.debug("Saving to " + file.getAbsolutePath());
|
||||
plugInPort.saveProjectToFile(file.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(Void result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Exception e) {
|
||||
swingUI.showMessage("Could not save to file. " + e.getMessage(),
|
||||
"Error", ISwingUI.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
swingUI.executeBackgroundTask(new ITask<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInBackground() throws Exception {
|
||||
LOG.debug("Saving to " + plugInPort.getCurrentFileName());
|
||||
plugInPort.saveProjectToFile(plugInPort.getCurrentFileName());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(Void result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Exception e) {
|
||||
swingUI.showMessage("Could not save to file. " + e.getMessage(), "Error",
|
||||
ISwingUI.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SaveAsAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private ISwingUI swingUI;
|
||||
|
||||
public SaveAsAction(IPlugInPort plugInPort, ISwingUI swingUI) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
this.swingUI = swingUI;
|
||||
putValue(AbstractAction.NAME, "Save As");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S,
|
||||
ActionEvent.CTRL_MASK | ActionEvent.SHIFT_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.DiskBlue.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("SaveAsAction triggered");
|
||||
final File file = DialogFactory.getInstance().showSaveDialog(
|
||||
FileFilterEnum.DIY.getFilter(), null, FileFilterEnum.DIY.getExtensions()[0],
|
||||
null);
|
||||
if (file != null) {
|
||||
swingUI.executeBackgroundTask(new ITask<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInBackground() throws Exception {
|
||||
LOG.debug("Saving to " + file.getAbsolutePath());
|
||||
plugInPort.saveProjectToFile(file.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(Void result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Exception e) {
|
||||
swingUI.showMessage("Could not save to file. " + e.getMessage(), "Error",
|
||||
ISwingUI.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CreateBomAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public CreateBomAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Create B.O.M.");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.BOM.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("CreateBomAction triggered");
|
||||
List<BomEntry> bom = BomMaker.getInstance().createBom(
|
||||
plugInPort.getCurrentProject().getComponents());
|
||||
BomDialog dialog = DialogFactory.getInstance().createBomDialog(bom);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExportPDFAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IDrawingProvider drawingProvider;
|
||||
private ISwingUI swingUI;
|
||||
|
||||
public ExportPDFAction(IDrawingProvider drawingProvider, ISwingUI swingUI) {
|
||||
super();
|
||||
this.drawingProvider = drawingProvider;
|
||||
this.swingUI = swingUI;
|
||||
putValue(AbstractAction.NAME, "Export to PDF");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.PDF.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("ExportPDFAction triggered");
|
||||
final File file = DialogFactory.getInstance().showSaveDialog(
|
||||
FileFilterEnum.PDF.getFilter(), null, FileFilterEnum.PDF.getExtensions()[0],
|
||||
null);
|
||||
if (file != null) {
|
||||
swingUI.executeBackgroundTask(new ITask<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInBackground() throws Exception {
|
||||
LOG.debug("Exporting to " + file.getAbsolutePath());
|
||||
DrawingExporter.getInstance().exportPDF(
|
||||
ExportPDFAction.this.drawingProvider, file);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(Void result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Exception e) {
|
||||
swingUI.showMessage("Could not export to PDF. " + e.getMessage(), "Error",
|
||||
ISwingUI.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExportPNGAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IDrawingProvider drawingProvider;
|
||||
private ISwingUI swingUI;
|
||||
|
||||
public ExportPNGAction(IDrawingProvider drawingProvider, ISwingUI swingUI) {
|
||||
super();
|
||||
this.drawingProvider = drawingProvider;
|
||||
this.swingUI = swingUI;
|
||||
putValue(AbstractAction.NAME, "Export to PNG");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Image.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("ExportPNGAction triggered");
|
||||
final File file = DialogFactory.getInstance().showSaveDialog(
|
||||
FileFilterEnum.PNG.getFilter(), null, FileFilterEnum.PNG.getExtensions()[0],
|
||||
null);
|
||||
if (file != null) {
|
||||
swingUI.executeBackgroundTask(new ITask<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInBackground() throws Exception {
|
||||
LOG.debug("Exporting to " + file.getAbsolutePath());
|
||||
DrawingExporter.getInstance().exportPNG(
|
||||
ExportPNGAction.this.drawingProvider, file);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(Void result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Exception e) {
|
||||
swingUI.showMessage("Could not export to PNG. " + e.getMessage(), "Error",
|
||||
ISwingUI.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PrintAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IDrawingProvider drawingProvider;
|
||||
|
||||
public PrintAction(IDrawingProvider drawingProvider) {
|
||||
super();
|
||||
this.drawingProvider = drawingProvider;
|
||||
putValue(AbstractAction.NAME, "Print...");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_P,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Print.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("ExportPNGAction triggered");
|
||||
try {
|
||||
DrawingExporter.getInstance().print(this.drawingProvider);
|
||||
} catch (PrinterException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExitAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public ExitAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Exit");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Exit.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (plugInPort.allowFileAction()) {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Edit menu actions.
|
||||
|
||||
public static class CutAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private Clipboard clipboard;
|
||||
private ClipboardOwner clipboardOwner;
|
||||
|
||||
public CutAction(IPlugInPort plugInPort, Clipboard clipboard, ClipboardOwner clipboardOwner) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
this.clipboard = clipboard;
|
||||
this.clipboardOwner = clipboardOwner;
|
||||
putValue(AbstractAction.NAME, "Cut");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Cut.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Cut triggered");
|
||||
clipboard.setContents(new ComponentTransferable(cloner.deepClone(plugInPort
|
||||
.getSelectedComponents())), clipboardOwner);
|
||||
plugInPort.deleteSelectedComponents();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CopyAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private Clipboard clipboard;
|
||||
private ClipboardOwner clipboardOwner;
|
||||
|
||||
public CopyAction(IPlugInPort plugInPort, Clipboard clipboard, ClipboardOwner clipboardOwner) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
this.clipboard = clipboard;
|
||||
this.clipboardOwner = clipboardOwner;
|
||||
putValue(AbstractAction.NAME, "Copy");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Copy.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Copy triggered");
|
||||
clipboard.setContents(new ComponentTransferable(cloner.deepClone(plugInPort
|
||||
.getSelectedComponents())), clipboardOwner);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PasteAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private Clipboard clipboard;
|
||||
|
||||
public PasteAction(IPlugInPort plugInPort, Clipboard clipboard) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
this.clipboard = clipboard;
|
||||
putValue(AbstractAction.NAME, "Paste");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_V,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Paste.getIcon());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Paste triggered");
|
||||
try {
|
||||
List<IDIYComponent<?>> components = (List<IDIYComponent<?>>) clipboard
|
||||
.getData(ComponentTransferable.listFlavor);
|
||||
plugInPort.pasteComponents(cloner.deepClone(components));
|
||||
} catch (Exception ex) {
|
||||
LOG.error("Coule not paste.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SelectAllAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public SelectAllAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Select All");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Selection.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Select All triggered");
|
||||
plugInPort.selectAll();
|
||||
}
|
||||
}
|
||||
|
||||
public static class GroupAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public GroupAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Group Selection");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_G,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Group.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Group Selection triggered");
|
||||
plugInPort.groupSelectedComponents();
|
||||
}
|
||||
}
|
||||
|
||||
public static class UngroupAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public UngroupAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Ungroup Selection");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_U,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Ungroup.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Ungroup Selection triggered");
|
||||
plugInPort.ungroupSelectedComponents();
|
||||
}
|
||||
}
|
||||
|
||||
public static class EditProjectAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public EditProjectAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Edit Project");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.DocumentEdit.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Edit Project triggered");
|
||||
List<PropertyWrapper> properties = plugInPort.getProjectProperties();
|
||||
PropertyEditorDialog editor = DialogFactory.getInstance().createPropertyEditorDialog(
|
||||
properties, "Edit Project");
|
||||
editor.setVisible(true);
|
||||
if (ButtonDialog.OK.equals(editor.getSelectedButtonCaption())) {
|
||||
plugInPort.applyPropertiesToProject(properties);
|
||||
}
|
||||
// Save default values.
|
||||
for (PropertyWrapper property : editor.getDefaultedProperties()) {
|
||||
if (property.getValue() != null) {
|
||||
plugInPort.setProjectDefaultPropertyValue(property.getName(), property
|
||||
.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class EditSelectionAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public EditSelectionAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Edit Selection");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E,
|
||||
ActionEvent.CTRL_MASK));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.EditComponent.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Edit Selection triggered");
|
||||
List<PropertyWrapper> properties = plugInPort.getMutualSelectionProperties();
|
||||
if (properties == null || properties.isEmpty()) {
|
||||
LOG.info("Nothing to edit");
|
||||
return;
|
||||
}
|
||||
PropertyEditorDialog editor = DialogFactory.getInstance().createPropertyEditorDialog(
|
||||
properties, "Edit Selection");
|
||||
editor.setVisible(true);
|
||||
if (ButtonDialog.OK.equals(editor.getSelectedButtonCaption())) {
|
||||
plugInPort.applyPropertiesToSelection(properties);
|
||||
}
|
||||
// Save default values.
|
||||
for (PropertyWrapper property : editor.getDefaultedProperties()) {
|
||||
if (property.getValue() != null) {
|
||||
plugInPort.setSelectionDefaultPropertyValue(property.getName(), property
|
||||
.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class DeleteSelectionAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public DeleteSelectionAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Delete Selection");
|
||||
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Delete.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Delete Selection triggered");
|
||||
plugInPort.deleteSelectedComponents();
|
||||
}
|
||||
}
|
||||
|
||||
public static class SendToBackAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public SendToBackAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Send to Back");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Back.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Send to Back triggered");
|
||||
plugInPort.sendSelectionToBack();
|
||||
}
|
||||
}
|
||||
|
||||
public static class BringToFrontAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public BringToFrontAction(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
putValue(AbstractAction.NAME, "Bring to Front");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Front.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LOG.info("Bring to Front triggered");
|
||||
plugInPort.bringSelectionToFront();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package org.diylc.swing;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.JPopupMenu.Separator;
|
||||
|
||||
import org.diylc.common.BadPositionException;
|
||||
import org.diylc.common.ITask;
|
||||
import org.diylc.core.IView;
|
||||
|
||||
/**
|
||||
* Interface for plugin access to the swing front end.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface ISwingUI extends IView {
|
||||
|
||||
/**
|
||||
* Injects a custom GUI panels provided by the plug-in and desired position
|
||||
* in the window. Application will layout plug-in panels accordingly. <br>
|
||||
* Valid positions are:
|
||||
* <ul>
|
||||
* <li> {@link SwingConstants#TOP}</li>
|
||||
* <li> {@link SwingConstants#BOTTOM}</li>
|
||||
* <li> {@link SwingConstants#LEFT}</li>
|
||||
* <li> {@link SwingConstants#RIGHT}</li>
|
||||
* </ul>
|
||||
*
|
||||
* Center position is reserved for the main canvas panel and cannot be used.
|
||||
*
|
||||
* @param component
|
||||
* @param position
|
||||
* @throws BadPositionException
|
||||
* in case invalid position is specified
|
||||
*/
|
||||
void injectGUIComponent(JComponent component, int position) throws BadPositionException;
|
||||
|
||||
/**
|
||||
* Injects a custom menu action into application's main menu. If
|
||||
* <code>action</code> is set to null {@link Separator} will be added. If
|
||||
* the specified menu does not exist it will be automatically created.
|
||||
*
|
||||
* @param action
|
||||
* {@link Action} to inser
|
||||
* @param menuName
|
||||
* name of the menu to insert into
|
||||
*/
|
||||
void injectMenuAction(Action action, String menuName);
|
||||
|
||||
/**
|
||||
* Injects a custom submenu into application's main menu. If
|
||||
* <code>action</code> is set to null {@link Separator} will be added. If
|
||||
* the specified menu does not exist it will be automatically created.
|
||||
*
|
||||
* @param name
|
||||
* @param icon
|
||||
* @param parentMenuName
|
||||
*/
|
||||
void injectSubmenu(String name, Icon icon, String parentMenuName);
|
||||
|
||||
<T extends Object> void executeBackgroundTask(ITask<T> task);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.diylc.swing.gui;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionAdapter;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
public class CustomGlassPane extends JComponent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Icon icon;
|
||||
|
||||
public CustomGlassPane() {
|
||||
super();
|
||||
addMouseMotionListener(new MouseMotionAdapter() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (icon != null) {
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setCursorIcon(Icon icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
Point cursor = getMousePosition();
|
||||
if ((icon != null) && (cursor != null)) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
icon.paintIcon(this, g2d, cursor.x + 10, cursor.y + 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
package org.diylc.swing.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.swing.gui.components.OverwritePromptFileChooser;
|
||||
import org.diylc.swing.gui.editor.PropertyEditorDialog;
|
||||
import org.diylc.swing.plugins.file.BomDialog;
|
||||
import org.diylc.swing.plugins.file.BomEntry;
|
||||
import org.diylc.swing.plugins.online.view.LoginDialog;
|
||||
import org.diylc.swing.plugins.online.view.NewUserDialog;
|
||||
import org.diylc.swing.plugins.online.view.UploadDialog;
|
||||
|
||||
import com.diyfever.gui.AboutDialog;
|
||||
import com.diyfever.gui.IFileChooserAccessory;
|
||||
import com.diyfever.gui.ProgressDialog;
|
||||
import com.diyfever.gui.miscutils.ConfigurationManager;
|
||||
|
||||
public class DialogFactory {
|
||||
|
||||
private static DialogFactory instance;
|
||||
|
||||
private static final String PATH_KEY = "lastPath";
|
||||
|
||||
public static DialogFactory getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new DialogFactory();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private JFrame mainFrame;
|
||||
private File lastDirectory;
|
||||
|
||||
private DialogFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the frame to be used as dialog parent. This should be called prior
|
||||
* to any other methods in this class.
|
||||
*
|
||||
* @param mainFrame
|
||||
*/
|
||||
public void initialize(JFrame mainFrame) {
|
||||
this.mainFrame = mainFrame;
|
||||
String lastDirectoryPath = (String) ConfigurationManager.getInstance()
|
||||
.readString(PATH_KEY, null);
|
||||
if (lastDirectoryPath != null) {
|
||||
lastDirectory = new File(lastDirectoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyEditorDialog createPropertyEditorDialog(List<PropertyWrapper> properties,
|
||||
String title) {
|
||||
PropertyEditorDialog editor = new PropertyEditorDialog(mainFrame, properties, title);
|
||||
return editor;
|
||||
}
|
||||
|
||||
public BomDialog createBomDialog(List<BomEntry> bom) {
|
||||
BomDialog dialog = new BomDialog(mainFrame, bom);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public File showOpenDialog(FileFilter fileFilter, File initialFile, String defaultExtension,
|
||||
IFileChooserAccessory accessory) {
|
||||
JFileChooser openFileChooser = new JFileChooser();
|
||||
initializeFileChooser(openFileChooser, fileFilter, initialFile, defaultExtension, accessory);
|
||||
|
||||
int result = openFileChooser.showOpenDialog(mainFrame);
|
||||
|
||||
return processFileChooserResult(result, openFileChooser, defaultExtension);
|
||||
}
|
||||
|
||||
public File showSaveDialog(FileFilter fileFilter, File initialFile, String defaultExtension,
|
||||
IFileChooserAccessory accessory) {
|
||||
JFileChooser saveFileChooser = new OverwritePromptFileChooser();
|
||||
initializeFileChooser(saveFileChooser, fileFilter, initialFile, defaultExtension, accessory);
|
||||
|
||||
int result = saveFileChooser.showSaveDialog(mainFrame);
|
||||
|
||||
return processFileChooserResult(result, saveFileChooser, defaultExtension);
|
||||
}
|
||||
|
||||
private void initializeFileChooser(JFileChooser fileChooser, FileFilter fileFilter,
|
||||
File initialFile, String defaultExtension, IFileChooserAccessory accessory) {
|
||||
if (accessory != null) {
|
||||
accessory.install(fileChooser);
|
||||
}
|
||||
for (FileFilter filter : fileChooser.getChoosableFileFilters()) {
|
||||
fileChooser.removeChoosableFileFilter(filter);
|
||||
}
|
||||
if (fileChooser instanceof OverwritePromptFileChooser) {
|
||||
((OverwritePromptFileChooser) fileChooser).setFileFilter(fileFilter, defaultExtension);
|
||||
} else {
|
||||
fileChooser.setFileFilter(fileFilter);
|
||||
}
|
||||
if (lastDirectory != null) {
|
||||
fileChooser.setCurrentDirectory(lastDirectory);
|
||||
}
|
||||
fileChooser.setSelectedFile(initialFile);
|
||||
}
|
||||
|
||||
private File processFileChooserResult(int result, JFileChooser fileChooser,
|
||||
String defaultExtension) {
|
||||
fileChooser.setAccessory(null);
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
lastDirectory = fileChooser.getCurrentDirectory();
|
||||
ConfigurationManager.getInstance().writeValue(PATH_KEY,
|
||||
lastDirectory.getAbsolutePath());
|
||||
if (fileChooser.getSelectedFile().getAbsolutePath().contains(".")) {
|
||||
return fileChooser.getSelectedFile();
|
||||
} else {
|
||||
return new File(fileChooser.getSelectedFile().getAbsoluteFile() + "."
|
||||
+ defaultExtension);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public AboutDialog createAboutDialog(String appName, Icon icon, String version, String author,
|
||||
String url, String mail, String htmlContent) {
|
||||
AboutDialog dialog = new AboutDialog(mainFrame, appName, icon, version, author, url, mail,
|
||||
htmlContent);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public NewUserDialog createNewUserDialog() {
|
||||
NewUserDialog dialog = new NewUserDialog(mainFrame);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public LoginDialog createLoginDialog() {
|
||||
LoginDialog dialog = new LoginDialog(mainFrame);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public UploadDialog createUploadDialog() {
|
||||
UploadDialog dialog = new UploadDialog(mainFrame);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public ProgressDialog createProgressDialog(String title, String[] buttonCaptions,
|
||||
String description, boolean useProgress) {
|
||||
ProgressDialog dialog = new ProgressDialog(mainFrame, title, buttonCaptions, description,
|
||||
useProgress);
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
@@ -1,310 +0,0 @@
|
||||
package org.diylc.swing.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.Timer;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.BadPositionException;
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.IPlugIn;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.ITask;
|
||||
import org.diylc.images.IconLoader;
|
||||
import org.diylc.presenter.Presenter;
|
||||
import org.diylc.swing.ISwingUI;
|
||||
import org.diylc.swing.plugins.canvas.CanvasPlugin;
|
||||
import org.diylc.swing.plugins.edit.EditMenuPlugin;
|
||||
import org.diylc.swing.plugins.file.FileMenuPlugin;
|
||||
import org.diylc.swing.plugins.help.HelpMenuPlugin;
|
||||
import org.diylc.swing.plugins.layers.LayersMenuPlugin;
|
||||
import org.diylc.swing.plugins.statusbar.StatusBar;
|
||||
import org.diylc.swing.plugins.toolbox.ToolBox;
|
||||
|
||||
public class MainFrame extends JFrame implements ISwingUI {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MainFrame.class);
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JPanel centerPanel;
|
||||
private JPanel leftPanel;
|
||||
private JPanel rightPanel;
|
||||
private JPanel topPanel;
|
||||
private JPanel bottomPanel;
|
||||
|
||||
private Presenter presenter;
|
||||
|
||||
private JMenuBar mainMenuBar;
|
||||
private Map<String, JMenu> menuMap;
|
||||
|
||||
private CanvasPlugin canvasPlugin;
|
||||
|
||||
public MainFrame() {
|
||||
super("DIYLC 3");
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
setPreferredSize(new Dimension(800, 600));
|
||||
createBasePanels();
|
||||
menuMap = new HashMap<String, JMenu>();
|
||||
setIconImages(Arrays.asList(IconLoader.IconSmall.getImage(), IconLoader.IconMedium
|
||||
.getImage(), IconLoader.IconLarge.getImage()));
|
||||
DialogFactory.getInstance().initialize(this);
|
||||
|
||||
this.presenter = new Presenter(this);
|
||||
|
||||
presenter.installPlugin(new ToolBox(this));
|
||||
presenter.installPlugin(new FileMenuPlugin(this));
|
||||
presenter.installPlugin(new EditMenuPlugin(this));
|
||||
presenter.installPlugin(new LayersMenuPlugin(this));
|
||||
// presenter.installPlugin(new OnlineManager());
|
||||
presenter.installPlugin(new HelpMenuPlugin(this));
|
||||
|
||||
presenter.installPlugin(new StatusBar(this));
|
||||
canvasPlugin = new CanvasPlugin(this);
|
||||
presenter.installPlugin(canvasPlugin);
|
||||
presenter.installPlugin(new FramePlugin());
|
||||
|
||||
presenter.createNewProject();
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
if (presenter.allowFileAction()) {
|
||||
dispose();
|
||||
presenter.dispose();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
if (presenter.allowFileAction()) {
|
||||
dispose();
|
||||
presenter.dispose();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// setGlassPane(new CustomGlassPane());
|
||||
// getGlassPane().setVisible(true);
|
||||
}
|
||||
|
||||
public Presenter getPresenter() {
|
||||
return presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b) {
|
||||
super.setVisible(b);
|
||||
// TODO: hack to prevent painting issues in the scroll bar rulers. Find
|
||||
// a better fix if possible.
|
||||
Timer timer = new Timer(500, new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
canvasPlugin.refresh();
|
||||
}
|
||||
|
||||
});
|
||||
timer.setRepeats(false);
|
||||
timer.start();
|
||||
// if (b) {
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
//
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
private void createBasePanels() {
|
||||
Container c = new Container();
|
||||
c.setLayout(new BorderLayout());
|
||||
|
||||
centerPanel = new JPanel(new BorderLayout());
|
||||
c.add(centerPanel, BorderLayout.CENTER);
|
||||
|
||||
topPanel = new JPanel();
|
||||
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
|
||||
c.add(topPanel, BorderLayout.NORTH);
|
||||
|
||||
leftPanel = new JPanel();
|
||||
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.X_AXIS));
|
||||
c.add(leftPanel, BorderLayout.WEST);
|
||||
|
||||
bottomPanel = new JPanel();
|
||||
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
|
||||
c.add(bottomPanel, BorderLayout.SOUTH);
|
||||
|
||||
rightPanel = new JPanel();
|
||||
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.X_AXIS));
|
||||
c.add(rightPanel, BorderLayout.EAST);
|
||||
|
||||
setContentPane(c);
|
||||
}
|
||||
|
||||
private JMenuBar getMainMenuBar() {
|
||||
if (mainMenuBar == null) {
|
||||
mainMenuBar = new JMenuBar();
|
||||
setJMenuBar(mainMenuBar);
|
||||
}
|
||||
return mainMenuBar;
|
||||
}
|
||||
|
||||
// IView
|
||||
|
||||
@Override
|
||||
public void showMessage(String message, String title, int messageType) {
|
||||
JOptionPane.showMessageDialog(this, message, title, messageType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int showConfirmDialog(String message, String title, int optionType, int messageType) {
|
||||
return JOptionPane.showConfirmDialog(this, message, title, optionType, messageType);
|
||||
}
|
||||
|
||||
private JMenu findOrCreateMenu(String menuName) {
|
||||
JMenu menu;
|
||||
if (menuMap.containsKey(menuName)) {
|
||||
menu = menuMap.get(menuName);
|
||||
} else {
|
||||
menu = new JMenu(menuName);
|
||||
menuMap.put(menuName, menu);
|
||||
getMainMenuBar().add(menu);
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGUIComponent(JComponent component, int position) throws BadPositionException {
|
||||
LOG.info(String.format("injectGUIComponent(%s, %s)", component.getClass().getName(),
|
||||
position));
|
||||
switch (position) {
|
||||
case SwingConstants.TOP:
|
||||
topPanel.add(component);
|
||||
break;
|
||||
case SwingConstants.LEFT:
|
||||
leftPanel.add(component);
|
||||
break;
|
||||
case SwingConstants.BOTTOM:
|
||||
bottomPanel.add(component);
|
||||
break;
|
||||
case SwingConstants.RIGHT:
|
||||
rightPanel.add(component);
|
||||
break;
|
||||
case SwingConstants.CENTER:
|
||||
centerPanel.add(component, BorderLayout.CENTER);
|
||||
break;
|
||||
default:
|
||||
throw new BadPositionException();
|
||||
}
|
||||
pack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectMenuAction(Action action, String menuName) {
|
||||
LOG.info(String.format("injectMenuAction(%s, %s)", action == null ? "Separator" : action
|
||||
.getValue(Action.NAME), menuName));
|
||||
JMenu menu = findOrCreateMenu(menuName);
|
||||
if (action == null) {
|
||||
menu.addSeparator();
|
||||
} else {
|
||||
Boolean isCheckBox = (Boolean) action.getValue(IPlugInPort.CHECK_BOX_MENU_ITEM);
|
||||
if (isCheckBox != null && isCheckBox) {
|
||||
menu.add(new JCheckBoxMenuItem(action));
|
||||
} else {
|
||||
menu.add(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectSubmenu(String name, Icon icon, String parentMenuName) {
|
||||
LOG.info(String.format("injectSubmenu(%s, icon, %s)", name, parentMenuName));
|
||||
JMenu menu = findOrCreateMenu(parentMenuName);
|
||||
JMenu submenu = new JMenu(name);
|
||||
submenu.setIcon(icon);
|
||||
menu.add(submenu);
|
||||
menuMap.put(name, submenu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Object> void executeBackgroundTask(final ITask<T> task) {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
SwingWorker<T, Void> worker = new SwingWorker<T, Void>() {
|
||||
|
||||
@Override
|
||||
protected T doInBackground() throws Exception {
|
||||
return task.doInBackground();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
T result = get();
|
||||
task.complete(result);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Task failed", e);
|
||||
task.failed(e);
|
||||
}
|
||||
setCursor(Cursor.getDefaultCursor());
|
||||
}
|
||||
};
|
||||
worker.execute();
|
||||
}
|
||||
|
||||
class FramePlugin implements IPlugIn {
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
@Override
|
||||
public void connect(IPlugInPort plugInPort) {
|
||||
this.plugInPort = plugInPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EventType> getSubscribedEventTypes() {
|
||||
return EnumSet.of(EventType.FILE_STATUS_CHANGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessage(EventType eventType, Object... params) {
|
||||
if (eventType == EventType.FILE_STATUS_CHANGED) {
|
||||
String fileName = (String) params[0];
|
||||
if (fileName == null) {
|
||||
fileName = "Untitled";
|
||||
}
|
||||
String modified = (Boolean) params[1] ? " (modified)" : "";
|
||||
setTitle(String.format("DIYLC %s beta - %s %s", plugInPort
|
||||
.getCurrentVersionNumber(), fileName, modified));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
package org.diylc.swing.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.DrawOption;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.core.IView;
|
||||
import org.diylc.presenter.Presenter;
|
||||
|
||||
import com.diyfever.gui.miscutils.ConfigurationManager;
|
||||
|
||||
public class TemplateDialog extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(TemplateDialog.class);
|
||||
|
||||
private static final Dimension panelSize = new Dimension(400, 300);
|
||||
public static final String SHOW_TEMPLATES_KEY = "showTemplatesAtStartup";
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
private JList fileList;
|
||||
private JPanel canvasPanel;
|
||||
private Presenter presenter;
|
||||
private List<File> files;
|
||||
private JCheckBox showTemplatesBox;
|
||||
private JPanel mainPanel;
|
||||
private JButton loadButton;
|
||||
private JPanel infoPanel;
|
||||
|
||||
public TemplateDialog(JFrame owner, IPlugInPort plugInPort) {
|
||||
super(owner, "Templates");
|
||||
setModal(true);
|
||||
setResizable(false);
|
||||
this.plugInPort = plugInPort;
|
||||
this.presenter = new Presenter(new IView() {
|
||||
|
||||
@Override
|
||||
public int showConfirmDialog(String message, String title, int optionType,
|
||||
int messageType) {
|
||||
return JOptionPane.showConfirmDialog(TemplateDialog.this, message, title,
|
||||
optionType, messageType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(String message, String title, int messageType) {
|
||||
JOptionPane.showMessageDialog(TemplateDialog.this, message, title, messageType);
|
||||
}
|
||||
});
|
||||
// this.presenter.installPlugin(new IPlugIn() {
|
||||
//
|
||||
// @Override
|
||||
// public void connect(IPlugInPort plugInPort) {
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public EnumSet<EventType> getSubscribedEventTypes() {
|
||||
// return EnumSet.of(EventType.REPAINT);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void processMessage(EventType eventType, Object... params) {
|
||||
// if (eventType == EventType.REPAINT) {
|
||||
// getCanvasPanel().repaint();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
setContentPane(getMainPanel());
|
||||
pack();
|
||||
setLocationRelativeTo(owner);
|
||||
}
|
||||
|
||||
public JPanel getMainPanel() {
|
||||
if (mainPanel == null) {
|
||||
mainPanel = new JPanel(new GridBagLayout());
|
||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0;
|
||||
c.weighty = 1;
|
||||
c.weightx = 1;
|
||||
c.gridwidth = 2;
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.insets = new Insets(0, 0, 4, 0);
|
||||
mainPanel.add(getInfoPanel(), c);
|
||||
|
||||
c.gridy = 1;
|
||||
c.weightx = 0;
|
||||
c.gridwidth = 1;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
JScrollPane scrollPane = new JScrollPane(getFileList());
|
||||
mainPanel.add(scrollPane, c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.weightx = 1;
|
||||
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(scrollPane.getBorder());
|
||||
panel.add(getCanvasPanel(), BorderLayout.CENTER);
|
||||
mainPanel.add(panel, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 2;
|
||||
c.weightx = 0;
|
||||
c.weighty = 0;
|
||||
c.anchor = GridBagConstraints.LAST_LINE_START;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
mainPanel.add(getShowTemplatesBox(), c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.anchor = GridBagConstraints.LAST_LINE_END;
|
||||
c.insets = new Insets(4, 0, 0, 0);
|
||||
mainPanel.add(getLoadButton(), c);
|
||||
}
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
public JButton getLoadButton() {
|
||||
if (loadButton == null) {
|
||||
loadButton = new JButton("Load Template");
|
||||
loadButton.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
plugInPort.loadProject(presenter.getCurrentProject(), true);
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
return loadButton;
|
||||
}
|
||||
|
||||
public JPanel getInfoPanel() {
|
||||
if (infoPanel == null) {
|
||||
infoPanel = new JPanel();
|
||||
infoPanel.setBackground(Color.decode("#FFFFCC"));
|
||||
infoPanel.setBorder(new JTextField().getBorder());
|
||||
JLabel infoLabel = new JLabel(
|
||||
"<html>Templates are semi-product layouts that are used as a starting point for your projects.<br>"
|
||||
+ "Pick a templete in the left list and click \"Load Template\" to load it or close this dialog to continue.<br>"
|
||||
+ "You can create your own templates by placing a DIY file into <b>diylc/templates</b> directory.</html>");
|
||||
infoLabel.setOpaque(false);
|
||||
infoPanel.add(infoLabel);
|
||||
}
|
||||
return infoPanel;
|
||||
}
|
||||
|
||||
public JList getFileList() {
|
||||
if (fileList == null) {
|
||||
fileList = new JList(getFiles().toArray());
|
||||
fileList.setPreferredSize(new Dimension(128, -1));
|
||||
fileList.setCellRenderer(new DefaultListCellRenderer() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index,
|
||||
boolean isSelected, boolean cellHasFocus) {
|
||||
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index,
|
||||
isSelected, cellHasFocus);
|
||||
if (value instanceof File) {
|
||||
label.setText(((File) value).getName());
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
});
|
||||
fileList.addListSelectionListener(new ListSelectionListener() {
|
||||
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
File file = (File) fileList.getSelectedValue();
|
||||
if (file != null) {
|
||||
presenter.loadProjectFromFile(file.getAbsolutePath());
|
||||
Dimension dim = presenter.getCanvasDimensions(true);
|
||||
double xFactor = panelSize.getWidth() / dim.getWidth();
|
||||
double yFactor = panelSize.getHeight() / dim.getHeight();
|
||||
presenter.setZoomLevel(Math.min(xFactor, yFactor));
|
||||
getCanvasPanel().repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
fileList.setSelectedIndex(0);
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
|
||||
public JCheckBox getShowTemplatesBox() {
|
||||
if (showTemplatesBox == null) {
|
||||
showTemplatesBox = new JCheckBox("Show this dialog at startup");
|
||||
showTemplatesBox.setSelected(true);
|
||||
showTemplatesBox.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ConfigurationManager.getInstance().writeValue(SHOW_TEMPLATES_KEY,
|
||||
showTemplatesBox.isSelected());
|
||||
}
|
||||
});
|
||||
}
|
||||
return showTemplatesBox;
|
||||
}
|
||||
|
||||
public List<File> getFiles() {
|
||||
if (files == null) {
|
||||
files = new ArrayList<File>();
|
||||
File dir = new File("templates");
|
||||
if (dir.exists()) {
|
||||
for (File f : dir.listFiles()) {
|
||||
if (f.isFile() && f.getName().toLowerCase().endsWith(".diy")) {
|
||||
files.add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG.debug("Found " + files.size() + " templates");
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
public JPanel getCanvasPanel() {
|
||||
if (canvasPanel == null) {
|
||||
canvasPanel = new JPanel() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
// Graphics2D g2d = (Graphics2D) g;
|
||||
// AffineTransform transform = g2d.getTransform();
|
||||
presenter.draw((Graphics2D) g, EnumSet.of(DrawOption.ZOOM,
|
||||
DrawOption.ANTIALIASING), null);
|
||||
// g2d.setTransform(transform);
|
||||
// Rectangle rect = canvasPanel.getBounds();
|
||||
// BorderFactory.createEtchedBorder().paintBorder(canvasPanel,
|
||||
// g, 0, 0,
|
||||
// (int) rect.getWidth(), (int) rect.getHeight());
|
||||
}
|
||||
};
|
||||
canvasPanel.setBackground(Color.white);
|
||||
canvasPanel.setPreferredSize(panelSize);
|
||||
}
|
||||
return canvasPanel;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.diylc.swing.gui.components;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
public class OverwritePromptFileChooser extends JFileChooser {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String defaultExtension;
|
||||
|
||||
public void approveSelection() {
|
||||
File lSelectedFile;
|
||||
if (getSelectedFile().getAbsolutePath().contains(".")) {
|
||||
lSelectedFile = getSelectedFile();
|
||||
} else {
|
||||
lSelectedFile = new File(getSelectedFile().getAbsoluteFile() + "." + defaultExtension);
|
||||
}
|
||||
|
||||
if (lSelectedFile != null && lSelectedFile.exists()) {
|
||||
int lResponse = JOptionPane.showConfirmDialog(this, lSelectedFile.getAbsolutePath()
|
||||
+ " already exists.\nDo you " + "want to replace it?", "Warning",
|
||||
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||
|
||||
if (lResponse != JOptionPane.YES_OPTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.approveSelection();
|
||||
}
|
||||
|
||||
public void setFileFilter(FileFilter filter, String defaultExtension) {
|
||||
this.defaultExtension = defaultExtension;
|
||||
super.setFileFilter(filter);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
|
||||
|
||||
public class BooleanEditor extends JCheckBox {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public BooleanEditor(final PropertyWrapper property) {
|
||||
super();
|
||||
setSelected((Boolean) property.getValue());
|
||||
addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
property.setValue(isSelected());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
|
||||
public class ByteEditor extends JSlider {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ByteEditor(final PropertyWrapper property) {
|
||||
super();
|
||||
setMinimum(0);
|
||||
setMaximum(127);
|
||||
setValue((Byte) property.getValue());
|
||||
addChangeListener(new ChangeListener() {
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
property.setValue(new Integer(getValue()).byteValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JColorChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
|
||||
|
||||
public class ColorEditor extends JLabel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ColorEditor(final PropertyWrapper property) {
|
||||
super("Click to edit");
|
||||
setOpaque(true);
|
||||
setHorizontalAlignment(SwingConstants.CENTER);
|
||||
setBorder(BorderFactory.createEtchedBorder());
|
||||
setBackground((Color) property.getValue());
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
addMouseListener(new MouseAdapter() {
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
Color newColor = JColorChooser.showDialog(ColorEditor.this, "Choose Color",
|
||||
getBackground());
|
||||
if (newColor != null) {
|
||||
property.setValue(newColor);
|
||||
setBackground(newColor);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground(Color bg) {
|
||||
if (bg.getRed() < 127 || bg.getBlue() < 127 || bg.getGreen() < 127) {
|
||||
setForeground(Color.white);
|
||||
} else {
|
||||
setForeground(Color.black);
|
||||
}
|
||||
super.setBackground(bg);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
|
||||
public class EnumEditor extends JComboBox {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final PropertyWrapper property;
|
||||
|
||||
public EnumEditor(PropertyWrapper property) {
|
||||
this.property = property;
|
||||
Object[] values = property.getType().getEnumConstants();
|
||||
setModel(new DefaultComboBoxModel(values));
|
||||
setSelectedItem(property.getValue());
|
||||
addItemListener(new ItemListener() {
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
EnumEditor.this.property.setValue(e.getItem());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.core.measures.AbstractMeasure;
|
||||
|
||||
public class FieldEditorFactory {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(FieldEditorFactory.class);
|
||||
|
||||
public static Component createFieldEditor(PropertyWrapper property) {
|
||||
if (property.getType().equals(String.class)) {
|
||||
StringEditor editor = new StringEditor(property);
|
||||
return editor;
|
||||
}
|
||||
if (property.getType().equals(Color.class)) {
|
||||
ColorEditor editor = new ColorEditor(property);
|
||||
return editor;
|
||||
}
|
||||
if (AbstractMeasure.class.isAssignableFrom(property.getType())) {
|
||||
MeasureEditor editor = new MeasureEditor(property);
|
||||
return editor;
|
||||
}
|
||||
if (ImageIcon.class.isAssignableFrom(property.getType())) {
|
||||
ImageEditor editor = new ImageEditor(property);
|
||||
return editor;
|
||||
}
|
||||
if (property.getType().isEnum()) {
|
||||
EnumEditor editor = new EnumEditor(property);
|
||||
return editor;
|
||||
}
|
||||
if (Byte.class.isAssignableFrom(property.getType())
|
||||
|| byte.class.isAssignableFrom(property.getType())) {
|
||||
ByteEditor editor = new ByteEditor(property);
|
||||
return editor;
|
||||
}
|
||||
if (Boolean.class.isAssignableFrom(property.getType())
|
||||
|| boolean.class.isAssignableFrom(property.getType())) {
|
||||
BooleanEditor editor = new BooleanEditor(property);
|
||||
return editor;
|
||||
}
|
||||
LOG.error("Unrecognized parameter type: " + property.getType().getName());
|
||||
return new JLabel("Unrecognized");
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JColorChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
|
||||
|
||||
public class FontEditor extends JLabel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public FontEditor(final PropertyWrapper property) {
|
||||
super("Click to edit");
|
||||
setOpaque(true);
|
||||
setHorizontalAlignment(SwingConstants.CENTER);
|
||||
setBorder(BorderFactory.createEtchedBorder());
|
||||
setBackground((Color) property.getValue());
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
addMouseListener(new MouseAdapter() {
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
// JFo
|
||||
Color newColor = JColorChooser.showDialog(FontEditor.this, "Choose Color",
|
||||
getBackground());
|
||||
if (newColor != null) {
|
||||
property.setValue(newColor);
|
||||
setBackground(newColor);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground(Color bg) {
|
||||
if (bg.getRed() < 127 || bg.getBlue() < 127 || bg.getGreen() < 127) {
|
||||
setForeground(Color.white);
|
||||
} else {
|
||||
setForeground(Color.black);
|
||||
}
|
||||
super.setBackground(bg);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.swing.gui.DialogFactory;
|
||||
import org.diylc.swing.plugins.file.FileFilterEnum;
|
||||
|
||||
public class ImageEditor extends JButton {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ImageEditor(final PropertyWrapper property) {
|
||||
super("Click to load file");
|
||||
addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent e) {
|
||||
File file = DialogFactory.getInstance().showOpenDialog(
|
||||
FileFilterEnum.IMAGES.getFilter(), null,
|
||||
FileFilterEnum.IMAGES.getExtensions()[0], null);
|
||||
if (file != null) {
|
||||
ImageIcon image = new ImageIcon(file.getAbsolutePath());
|
||||
property.setValue(image);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground(Color bg) {
|
||||
if (bg.getRed() < 127 || bg.getBlue() < 127 || bg.getGreen() < 127) {
|
||||
setForeground(Color.white);
|
||||
} else {
|
||||
setForeground(Color.black);
|
||||
}
|
||||
super.setBackground(bg);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.core.measures.AbstractMeasure;
|
||||
import org.diylc.core.measures.Unit;
|
||||
|
||||
import com.diyfever.gui.DoubleTextField;
|
||||
|
||||
public class MeasureEditor extends Container {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public MeasureEditor(final PropertyWrapper property) {
|
||||
setLayout(new BorderLayout());
|
||||
AbstractMeasure measure = ((AbstractMeasure) property.getValue());
|
||||
DoubleTextField valueField = new DoubleTextField(measure.getValue());
|
||||
valueField.addPropertyChangeListener(DoubleTextField.VALUE_PROPERTY,
|
||||
new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
try {
|
||||
AbstractMeasure<?> newMeasure = (AbstractMeasure<?>) ((AbstractMeasure) property
|
||||
.getValue()).clone();
|
||||
newMeasure.setValue((Double) evt.getNewValue());
|
||||
property.setValue(newMeasure);
|
||||
} catch (CloneNotSupportedException ex) {
|
||||
}
|
||||
}
|
||||
});
|
||||
add(valueField, BorderLayout.CENTER);
|
||||
try {
|
||||
Method method = measure.getUnit().getClass().getMethod("values");
|
||||
final JComboBox unitBox = new JComboBox((Object[]) method.invoke(measure.getUnit()));
|
||||
unitBox.setSelectedItem(measure.getUnit());
|
||||
unitBox.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
AbstractMeasure<Enum<? extends Unit>> newMeasure = (AbstractMeasure<Enum<? extends Unit>>) ((AbstractMeasure) property
|
||||
.getValue()).clone();
|
||||
newMeasure.setUnit((Enum<? extends Unit>) unitBox.getSelectedItem());
|
||||
property.setValue(newMeasure);
|
||||
} catch (CloneNotSupportedException ex) {
|
||||
}
|
||||
}
|
||||
});
|
||||
add(unitBox, BorderLayout.EAST);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (SecurityException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.core.ValidationException;
|
||||
|
||||
import com.diyfever.gui.ButtonDialog;
|
||||
|
||||
public class PropertyEditorDialog extends ButtonDialog {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(PropertyEditorDialog.class);
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String DEFAULT_BOX_TOOLTIP = "<html>If this box is checked application will use the current value as a<br>default when creating new components of the same type</html>";
|
||||
|
||||
private List<PropertyWrapper> properties;
|
||||
private Set<PropertyWrapper> defaultedProperties;
|
||||
|
||||
public PropertyEditorDialog(JFrame owner, List<PropertyWrapper> properties, String title) {
|
||||
super(owner, title, new String[] { ButtonDialog.OK, ButtonDialog.CANCEL });
|
||||
|
||||
LOG.debug("Creating property editor for: " + properties);
|
||||
|
||||
this.properties = properties;
|
||||
this.defaultedProperties = new HashSet<PropertyWrapper>();
|
||||
|
||||
setMinimumSize(new Dimension(240, 40));
|
||||
|
||||
layoutGui();
|
||||
setLocationRelativeTo(owner);
|
||||
//
|
||||
// setModal(true);
|
||||
//
|
||||
// JPanel holderPanel = new JPanel();
|
||||
// holderPanel.setLayout(new BorderLayout());
|
||||
// holderPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
||||
//
|
||||
// holderPanel.add(createEditorFields(), BorderLayout.CENTER);
|
||||
// holderPanel.add(createButtonPanel(), BorderLayout.SOUTH);
|
||||
//
|
||||
// setContentPane(holderPanel);
|
||||
//
|
||||
//
|
||||
// pack();
|
||||
// setLocationRelativeTo(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean validateInput(String button) {
|
||||
if (button.equals(ButtonDialog.OK)) {
|
||||
for (PropertyWrapper property : properties) {
|
||||
try {
|
||||
property.getValidator().validate(property.getValue());
|
||||
} catch (ValidationException ve) {
|
||||
JOptionPane.showMessageDialog(PropertyEditorDialog.this, "Input error for \""
|
||||
+ property.getName() + "\": " + ve.getMessage(), "Error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private JPanel createEditorFields() {
|
||||
JPanel editorPanel = new JPanel(new GridBagLayout());
|
||||
editorPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
||||
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
|
||||
gbc.gridy = 0;
|
||||
gbc.insets = new Insets(2, 2, 2, 2);
|
||||
gbc.anchor = GridBagConstraints.LINE_START;
|
||||
|
||||
for (PropertyWrapper property : properties) {
|
||||
gbc.gridx = 0;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.weightx = 0;
|
||||
|
||||
editorPanel.add(new JLabel(property.getName() + ": "), gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc.weightx = 1;
|
||||
|
||||
Component editor = FieldEditorFactory.createFieldEditor(property);
|
||||
editor.addKeyListener(new KeyAdapter() {
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
getButton(OK).doClick();
|
||||
} else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
|
||||
getButton(CANCEL).doClick();
|
||||
}
|
||||
}
|
||||
});
|
||||
editorPanel.add(editor, gbc);
|
||||
|
||||
if (property.isDefaultable()) {
|
||||
gbc.gridx = 2;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.weightx = 0;
|
||||
|
||||
editorPanel.add(createDefaultCheckBox(property), gbc);
|
||||
}
|
||||
|
||||
gbc.gridy++;
|
||||
}
|
||||
|
||||
return editorPanel;
|
||||
}
|
||||
|
||||
private JCheckBox createDefaultCheckBox(final PropertyWrapper property) {
|
||||
final JCheckBox checkBox = new JCheckBox();
|
||||
checkBox.setToolTipText(DEFAULT_BOX_TOOLTIP);
|
||||
checkBox.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (checkBox.isSelected()) {
|
||||
defaultedProperties.add(property);
|
||||
} else {
|
||||
defaultedProperties.remove(property);
|
||||
}
|
||||
}
|
||||
});
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
public Set<PropertyWrapper> getDefaultedProperties() {
|
||||
return defaultedProperties;
|
||||
}
|
||||
|
||||
public static boolean showFor(JFrame owner, List<PropertyWrapper> properties, String title) {
|
||||
PropertyEditorDialog editor = new PropertyEditorDialog(owner, properties, title);
|
||||
editor.setVisible(true);
|
||||
if (OK.equals(editor.getSelectedButtonCaption())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent getMainComponent() {
|
||||
return createEditorFields();
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.diylc.swing.gui.editor;
|
||||
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
|
||||
|
||||
public class StringEditor extends JTextField {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final PropertyWrapper property;
|
||||
|
||||
public StringEditor(PropertyWrapper property) {
|
||||
super(property.getValue() == null ? "" : (String) property.getValue());
|
||||
this.property = property;
|
||||
getDocument().addDocumentListener(new DocumentListener() {
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
textChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
textChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
textChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void textChanged() {
|
||||
property.setValue(getText());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.diylc.swing.plugins.canvas;
|
||||
|
||||
import java.awt.dnd.DragGestureEvent;
|
||||
import java.awt.dnd.DragGestureListener;
|
||||
|
||||
import org.diylc.common.IPlugInPort;
|
||||
|
||||
/**
|
||||
* {@link DragGestureListener} for {@link CanvasPanel}.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
class CanvasGestureListener implements DragGestureListener {
|
||||
|
||||
private IPlugInPort presenter;
|
||||
|
||||
public CanvasGestureListener(IPlugInPort presenter) {
|
||||
super();
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragGestureRecognized(DragGestureEvent dge) {
|
||||
presenter.dragStarted(dge.getDragOrigin(), dge.getTriggerEvent().isControlDown(), dge
|
||||
.getTriggerEvent().isShiftDown(), dge.getTriggerEvent().isAltDown());
|
||||
dge.startDrag(presenter.getCursorAt(dge.getDragOrigin()), new EmptyTransferable(),
|
||||
new CanvasSourceListener(presenter));
|
||||
}
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
package org.diylc.swing.plugins.canvas;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Image;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.dnd.Autoscroll;
|
||||
import java.awt.dnd.DnDConstants;
|
||||
import java.awt.dnd.DragSource;
|
||||
import java.awt.dnd.DropTarget;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import org.diylc.common.DrawOption;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
import org.diylc.swing.gui.DialogFactory;
|
||||
import org.diylc.swing.gui.editor.PropertyEditorDialog;
|
||||
|
||||
import com.diyfever.gui.ButtonDialog;
|
||||
|
||||
/**
|
||||
* GUI class used to draw onto.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
class CanvasPanel extends JComponent implements Autoscroll {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
private Image bufferImage;
|
||||
private GraphicsConfiguration screenGraphicsConfiguration;
|
||||
|
||||
private static boolean USE_HARDWARE_ACCELLERATION = true;
|
||||
|
||||
static final EnumSet<DrawOption> DRAW_OPTIONS = EnumSet.of(DrawOption.GRID,
|
||||
DrawOption.SELECTION, DrawOption.ZOOM, DrawOption.ANTIALIASING,
|
||||
DrawOption.CONTROL_POINTS);
|
||||
|
||||
public CanvasPanel(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
setFocusable(true);
|
||||
initializeListeners();
|
||||
initializeDnD();
|
||||
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice[] devices = graphicsEnvironment.getScreenDevices();
|
||||
screenGraphicsConfiguration = devices[0].getDefaultConfiguration();
|
||||
|
||||
initializeActions();
|
||||
}
|
||||
|
||||
public void invalidateCache() {
|
||||
bufferImage = null;
|
||||
}
|
||||
|
||||
private void initializeDnD() {
|
||||
// Initialize drag source recognizer.
|
||||
DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(this,
|
||||
DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK, new CanvasGestureListener(plugInPort));
|
||||
// Initialize drop target.
|
||||
new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE,
|
||||
new CanvasTargetListener(plugInPort), true);
|
||||
}
|
||||
|
||||
private void initializeActions() {
|
||||
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "clearSlot");
|
||||
getActionMap().put("clearSlot", new AbstractAction() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
CanvasPanel.this.plugInPort.setNewComponentTypeSlot(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void createBufferImage() {
|
||||
if (USE_HARDWARE_ACCELLERATION) {
|
||||
bufferImage = screenGraphicsConfiguration.createCompatibleVolatileImage(getWidth(),
|
||||
getHeight());
|
||||
((VolatileImage) bufferImage).validate(screenGraphicsConfiguration);
|
||||
} else {
|
||||
bufferImage = createImage(getWidth(), getHeight());
|
||||
}
|
||||
Graphics2D g2d = (Graphics2D) bufferImage.getGraphics();
|
||||
plugInPort.draw(g2d, DRAW_OPTIONS, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
if (plugInPort == null) {
|
||||
return;
|
||||
}
|
||||
if (bufferImage == null) {
|
||||
createBufferImage();
|
||||
} else {
|
||||
Graphics2D g2d = (Graphics2D) bufferImage.getGraphics();
|
||||
plugInPort.draw(g2d, DRAW_OPTIONS, null);
|
||||
}
|
||||
if (USE_HARDWARE_ACCELLERATION) {
|
||||
VolatileImage volatileImage = (VolatileImage) bufferImage;
|
||||
do {
|
||||
try {
|
||||
if (volatileImage.contentsLost()) {
|
||||
createBufferImage();
|
||||
}
|
||||
// int validation = volatileImage.validate(screenGraphicsConfiguration);
|
||||
// if (validation == VolatileImage.IMAGE_INCOMPATIBLE) {
|
||||
// createBufferImage();
|
||||
// }
|
||||
g.drawImage(bufferImage, 0, 0, this);
|
||||
} catch (NullPointerException e) {
|
||||
createBufferImage();
|
||||
}
|
||||
} while (volatileImage == null || volatileImage.contentsLost());
|
||||
} else {
|
||||
g.drawImage(bufferImage, 0, 0, this);
|
||||
bufferImage.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Graphics g) {
|
||||
paint(g);
|
||||
}
|
||||
|
||||
private void initializeListeners() {
|
||||
addComponentListener(new ComponentAdapter() {
|
||||
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
invalidateCache();
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
// addKeyListener(new KeyAdapter() {
|
||||
//
|
||||
// @Override
|
||||
// public void keyPressed(KeyEvent e) {
|
||||
// if (e.getKeyCode() == KeyEvent.VK_DELETE) {
|
||||
// plugInPort.deleteSelectedComponents();
|
||||
// }
|
||||
// // plugInPort.mouseMoved(getMousePosition(), e.isControlDown(),
|
||||
// // e.isShiftDown(), e
|
||||
// // .isAltDown());
|
||||
// }
|
||||
// });
|
||||
addMouseMotionListener(new MouseAdapter() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
setCursor(plugInPort.getCursorAt(e.getPoint()));
|
||||
plugInPort.mouseMoved(e.getPoint(), e.isControlDown(), e.isShiftDown(), e
|
||||
.isAltDown());
|
||||
}
|
||||
});
|
||||
addMouseListener(new MouseAdapter() {
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||
if (e.getClickCount() == 2) {
|
||||
List<PropertyWrapper> properties = plugInPort
|
||||
.getMutualSelectionProperties();
|
||||
if (properties == null || properties.isEmpty()) {
|
||||
// properties = plugInPort.getProjectProperties();
|
||||
// PropertyEditorDialog editor =
|
||||
// DialogFactory.getInstance()
|
||||
// .createPropertyEditorDialog(properties,
|
||||
// "Edit Project");
|
||||
// editor.setVisible(true);
|
||||
// if
|
||||
// (ButtonDialog.OK.equals(editor.getSelectedButtonCaption()))
|
||||
// {
|
||||
// plugInPort.applyPropertiesToProject(properties);
|
||||
// // Save default values.
|
||||
// for (PropertyWrapper property :
|
||||
// editor.getDefaultedProperties()) {
|
||||
// if (property.getValue() != null) {
|
||||
// plugInPort.setProjectDefaultPropertyValue(property.getName(),
|
||||
// property.getValue());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
} else {
|
||||
PropertyEditorDialog editor = DialogFactory.getInstance()
|
||||
.createPropertyEditorDialog(properties, "Edit Selection");
|
||||
editor.setVisible(true);
|
||||
if (ButtonDialog.OK.equals(editor.getSelectedButtonCaption())) {
|
||||
try {
|
||||
plugInPort.applyPropertiesToSelection(properties);
|
||||
} catch (Exception e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
// Save default values.
|
||||
for (PropertyWrapper property : editor.getDefaultedProperties()) {
|
||||
if (property.getValue() != null) {
|
||||
plugInPort.setSelectionDefaultPropertyValue(property.getName(),
|
||||
property.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
plugInPort.mouseClicked(e.getPoint(), e.isControlDown(), e.isShiftDown(), e
|
||||
.isAltDown());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Autoscroll
|
||||
|
||||
@Override
|
||||
public void autoscroll(Point cursorLocn) {
|
||||
scrollRectToVisible(new Rectangle(cursorLocn.x - 15, cursorLocn.y - 15, 30, 30));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getAutoscrollInsets() {
|
||||
Rectangle rect = getVisibleRect();
|
||||
return new Insets(rect.y - 15, rect.x - 15, rect.y + rect.height + 15, rect.x + rect.width
|
||||
+ 15);
|
||||
}
|
||||
}
|
||||
@@ -1,309 +0,0 @@
|
||||
package org.diylc.swing.plugins.canvas;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.ClipboardOwner;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.BadPositionException;
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.IPlugIn;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.presenter.Presenter;
|
||||
import org.diylc.swing.ActionFactory;
|
||||
import org.diylc.swing.ISwingUI;
|
||||
import org.diylc.swing.plugins.edit.ComponentTransferable;
|
||||
import org.diylc.swing.plugins.file.ProjectDrawingProvider;
|
||||
|
||||
import com.diyfever.gui.miscutils.ConfigurationManager;
|
||||
import com.diyfever.gui.ruler.IRulerListener;
|
||||
import com.diyfever.gui.ruler.RulerScrollPane;
|
||||
|
||||
public class CanvasPlugin implements IPlugIn, ClipboardOwner {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(CanvasPlugin.class);
|
||||
|
||||
private static final String WHEEL_ZOOM = "wheelZoom";
|
||||
|
||||
private RulerScrollPane scrollPane;
|
||||
private CanvasPanel canvasPanel;
|
||||
private JPopupMenu popupMenu;
|
||||
|
||||
private ActionFactory.CutAction cutAction;
|
||||
private ActionFactory.CopyAction copyAction;
|
||||
private ActionFactory.PasteAction pasteAction;
|
||||
private ActionFactory.EditSelectionAction editSelectionAction;
|
||||
private ActionFactory.DeleteSelectionAction deleteSelectionAction;
|
||||
private ActionFactory.GroupAction groupAction;
|
||||
private ActionFactory.UngroupAction ungroupAction;
|
||||
private ActionFactory.SendToBackAction sendToBackAction;
|
||||
private ActionFactory.BringToFrontAction bringToFrontAction;
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private ISwingUI swingUI;
|
||||
|
||||
private Clipboard clipboard;
|
||||
|
||||
private double zoomLevel = 1;
|
||||
|
||||
public CanvasPlugin(ISwingUI swingUI) {
|
||||
this.swingUI = swingUI;
|
||||
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(IPlugInPort plugInPort) {
|
||||
this.plugInPort = plugInPort;
|
||||
try {
|
||||
swingUI.injectGUIComponent(getScrollPane(), SwingConstants.CENTER);
|
||||
} catch (BadPositionException e) {
|
||||
LOG.error("Could not install canvas plugin", e);
|
||||
}
|
||||
}
|
||||
|
||||
public CanvasPanel getCanvasPanel() {
|
||||
if (canvasPanel == null) {
|
||||
canvasPanel = new CanvasPanel(plugInPort);
|
||||
canvasPanel.addMouseListener(new MouseAdapter() {
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
// Enable actions.
|
||||
boolean enabled = !plugInPort.getSelectedComponents().isEmpty();
|
||||
getCutAction().setEnabled(enabled);
|
||||
getCopyAction().setEnabled(enabled);
|
||||
try {
|
||||
getPasteAction()
|
||||
.setEnabled(
|
||||
clipboard
|
||||
.isDataFlavorAvailable(ComponentTransferable.listFlavor));
|
||||
} catch (Exception ex) {
|
||||
getPasteAction().setEnabled(false);
|
||||
}
|
||||
getEditSelectionAction().setEnabled(enabled);
|
||||
getDeleteSelectionAction().setEnabled(enabled);
|
||||
getGroupAction().setEnabled(enabled);
|
||||
getUngroupAction().setEnabled(enabled);
|
||||
getSendToBackAction().setEnabled(enabled);
|
||||
getBringToFrontAction().setEnabled(enabled);
|
||||
|
||||
getPopupMenu().show(canvasPanel, e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return canvasPanel;
|
||||
}
|
||||
|
||||
private RulerScrollPane getScrollPane() {
|
||||
if (scrollPane == null) {
|
||||
scrollPane = new RulerScrollPane(getCanvasPanel(), new ProjectDrawingProvider(
|
||||
plugInPort, true), new Size(1d, SizeUnit.cm).convertToPixels(), new Size(1d,
|
||||
SizeUnit.in).convertToPixels());
|
||||
boolean metric = ConfigurationManager.getInstance().readBoolean(Presenter.METRIC_KEY,
|
||||
true);
|
||||
boolean wheelZoom = ConfigurationManager.getInstance().readBoolean(WHEEL_ZOOM, false);
|
||||
scrollPane.setMetric(metric);
|
||||
scrollPane.setWheelScrollingEnabled(!wheelZoom);
|
||||
scrollPane.addUnitListener(new IRulerListener() {
|
||||
|
||||
@Override
|
||||
public void unitsChanged(boolean isMetric) {
|
||||
plugInPort.setMetric(isMetric);
|
||||
}
|
||||
});
|
||||
if (wheelZoom) {
|
||||
scrollPane.addMouseWheelListener(new MouseWheelListener() {
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
double d = plugInPort.getZoomLevel();
|
||||
Double[] availableZoomLevels = plugInPort.getAvailableZoomLevels();
|
||||
if (e.getWheelRotation() > 0) {
|
||||
int i = availableZoomLevels.length - 1;
|
||||
while (i > 0 && availableZoomLevels[i] >= d) {
|
||||
i--;
|
||||
}
|
||||
plugInPort.setZoomLevel(availableZoomLevels[i]);
|
||||
} else {
|
||||
int i = 0;
|
||||
while (i < availableZoomLevels.length - 1
|
||||
&& availableZoomLevels[i] <= d) {
|
||||
i++;
|
||||
}
|
||||
plugInPort.setZoomLevel(availableZoomLevels[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return scrollPane;
|
||||
}
|
||||
|
||||
public JPopupMenu getPopupMenu() {
|
||||
if (popupMenu == null) {
|
||||
popupMenu = new JPopupMenu();
|
||||
popupMenu.add(getCutAction());
|
||||
popupMenu.add(getCopyAction());
|
||||
popupMenu.add(getPasteAction());
|
||||
popupMenu.addSeparator();
|
||||
popupMenu.add(getEditSelectionAction());
|
||||
popupMenu.add(getDeleteSelectionAction());
|
||||
popupMenu.add(getGroupAction());
|
||||
popupMenu.add(getUngroupAction());
|
||||
popupMenu.add(getSendToBackAction());
|
||||
popupMenu.add(getBringToFrontAction());
|
||||
popupMenu.addSeparator();
|
||||
popupMenu.add(ActionFactory.getInstance().createEditProjectAction(plugInPort));
|
||||
}
|
||||
return popupMenu;
|
||||
}
|
||||
|
||||
public ActionFactory.CutAction getCutAction() {
|
||||
if (cutAction == null) {
|
||||
cutAction = ActionFactory.getInstance().createCutAction(plugInPort, clipboard, this);
|
||||
}
|
||||
return cutAction;
|
||||
}
|
||||
|
||||
public ActionFactory.CopyAction getCopyAction() {
|
||||
if (copyAction == null) {
|
||||
copyAction = ActionFactory.getInstance().createCopyAction(plugInPort, clipboard, this);
|
||||
}
|
||||
return copyAction;
|
||||
}
|
||||
|
||||
public ActionFactory.PasteAction getPasteAction() {
|
||||
if (pasteAction == null) {
|
||||
pasteAction = ActionFactory.getInstance().createPasteAction(plugInPort, clipboard);
|
||||
}
|
||||
return pasteAction;
|
||||
}
|
||||
|
||||
public ActionFactory.EditSelectionAction getEditSelectionAction() {
|
||||
if (editSelectionAction == null) {
|
||||
editSelectionAction = ActionFactory.getInstance().createEditSelectionAction(plugInPort);
|
||||
}
|
||||
return editSelectionAction;
|
||||
}
|
||||
|
||||
public ActionFactory.DeleteSelectionAction getDeleteSelectionAction() {
|
||||
if (deleteSelectionAction == null) {
|
||||
deleteSelectionAction = ActionFactory.getInstance().createDeleteSelectionAction(
|
||||
plugInPort);
|
||||
}
|
||||
return deleteSelectionAction;
|
||||
}
|
||||
|
||||
public ActionFactory.GroupAction getGroupAction() {
|
||||
if (groupAction == null) {
|
||||
groupAction = ActionFactory.getInstance().createGroupAction(plugInPort);
|
||||
}
|
||||
return groupAction;
|
||||
}
|
||||
|
||||
public ActionFactory.UngroupAction getUngroupAction() {
|
||||
if (ungroupAction == null) {
|
||||
ungroupAction = ActionFactory.getInstance().createUngroupAction(plugInPort);
|
||||
}
|
||||
return ungroupAction;
|
||||
}
|
||||
|
||||
public ActionFactory.SendToBackAction getSendToBackAction() {
|
||||
if (sendToBackAction == null) {
|
||||
sendToBackAction = ActionFactory.getInstance().createSendToBackAction(plugInPort);
|
||||
}
|
||||
return sendToBackAction;
|
||||
}
|
||||
|
||||
public ActionFactory.BringToFrontAction getBringToFrontAction() {
|
||||
if (bringToFrontAction == null) {
|
||||
bringToFrontAction = ActionFactory.getInstance().createBringToFrontAction(plugInPort);
|
||||
}
|
||||
return bringToFrontAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EventType> getSubscribedEventTypes() {
|
||||
return EnumSet.of(EventType.PROJECT_LOADED, EventType.ZOOM_CHANGED, EventType.REPAINT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessage(final EventType eventType, Object... params) {
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run() {
|
||||
// LOG.debug("event: " + eventType);
|
||||
switch (eventType) {
|
||||
case PROJECT_LOADED:
|
||||
refreshSize();
|
||||
if ((Boolean) params[1]) {
|
||||
// Scroll to the center.
|
||||
Rectangle visibleRect = canvasPanel.getVisibleRect();
|
||||
visibleRect.setLocation((canvasPanel.getWidth() - visibleRect.width) / 2,
|
||||
(canvasPanel.getHeight() - visibleRect.height) / 2);
|
||||
canvasPanel.scrollRectToVisible(visibleRect);
|
||||
canvasPanel.revalidate();
|
||||
}
|
||||
break;
|
||||
case ZOOM_CHANGED:
|
||||
Rectangle visibleRect = canvasPanel.getVisibleRect();
|
||||
refreshSize();
|
||||
// Try to set the visible area to be centered with the previous
|
||||
// one.
|
||||
double zoomFactor = (Double) params[0] / zoomLevel;
|
||||
visibleRect.setBounds((int) (visibleRect.x * zoomFactor),
|
||||
(int) (visibleRect.y * zoomFactor), visibleRect.width, visibleRect.height);
|
||||
canvasPanel.scrollRectToVisible(visibleRect);
|
||||
canvasPanel.revalidate();
|
||||
|
||||
zoomLevel = (Double) params[0];
|
||||
break;
|
||||
case REPAINT:
|
||||
canvasPanel.repaint();
|
||||
break;
|
||||
}
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
private void refreshSize() {
|
||||
Dimension d = plugInPort.getCanvasDimensions(true);
|
||||
canvasPanel.setSize(d);
|
||||
canvasPanel.setPreferredSize(d);
|
||||
getScrollPane().setZoomLevel(plugInPort.getZoomLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes ruler scroll pane to refresh by sending a fake mouse moved message
|
||||
* to the canvasPanel.
|
||||
*/
|
||||
public void refresh() {
|
||||
MouseEvent event = new MouseEvent(canvasPanel, MouseEvent.MOUSE_MOVED, System
|
||||
.currentTimeMillis(), 0, 1, 1,// canvasPanel.getWidth() / 2,
|
||||
// canvasPanel.getHeight() / 2,
|
||||
0, false);
|
||||
canvasPanel.dispatchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package org.diylc.swing.plugins.canvas;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.dnd.DragSourceDragEvent;
|
||||
import java.awt.dnd.DragSourceDropEvent;
|
||||
import java.awt.dnd.DragSourceEvent;
|
||||
import java.awt.dnd.DragSourceListener;
|
||||
|
||||
import org.diylc.common.IPlugInPort;
|
||||
|
||||
|
||||
/**
|
||||
* {@link DragSourceListener} for {@link CanvasPanel}.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
class CanvasSourceListener implements DragSourceListener {
|
||||
|
||||
private IPlugInPort presenter;
|
||||
|
||||
public CanvasSourceListener(IPlugInPort presenter) {
|
||||
super();
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragDropEnd(DragSourceDropEvent dsde) {
|
||||
// presenter.dragEnded(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragEnter(DragSourceDragEvent dsde) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragExit(DragSourceEvent dse) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragOver(DragSourceDragEvent dsde) {
|
||||
Point p = dsde.getDragSourceContext().getComponent().getMousePosition();
|
||||
if (p != null) {
|
||||
dsde.getDragSourceContext().getComponent().firePropertyChange("dragPoint", p.x, p.y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropActionChanged(DragSourceDragEvent dsde) {
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package org.diylc.swing.plugins.canvas;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.dnd.DnDConstants;
|
||||
import java.awt.dnd.DropTargetDragEvent;
|
||||
import java.awt.dnd.DropTargetDropEvent;
|
||||
import java.awt.dnd.DropTargetEvent;
|
||||
import java.awt.dnd.DropTargetListener;
|
||||
|
||||
import org.diylc.common.IPlugInPort;
|
||||
|
||||
|
||||
/**
|
||||
* {@link DropTargetListener} for {@link CanvasPanel}.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
class CanvasTargetListener implements DropTargetListener {
|
||||
|
||||
private IPlugInPort presenter;
|
||||
|
||||
// Cached values
|
||||
private Point currentPoint = null;
|
||||
private boolean lastAccept;
|
||||
|
||||
public CanvasTargetListener(IPlugInPort presenter) {
|
||||
super();
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragEnter(DropTargetDragEvent dtde) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragExit(DropTargetEvent dte) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragOver(DropTargetDragEvent dtde) {
|
||||
// If dragOver was previously called for this location use cached value.
|
||||
if (dtde.getLocation().equals(currentPoint)) {
|
||||
if (lastAccept) {
|
||||
dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
|
||||
} else {
|
||||
dtde.rejectDrag();
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Transferable t = dtde.getTransferable();
|
||||
// if
|
||||
// (t.isDataFlavorSupported(SelectionTransferable.selectionFlavor))
|
||||
// {
|
||||
// if (currentPoint != null) {
|
||||
// List<IDIYComponent> selection = (List<IDIYComponent>) t
|
||||
// .getTransferData(SelectionTransferable.selectionFlavor);
|
||||
// Point startPoint = (Point) t
|
||||
// .getTransferData(PointTransferable.pointFlavor);
|
||||
// presenter.selectionMoved(dtde.getLocation().x
|
||||
// - currentPoint.x, dtde.getLocation().y
|
||||
// - currentPoint.y);
|
||||
// }
|
||||
// } else if
|
||||
// (t.isDataFlavorSupported(PointTransferable.pointFlavor)) {
|
||||
// Point startPoint = (Point) t
|
||||
// .getTransferData(PointTransferable.pointFlavor);
|
||||
// Point endPoint = dtde.getLocation();
|
||||
// presenter.setSelectionRect(Utils.createRectangle(startPoint,
|
||||
// endPoint));
|
||||
// }
|
||||
currentPoint = dtde.getLocation();
|
||||
if (presenter.dragOver(currentPoint)) {
|
||||
dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
|
||||
lastAccept = true;
|
||||
} else {
|
||||
dtde.rejectDrag();
|
||||
lastAccept = false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
dtde.rejectDrag();
|
||||
lastAccept = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drop(DropTargetDropEvent dtde) {
|
||||
presenter.dragEnded(dtde.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropActionChanged(DropTargetDragEvent dtde) {
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.diylc.swing.plugins.canvas;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.io.IOException;
|
||||
|
||||
public class EmptyTransferable implements Transferable {
|
||||
|
||||
@Override
|
||||
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
return new DataFlavor[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.diylc.swing.plugins.canvas;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PointTransferable implements Transferable {
|
||||
|
||||
public static final DataFlavor pointFlavor = new DataFlavor(Point.class, "Java Point");
|
||||
|
||||
private Point startPoint;
|
||||
|
||||
public PointTransferable(Point startPoint) {
|
||||
super();
|
||||
this.startPoint = startPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
|
||||
if (flavor.equals(pointFlavor)) {
|
||||
return startPoint;
|
||||
}
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
return new DataFlavor[] { pointFlavor };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
return flavor.equals(pointFlavor);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package org.diylc.swing.plugins.canvas;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
|
||||
public class SelectionTransferable implements Transferable {
|
||||
|
||||
public static final DataFlavor selectionFlavor = new DataFlavor(List.class,
|
||||
"Component Selection");
|
||||
|
||||
private Point startPoint;
|
||||
private List<IDIYComponent<?>> selection;
|
||||
|
||||
public SelectionTransferable(List<IDIYComponent<?>> selection, Point startPoint) {
|
||||
super();
|
||||
this.selection = selection;
|
||||
this.startPoint = startPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
|
||||
if (flavor.equals(selectionFlavor)) {
|
||||
return selection;
|
||||
}
|
||||
if (flavor.equals(PointTransferable.pointFlavor)) {
|
||||
return startPoint;
|
||||
}
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
return new DataFlavor[] { selectionFlavor, PointTransferable.pointFlavor };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
return flavor.equals(selectionFlavor) || flavor.equals(selectionFlavor);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.diylc.swing.plugins.edit;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/**
|
||||
* Represents component selection as a {@link List} of {@link IDIYComponent}
|
||||
* objects. Implements {@link Transferable}, so it is suitable for clipboard
|
||||
* usage.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ComponentTransferable extends ArrayList<IDIYComponent<?>> implements Transferable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final DataFlavor listFlavor = new DataFlavor(ComponentTransferable.class, "application/diylc");
|
||||
|
||||
public ComponentTransferable() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ComponentTransferable(Collection<IDIYComponent<?>> selectedComponents) {
|
||||
super(selectedComponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
|
||||
if (flavor.equals(listFlavor)) {
|
||||
return this;
|
||||
}
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
return new DataFlavor[] { listFlavor };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
return flavor.equals(listFlavor);
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
package org.diylc.swing.plugins.edit;
|
||||
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.ClipboardOwner;
|
||||
import java.awt.datatransfer.FlavorEvent;
|
||||
import java.awt.datatransfer.FlavorListener;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.IPlugIn;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.swing.ActionFactory;
|
||||
import org.diylc.swing.ISwingUI;
|
||||
|
||||
import com.diyfever.gui.undo.IUndoListener;
|
||||
import com.diyfever.gui.undo.UndoHandler;
|
||||
|
||||
public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
|
||||
|
||||
private static final String EDIT_TITLE = "Edit";
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private ISwingUI swingUI;
|
||||
|
||||
private Clipboard clipboard;
|
||||
|
||||
private ActionFactory.CutAction cutAction;
|
||||
private ActionFactory.CopyAction copyAction;
|
||||
private ActionFactory.PasteAction pasteAction;
|
||||
private ActionFactory.EditSelectionAction editSelectionAction;
|
||||
private ActionFactory.DeleteSelectionAction deleteSelectionAction;
|
||||
private ActionFactory.GroupAction groupAction;
|
||||
private ActionFactory.UngroupAction ungroupAction;
|
||||
private ActionFactory.SendToBackAction sendToBackAction;
|
||||
private ActionFactory.BringToFrontAction bringToFrontAction;
|
||||
|
||||
private UndoHandler<Project> undoHandler;
|
||||
|
||||
public EditMenuPlugin(ISwingUI swingUI) {
|
||||
this.swingUI = swingUI;
|
||||
// SecurityManager securityManager = System.getSecurityManager();
|
||||
// if (securityManager != null) {
|
||||
// try {
|
||||
// securityManager.checkSystemClipboardAccess();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
undoHandler = new UndoHandler<Project>(new IUndoListener<Project>() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(Project currentState) {
|
||||
plugInPort.loadProject(currentState, false);
|
||||
}
|
||||
});
|
||||
clipboard.addFlavorListener(new FlavorListener() {
|
||||
|
||||
@Override
|
||||
public void flavorsChanged(FlavorEvent e) {
|
||||
refreshActions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ActionFactory.CutAction getCutAction() {
|
||||
if (cutAction == null) {
|
||||
cutAction = ActionFactory.getInstance().createCutAction(plugInPort, clipboard, this);
|
||||
}
|
||||
return cutAction;
|
||||
}
|
||||
|
||||
public ActionFactory.CopyAction getCopyAction() {
|
||||
if (copyAction == null) {
|
||||
copyAction = ActionFactory.getInstance().createCopyAction(plugInPort, clipboard, this);
|
||||
}
|
||||
return copyAction;
|
||||
}
|
||||
|
||||
public ActionFactory.PasteAction getPasteAction() {
|
||||
if (pasteAction == null) {
|
||||
pasteAction = ActionFactory.getInstance().createPasteAction(plugInPort, clipboard);
|
||||
}
|
||||
return pasteAction;
|
||||
}
|
||||
|
||||
public ActionFactory.EditSelectionAction getEditSelectionAction() {
|
||||
if (editSelectionAction == null) {
|
||||
editSelectionAction = ActionFactory.getInstance().createEditSelectionAction(plugInPort);
|
||||
}
|
||||
return editSelectionAction;
|
||||
}
|
||||
|
||||
public ActionFactory.DeleteSelectionAction getDeleteSelectionAction() {
|
||||
if (deleteSelectionAction == null) {
|
||||
deleteSelectionAction = ActionFactory.getInstance().createDeleteSelectionAction(
|
||||
plugInPort);
|
||||
}
|
||||
return deleteSelectionAction;
|
||||
}
|
||||
|
||||
public ActionFactory.GroupAction getGroupAction() {
|
||||
if (groupAction == null) {
|
||||
groupAction = ActionFactory.getInstance().createGroupAction(plugInPort);
|
||||
}
|
||||
return groupAction;
|
||||
}
|
||||
|
||||
public ActionFactory.UngroupAction getUngroupAction() {
|
||||
if (ungroupAction == null) {
|
||||
ungroupAction = ActionFactory.getInstance().createUngroupAction(plugInPort);
|
||||
}
|
||||
return ungroupAction;
|
||||
}
|
||||
|
||||
public ActionFactory.SendToBackAction getSendToBackAction() {
|
||||
if (sendToBackAction == null) {
|
||||
sendToBackAction = ActionFactory.getInstance().createSendToBackAction(plugInPort);
|
||||
}
|
||||
return sendToBackAction;
|
||||
}
|
||||
|
||||
public ActionFactory.BringToFrontAction getBringToFrontAction() {
|
||||
if (bringToFrontAction == null) {
|
||||
bringToFrontAction = ActionFactory.getInstance().createBringToFrontAction(plugInPort);
|
||||
}
|
||||
return bringToFrontAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(IPlugInPort plugInPort) {
|
||||
this.plugInPort = plugInPort;
|
||||
|
||||
ActionFactory actionFactory = ActionFactory.getInstance();
|
||||
|
||||
swingUI.injectMenuAction(undoHandler.getUndoAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(undoHandler.getRedoAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(null, EDIT_TITLE);
|
||||
swingUI.injectMenuAction(getCutAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(getCopyAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(getPasteAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(null, EDIT_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createSelectAllAction(plugInPort), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(getEditSelectionAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(getDeleteSelectionAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(getGroupAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(getUngroupAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(getSendToBackAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(getBringToFrontAction(), EDIT_TITLE);
|
||||
swingUI.injectMenuAction(null, EDIT_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createEditProjectAction(plugInPort), EDIT_TITLE);
|
||||
|
||||
refreshActions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EventType> getSubscribedEventTypes() {
|
||||
return EnumSet.of(EventType.SELECTION_CHANGED, EventType.PROJECT_MODIFIED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessage(EventType eventType, Object... params) {
|
||||
switch (eventType) {
|
||||
case SELECTION_CHANGED:
|
||||
refreshActions();
|
||||
break;
|
||||
case PROJECT_MODIFIED:
|
||||
undoHandler.stateChanged((Project) params[0], (Project) params[1], (String) params[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshActions() {
|
||||
boolean enabled = !plugInPort.getSelectedComponents().isEmpty();
|
||||
getCutAction().setEnabled(enabled);
|
||||
getCopyAction().setEnabled(enabled);
|
||||
try {
|
||||
getPasteAction().setEnabled(
|
||||
clipboard.isDataFlavorAvailable(ComponentTransferable.listFlavor));
|
||||
} catch (Exception e) {
|
||||
getPasteAction().setEnabled(false);
|
||||
}
|
||||
getEditSelectionAction().setEnabled(enabled);
|
||||
getDeleteSelectionAction().setEnabled(enabled);
|
||||
getGroupAction().setEnabled(enabled);
|
||||
getUngroupAction().setEnabled(enabled);
|
||||
getSendToBackAction().setEnabled(enabled);
|
||||
getBringToFrontAction().setEnabled(enabled);
|
||||
}
|
||||
|
||||
// ClipboardOwner
|
||||
|
||||
@Override
|
||||
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
||||
refreshActions();
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
package org.diylc.swing.plugins.file;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import org.diylc.images.IconLoader;
|
||||
import org.diylc.swing.gui.DialogFactory;
|
||||
|
||||
import com.diyfever.gui.export.TableExporter;
|
||||
import com.diyfever.gui.objecttable.ObjectListTable;
|
||||
|
||||
public class BomDialog extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ObjectListTable<BomEntry> table;
|
||||
private JPanel toolbar;
|
||||
|
||||
public BomDialog(JFrame parent, List<BomEntry> bom) {
|
||||
super(parent, "Bill of Materials");
|
||||
setContentPane(createMainPanel());
|
||||
getTable().setData(bom);
|
||||
pack();
|
||||
setLocationRelativeTo(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b) {
|
||||
super.setVisible(b);
|
||||
if (b) {
|
||||
getTable().autoFit(Arrays.asList(3));
|
||||
}
|
||||
}
|
||||
|
||||
private JPanel createMainPanel() {
|
||||
JPanel mainPanel = new JPanel();
|
||||
mainPanel.setLayout(new BorderLayout());
|
||||
mainPanel.add(getToolbar(), BorderLayout.NORTH);
|
||||
mainPanel.add(new JScrollPane(getTable()), BorderLayout.CENTER);
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
private ObjectListTable<BomEntry> getTable() {
|
||||
if (table == null) {
|
||||
try {
|
||||
table = new ObjectListTable<BomEntry>(BomEntry.class, new String[] { "getName",
|
||||
"getValue", "getQuantity", "getNotes/setNotes" }, null);
|
||||
} catch (SecurityException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
private JPanel getToolbar() {
|
||||
if (toolbar == null) {
|
||||
toolbar = new JPanel();
|
||||
toolbar.add(new JButton(new SaveToExcelAction()));
|
||||
toolbar.add(new JButton(new SaveToCSVAction()));
|
||||
toolbar.add(new JButton(new SaveToPNGAction()));
|
||||
toolbar.add(new JButton(new SaveToHTMLAction()));
|
||||
}
|
||||
return toolbar;
|
||||
}
|
||||
|
||||
class SaveToExcelAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SaveToExcelAction() {
|
||||
super();
|
||||
putValue(Action.NAME, "Save to Excel");
|
||||
putValue(Action.SMALL_ICON, IconLoader.Excel.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
File file = DialogFactory.getInstance().showSaveDialog(
|
||||
FileFilterEnum.EXCEL.getFilter(), null,
|
||||
FileFilterEnum.EXCEL.getExtensions()[0], null);
|
||||
if (file != null) {
|
||||
try {
|
||||
TableExporter.getInstance().exportToExcel(getTable(), file);
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SaveToCSVAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SaveToCSVAction() {
|
||||
super();
|
||||
putValue(Action.NAME, "Save to CSV");
|
||||
putValue(Action.SMALL_ICON, IconLoader.CSV.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
File file = DialogFactory.getInstance().showSaveDialog(FileFilterEnum.CSV.getFilter(),
|
||||
null, FileFilterEnum.CSV.getExtensions()[0], null);
|
||||
if (file != null) {
|
||||
try {
|
||||
TableExporter.getInstance().exportToCSV(getTable(), file);
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SaveToHTMLAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SaveToHTMLAction() {
|
||||
super();
|
||||
putValue(Action.NAME, "Save to HTML");
|
||||
putValue(Action.SMALL_ICON, IconLoader.HTML.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
File file = DialogFactory.getInstance().showSaveDialog(FileFilterEnum.HTML.getFilter(),
|
||||
null, FileFilterEnum.HTML.getExtensions()[0], null);
|
||||
if (file != null) {
|
||||
try {
|
||||
TableExporter.getInstance().exportToHTML(getTable(), file);
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SaveToPNGAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SaveToPNGAction() {
|
||||
super();
|
||||
putValue(Action.NAME, "Save to PNG");
|
||||
putValue(Action.SMALL_ICON, IconLoader.Image.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
File file = DialogFactory.getInstance().showSaveDialog(FileFilterEnum.PNG.getFilter(),
|
||||
null, FileFilterEnum.PNG.getExtensions()[0], null);
|
||||
if (file != null) {
|
||||
try {
|
||||
TableExporter.getInstance().exportToPNG(getTable(), file);
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package org.diylc.swing.plugins.file;
|
||||
|
||||
public class BomEntry {
|
||||
|
||||
private String name;
|
||||
private String value;
|
||||
private Integer quantity;
|
||||
private String notes;
|
||||
|
||||
public BomEntry(String name, String value, int quantity) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Integer getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(Integer quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void setNotes(String notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((notes == null) ? 0 : notes.hashCode());
|
||||
result = prime * result + quantity;
|
||||
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
BomEntry other = (BomEntry) obj;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (notes == null) {
|
||||
if (other.notes != null)
|
||||
return false;
|
||||
} else if (!notes.equals(other.notes))
|
||||
return false;
|
||||
if (quantity != other.quantity)
|
||||
return false;
|
||||
if (value == null) {
|
||||
if (other.value != null)
|
||||
return false;
|
||||
} else if (!value.equals(other.value))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package org.diylc.swing.plugins.file;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public class BomMaker {
|
||||
|
||||
private static BomMaker instance;
|
||||
|
||||
public static BomMaker getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new BomMaker();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private BomMaker() {
|
||||
}
|
||||
|
||||
public List<BomEntry> createBom(List<IDIYComponent<?>> components) {
|
||||
Map<String, BomEntry> entryMap = new HashMap<String, BomEntry>();
|
||||
for (IDIYComponent<?> component : components) {
|
||||
String name = component.getName();
|
||||
String value = component.getValue() == null ? null : component.getValue().toString();
|
||||
if ((name != null) && (value != null)) {
|
||||
String key = name + "|" + value;
|
||||
if (entryMap.containsKey(key)) {
|
||||
BomEntry entry = entryMap.get(key);
|
||||
entry.setQuantity(entry.getQuantity() + 1);
|
||||
} else {
|
||||
entryMap.put(key, new BomEntry(name, value, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
List<BomEntry> bom = new ArrayList<BomEntry>(entryMap.values());
|
||||
Collections.sort(bom, new Comparator<BomEntry>() {
|
||||
|
||||
@Override
|
||||
public int compare(BomEntry o1, BomEntry o2) {
|
||||
int compare = o1.getName().compareToIgnoreCase(o2.getName());
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
return o1.getValue().compareToIgnoreCase(o2.getValue());
|
||||
}
|
||||
});
|
||||
return bom;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package org.diylc.swing.plugins.file;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
public enum FileFilterEnum {
|
||||
|
||||
PNG("PNG Images (*.png)", "png"), PDF("PDF Files (*.pdf)", "pdf"), DIY(
|
||||
"DIY Project Files (*.diy)", "diy"), EXCEL("Excel Workbooks (*.xls)", "xls"), CSV(
|
||||
"Comma Separated Files (*.csv)", "csv"), HTML("HTML Files (*.html)", "html"), IMAGES(
|
||||
"Image Files (*.png, *.jpg, *.gif)", "png", "jpg", "gif");
|
||||
|
||||
FileFilter filter;
|
||||
String[] extensions;
|
||||
|
||||
private FileFilterEnum(final String description, final String... extensions) {
|
||||
this.extensions = extensions;
|
||||
filter = new FileFilter() {
|
||||
|
||||
@Override
|
||||
public boolean accept(File f) {
|
||||
if (f.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
String fileExt = f.getName();
|
||||
fileExt = fileExt.substring(fileExt.lastIndexOf('.') + 1).toLowerCase();
|
||||
for (String ext : extensions) {
|
||||
if (ext.equals(fileExt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public FileFilter getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
public String[] getExtensions() {
|
||||
return extensions;
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package org.diylc.swing.plugins.file;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.IPlugIn;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.images.IconLoader;
|
||||
import org.diylc.swing.ActionFactory;
|
||||
import org.diylc.swing.ISwingUI;
|
||||
|
||||
/**
|
||||
* Entry point class for File management utilities.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class FileMenuPlugin implements IPlugIn {
|
||||
|
||||
private static final String FILE_TITLE = "File";
|
||||
private static final String TRACE_MASK_TITLE = "Trace Mask";
|
||||
|
||||
private ProjectDrawingProvider drawingProvider;
|
||||
private TraceMaskDrawingProvider traceMaskDrawingProvider;
|
||||
|
||||
private ISwingUI swingUI;
|
||||
|
||||
public FileMenuPlugin(ISwingUI swingUI) {
|
||||
super();
|
||||
this.swingUI = swingUI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(IPlugInPort plugInPort) {
|
||||
this.drawingProvider = new ProjectDrawingProvider(plugInPort, false);
|
||||
this.traceMaskDrawingProvider = new TraceMaskDrawingProvider(plugInPort);
|
||||
|
||||
ActionFactory actionFactory = ActionFactory.getInstance();
|
||||
swingUI.injectMenuAction(actionFactory.createNewAction(plugInPort), FILE_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createOpenAction(plugInPort, swingUI), FILE_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createSaveAction(plugInPort, swingUI), FILE_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createSaveAsAction(plugInPort, swingUI), FILE_TITLE);
|
||||
swingUI.injectMenuAction(null, FILE_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createExportPDFAction(drawingProvider, swingUI),
|
||||
FILE_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createExportPNGAction(drawingProvider, swingUI),
|
||||
FILE_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createPrintAction(drawingProvider), FILE_TITLE);
|
||||
swingUI.injectSubmenu(TRACE_MASK_TITLE, IconLoader.TraceMask.getIcon(), FILE_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createExportPDFAction(traceMaskDrawingProvider,
|
||||
swingUI), TRACE_MASK_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createExportPNGAction(traceMaskDrawingProvider,
|
||||
swingUI), TRACE_MASK_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createPrintAction(traceMaskDrawingProvider),
|
||||
TRACE_MASK_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createBomAction(plugInPort), FILE_TITLE);
|
||||
swingUI.injectMenuAction(null, FILE_TITLE);
|
||||
swingUI.injectMenuAction(actionFactory.createExitAction(plugInPort), FILE_TITLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EventType> getSubscribedEventTypes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessage(EventType eventType, Object... params) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.diylc.swing.plugins.file;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.diylc.common.DrawOption;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
|
||||
import com.diyfever.gui.IDrawingProvider;
|
||||
|
||||
/**
|
||||
* {@link IDrawingProvider} implementation that uses {@link IPlugInPort} to draw
|
||||
* a project onto the canvas.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ProjectDrawingProvider implements IDrawingProvider {
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private boolean useZoom;
|
||||
|
||||
public ProjectDrawingProvider(IPlugInPort plugInPort, boolean useZoom) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
this.useZoom = useZoom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics g) {
|
||||
EnumSet<DrawOption> options = EnumSet.of(DrawOption.ANTIALIASING);
|
||||
if (useZoom) {
|
||||
options.add(DrawOption.ZOOM);
|
||||
}
|
||||
plugInPort.draw((Graphics2D) g, options, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getSize() {
|
||||
return plugInPort.getCanvasDimensions(useZoom);
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
package org.diylc.swing.plugins.file;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.diylc.common.DrawOption;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.core.IView;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.presenter.Presenter;
|
||||
|
||||
import com.diyfever.gui.IFileChooserAccessory;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.io.xml.DomDriver;
|
||||
|
||||
/**
|
||||
* {@link JComponent} that shows preview of the selected project in
|
||||
* {@link JFileChooser}. It's hooked onto {@link JFileChooser} as
|
||||
* {@link PropertyChangeListener} and refreshes when file is selected.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ProjectPreview extends JPanel implements PropertyChangeListener, IFileChooserAccessory {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IPlugInPort presenter;
|
||||
private XStream xStream;
|
||||
private Project emptyProject;
|
||||
private RenderComponent renderComponent;
|
||||
private JLabel nameLabel;
|
||||
|
||||
public ProjectPreview() {
|
||||
super();
|
||||
|
||||
setPreferredSize(new Dimension(140, 128));
|
||||
presenter = new Presenter(new IView() {
|
||||
|
||||
@Override
|
||||
public int showConfirmDialog(String message, String title, int optionType,
|
||||
int messageType) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(String message, String title, int messageType) {
|
||||
}
|
||||
});
|
||||
xStream = new XStream(new DomDriver());
|
||||
|
||||
emptyProject = new Project();
|
||||
emptyProject.setTitle("");
|
||||
|
||||
renderComponent = new RenderComponent();
|
||||
nameLabel = new JLabel();
|
||||
|
||||
// setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
add(renderComponent);
|
||||
add(nameLabel);
|
||||
}
|
||||
|
||||
// PropertyChangeListener
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
boolean update = false;
|
||||
String prop = evt.getPropertyName();
|
||||
|
||||
Project selectedProject = emptyProject;
|
||||
if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) {
|
||||
update = true;
|
||||
} else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) {
|
||||
File selectedFile = (File) evt.getNewValue();
|
||||
try {
|
||||
FileInputStream in = new FileInputStream(selectedFile);
|
||||
selectedProject = (Project) xStream.fromXML(in);
|
||||
in.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
update = true;
|
||||
}
|
||||
|
||||
nameLabel.setText(selectedProject.getTitle());
|
||||
presenter.loadProject(selectedProject, true);
|
||||
|
||||
if (update) {
|
||||
if (renderComponent.isShowing()) {
|
||||
renderComponent.repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RenderComponent extends JComponent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RenderComponent() {
|
||||
setPreferredSize(new Dimension(128, 96));
|
||||
// setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
Dimension d = presenter.getCanvasDimensions(false);
|
||||
// System.out.println(d);
|
||||
Rectangle rect = getBounds();
|
||||
// System.out.println(rect);
|
||||
|
||||
double projectRatio = d.getWidth() / d.getHeight();
|
||||
double actualRatio = rect.getWidth() / rect.getHeight();
|
||||
double zoomRatio;
|
||||
if (projectRatio > actualRatio) {
|
||||
zoomRatio = rect.getWidth() / d.getWidth();
|
||||
} else {
|
||||
zoomRatio = rect.getHeight() / d.getHeight();
|
||||
}
|
||||
// d.setSize(d.getWidth() * zoomRatio, d.getHeight() * zoomRatio);
|
||||
// int x = (int) (rect.getWidth() - d.getWidth() * zoomRatio) / 2;
|
||||
// int y = (int) (rect.getHeight() - d.getHeight() * zoomRatio) / 2;
|
||||
|
||||
// System.out.println(x + "," + y);
|
||||
|
||||
// g2d.translate(x, y);
|
||||
g2d.scale(zoomRatio, zoomRatio);
|
||||
presenter.draw(g2d, EnumSet.noneOf(DrawOption.class), null);
|
||||
|
||||
g2d.setColor(Color.black);
|
||||
g2d.drawRect(0, 0, d.width - (int) (1 / zoomRatio), d.height - (int) (1 / zoomRatio));
|
||||
}
|
||||
}
|
||||
|
||||
// IFileChooserAccessory
|
||||
|
||||
@Override
|
||||
public void install(JFileChooser fileChooser) {
|
||||
fileChooser.setAccessory(this);
|
||||
fileChooser.addPropertyChangeListener(this);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.diylc.swing.plugins.file;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.diylc.common.DrawOption;
|
||||
import org.diylc.common.IComponentFiler;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.presenter.ComponentZOrderFiler;
|
||||
|
||||
import com.diyfever.gui.IDrawingProvider;
|
||||
|
||||
/**
|
||||
* {@link IDrawingProvider} implementation that uses {@link IPlugInPort} to draw
|
||||
* a project onto the canvas.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class TraceMaskDrawingProvider implements IDrawingProvider {
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private IComponentFiler filter;
|
||||
|
||||
public TraceMaskDrawingProvider(IPlugInPort plugInPort) {
|
||||
super();
|
||||
this.plugInPort = plugInPort;
|
||||
this.filter = new ComponentZOrderFiler(IDIYComponent.TRACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics g) {
|
||||
plugInPort.draw((Graphics2D) g, EnumSet.of(DrawOption.ANTIALIASING),
|
||||
this.filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getSize() {
|
||||
return plugInPort.getCanvasDimensions(false);
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package org.diylc.swing.plugins.help;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Icon;
|
||||
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.IPlugIn;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.images.IconLoader;
|
||||
import org.diylc.swing.ISwingUI;
|
||||
import org.diylc.swing.gui.DialogFactory;
|
||||
|
||||
import com.diyfever.gui.AboutDialog;
|
||||
import com.diyfever.gui.miscutils.Utils;
|
||||
|
||||
/**
|
||||
* Entry point class for help-related utilities.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class HelpMenuPlugin implements IPlugIn {
|
||||
|
||||
private static final String HELP_TITLE = "Help";
|
||||
|
||||
public static String MANUAL_URL = "http://code.google.com/p/diy-layout-creator/wiki/Manual";
|
||||
public static String FAQ_URL = "http://code.google.com/p/diy-layout-creator/wiki/FAQ";
|
||||
public static String COMPONENT_URL = "http://code.google.com/p/diy-layout-creator/wiki/ComponentAPI";
|
||||
public static String PLUGIN_URL = "http://code.google.com/p/diy-layout-creator/wiki/PluginAPI";
|
||||
public static String BUG_URL = "http://code.google.com/p/diy-layout-creator/issues/entry";
|
||||
public static String DONATE_URL = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=25161";
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private AboutDialog aboutDialog;
|
||||
|
||||
public HelpMenuPlugin(ISwingUI swingUI) {
|
||||
swingUI.injectMenuAction(new NavigateURLAction("User Manual", IconLoader.Manual.getIcon(),
|
||||
MANUAL_URL), HELP_TITLE);
|
||||
swingUI.injectMenuAction(new NavigateURLAction("FAQ", IconLoader.Faq.getIcon(), FAQ_URL),
|
||||
HELP_TITLE);
|
||||
swingUI.injectMenuAction(new NavigateURLAction("Component API", IconLoader.Component
|
||||
.getIcon(), COMPONENT_URL), HELP_TITLE);
|
||||
swingUI.injectMenuAction(new NavigateURLAction("Plugin API", IconLoader.Plugin.getIcon(),
|
||||
PLUGIN_URL), HELP_TITLE);
|
||||
swingUI.injectMenuAction(new NavigateURLAction("Submit a Bug", IconLoader.Bug.getIcon(),
|
||||
BUG_URL), HELP_TITLE);
|
||||
swingUI.injectMenuAction(null, HELP_TITLE);
|
||||
swingUI.injectMenuAction(new NavigateURLAction("Donate", IconLoader.Donate.getIcon(),
|
||||
DONATE_URL), HELP_TITLE);
|
||||
swingUI.injectMenuAction(new AboutAction(), HELP_TITLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(IPlugInPort plugInPort) {
|
||||
this.plugInPort = plugInPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EventType> getSubscribedEventTypes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessage(EventType eventType, Object... params) {
|
||||
}
|
||||
|
||||
private AboutDialog getAboutDialog() {
|
||||
if (aboutDialog == null) {
|
||||
aboutDialog = DialogFactory.getInstance().createAboutDialog("DIY Layout Creator",
|
||||
IconLoader.IconLarge.getIcon(),
|
||||
plugInPort.getCurrentVersionNumber().toString(), "Branislav Stojkovic",
|
||||
"diylc.org", "bancika@gmail.com", "");
|
||||
}
|
||||
return aboutDialog;
|
||||
}
|
||||
|
||||
class AboutAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public AboutAction() {
|
||||
super();
|
||||
putValue(AbstractAction.NAME, "About");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.About.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
getAboutDialog().setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
class NavigateURLAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String url;
|
||||
|
||||
public NavigateURLAction(String name, Icon icon, String url) {
|
||||
super();
|
||||
this.url = url;
|
||||
putValue(AbstractAction.NAME, name);
|
||||
putValue(AbstractAction.SMALL_ICON, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Utils.openURL(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package org.diylc.swing.plugins.layers;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.IPlugIn;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.swing.ISwingUI;
|
||||
|
||||
public class LayersMenuPlugin implements IPlugIn {
|
||||
|
||||
private static final String LOCK_LAYERS_TITLE = "Lock Layers";
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private Map<Layer, Action> lockActionMap;
|
||||
|
||||
public LayersMenuPlugin(ISwingUI swingUI) {
|
||||
lockActionMap = new HashMap<Layer, Action>();
|
||||
for (Layer layer : Layer.values()) {
|
||||
final int zOrder = layer.getZOrder();
|
||||
AbstractAction action = new AbstractAction(layer.getTitle()) {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LayersMenuPlugin.this.plugInPort.setLayerLocked(zOrder,
|
||||
(Boolean) getValue(Action.SELECTED_KEY));
|
||||
}
|
||||
};
|
||||
action.putValue(IPlugInPort.CHECK_BOX_MENU_ITEM, true);
|
||||
lockActionMap.put(layer, action);
|
||||
swingUI.injectMenuAction(action, LOCK_LAYERS_TITLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(IPlugInPort plugInPort) {
|
||||
this.plugInPort = plugInPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EventType> getSubscribedEventTypes() {
|
||||
return EnumSet.of(EventType.LAYER_STATE_CHANGED);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void processMessage(EventType eventType, Object... params) {
|
||||
if (eventType == EventType.LAYER_STATE_CHANGED) {
|
||||
Set<Integer> lockedLayers = (Set<Integer>) params[0];
|
||||
for (Layer layer : Layer.values()) {
|
||||
lockActionMap.get(layer).putValue(Action.SELECTED_KEY,
|
||||
lockedLayers.contains(layer.getZOrder()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static enum Layer {
|
||||
CHASSIS("Chassis", IDIYComponent.CHASSIS), BOARD("Board", IDIYComponent.BOARD), TRACE(
|
||||
"Trace", IDIYComponent.TRACE), COMPONENT("Component", IDIYComponent.COMPONENT), TEXT(
|
||||
"Text", IDIYComponent.TEXT);
|
||||
|
||||
String title;
|
||||
int zOrder;
|
||||
|
||||
private Layer(String title, int order) {
|
||||
this.title = title;
|
||||
zOrder = order;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public int getZOrder() {
|
||||
return zOrder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
package org.diylc.swing.plugins.online;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import org.diylc.common.EventType;
|
||||
import org.diylc.common.IPlugIn;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.images.IconLoader;
|
||||
import org.diylc.swing.gui.DialogFactory;
|
||||
import org.diylc.swing.plugins.online.presenter.LibraryPresenter;
|
||||
import org.diylc.swing.plugins.online.view.LoginDialog;
|
||||
import org.diylc.swing.plugins.online.view.NewUserDialog;
|
||||
import org.diylc.swing.plugins.online.view.UploadDialog;
|
||||
|
||||
import com.diyfever.gui.ProgressDialog;
|
||||
|
||||
public class OnlineManager implements IPlugIn {
|
||||
|
||||
private static final String ONLINE_TITLE = "Online";
|
||||
|
||||
private IPlugInPort plugInPort;
|
||||
private LibraryPresenter libraryPresenter;
|
||||
|
||||
@Override
|
||||
public void connect(IPlugInPort plugInPort) {
|
||||
this.plugInPort = plugInPort;
|
||||
this.libraryPresenter = new LibraryPresenter();
|
||||
|
||||
initialize();
|
||||
|
||||
// plugInPort.injectMenuAction(new LibraryAction(), ONLINE_TITLE);
|
||||
// plugInPort.injectMenuAction(null, ONLINE_TITLE);
|
||||
// plugInPort.injectMenuAction(new LoginAction(), ONLINE_TITLE);
|
||||
// plugInPort.injectMenuAction(new CreateAccountAction(), ONLINE_TITLE);
|
||||
// plugInPort.injectMenuAction(null, ONLINE_TITLE);
|
||||
// plugInPort.injectMenuAction(new UploadAction(), ONLINE_TITLE);
|
||||
// plugInPort.injectMenuAction(new ManageProjectsAction(), ONLINE_TITLE);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
libraryPresenter.connectDb();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
if (libraryPresenter.isLoggedIn()) {
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
worker.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EventType> getSubscribedEventTypes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessage(EventType eventType, Object... params) {
|
||||
}
|
||||
|
||||
class LibraryAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public LibraryAction() {
|
||||
super();
|
||||
putValue(AbstractAction.NAME, "Browse Library");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Chest.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
}
|
||||
}
|
||||
|
||||
class LoginAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public LoginAction() {
|
||||
super();
|
||||
putValue(AbstractAction.NAME, "Log in");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.IdCard.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
LoginDialog dialog = DialogFactory.getInstance().createLoginDialog();
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
class CreateAccountAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CreateAccountAction() {
|
||||
super();
|
||||
putValue(AbstractAction.NAME, "Create New Account");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.IdCardAdd.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
NewUserDialog dialog = DialogFactory.getInstance().createNewUserDialog();
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
class UploadAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UploadAction() {
|
||||
super();
|
||||
putValue(AbstractAction.NAME, "Upload Project");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Upload.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
UploadDialog dialog = DialogFactory.getInstance().createUploadDialog();
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
class ManageProjectsAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ManageProjectsAction() {
|
||||
super();
|
||||
putValue(AbstractAction.NAME, "Manage Projects");
|
||||
putValue(AbstractAction.SMALL_ICON, IconLoader.Wrench.getIcon());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ProgressDialog dialog = DialogFactory.getInstance().createProgressDialog("Test",
|
||||
new String[] {}, "Some text", false);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user