Compare commits

..

275 Commits

Author SHA1 Message Date
bancika 934b510fbc 2012-08-21 20:04:28 +00:00
bancika 385612bc74 2012-08-21 20:03:42 +00:00
bancika ae3694c70d 2012-08-21 20:02:54 +00:00
bancika 56fef06b22 removed unused libs 2012-08-21 15:30:40 +00:00
bancika 4897b803b6 2012-08-21 14:43:10 +00:00
bancika 6c698e935e Replaced deep cloning library with manual implementation 2012-08-21 14:16:19 +00:00
bancika 1645eae18d Replaced deep cloning library with manual implementation 2012-08-21 14:16:07 +00:00
bancika 5adbc2c6ca Some components can be placed in any layer using Send to Back/Bring to Front 2012-08-21 11:06:19 +00:00
bancika e3b1f0d4e6 Some components can be placed in any layer using Send to Back/Bring to Front 2012-08-21 11:06:08 +00:00
bancika bc88253c70 Some components can be placed in any layer using Send to Back/Bring to Front 2012-08-21 11:05:59 +00:00
bancika 1d45bf345c 2012-08-21 08:58:36 +00:00
bancika c61ec71ee1 2012-08-21 08:58:19 +00:00
bancika 35272c1339 check if the app is run from Jar directly 2012-08-21 08:53:41 +00:00
bancika 93e057dfb2 [Improvement] Improved overall performance
[Bug Fix] Should be more stable under OSX and not crash unexpectedly
2012-08-21 08:32:18 +00:00
bancika aef5c88a3f [Improvement] Improved overall performance
[Bug Fix] Should be more stable under OSX and not crash unexpectedly
2012-08-21 08:32:11 +00:00
bancika 591bdd313c [Improvement] Improved overall performance
[Bug Fix] Should be more stable under OSX and not crash unexpectedly
2012-08-21 08:32:04 +00:00
bancika 3f9caf9918 [Improvement] Improved overall performance
[Bug Fix] Should be more stable under OSX and not crash unexpectedly
2012-08-21 08:29:27 +00:00
bancika 246decdf7c [Improvement] Improved overall performance
[Bug Fix] Should be more stable under OSX and not crash unexpectedly
2012-08-21 08:29:17 +00:00
bancika 0bc8141dc7 [Improvement] Improved overall performance
[Bug Fix] Should be more stable under OSX and not crash unexpectedly
2012-08-21 08:28:55 +00:00
bancika 6e8e8b9d49 release build 2012-08-20 09:49:51 +00:00
bancika c8ff6afe6e release build 2012-08-20 09:33:54 +00:00
bancika 714740da28 release build 2012-08-20 09:33:44 +00:00
bancika 45b759fa75 2012-08-17 15:56:41 +00:00
bancika 2445f05767 2012-08-17 15:39:49 +00:00
bancika 22578a4e3f 2012-08-17 14:57:22 +00:00
bancika 10a42b7fcf Better unsaved warning message 2012-08-17 14:51:14 +00:00
bancika 0498eb2c51 Better unsaved warning message 2012-08-17 14:51:05 +00:00
bancika d384711759 UNICODE font export to PDF files 2012-08-17 14:26:22 +00:00
bancika 5e0c422c30 UNICODE font export to PDF files 2012-08-17 14:26:06 +00:00
bancika 73cc182dad UNICODE font export to PDF files 2012-08-17 14:25:55 +00:00
bancika 7932657fb2 Transistors can show name or value 2012-08-17 13:28:07 +00:00
bancika 50bacee70a Transistors can show name or value 2012-08-17 13:27:59 +00:00
bancika 1c0219f4bf 2012-08-17 13:07:55 +00:00
bancika 4522d9aeb5 Faster component placement, auto-focus on "Value" box 2012-08-17 12:56:35 +00:00
bancika a25d43b710 Default resistor value to 100k 2012-08-17 12:55:36 +00:00
bancika 18261eab69 Control number of "Recently Used" items from config.properties 2012-08-17 12:35:15 +00:00
bancika 3b984d0850 Control number of "Recently Used" items from config.properties 2012-08-17 12:35:11 +00:00
bancika d72d898f3f Control number of "Recently Used" items from config.properties 2012-08-17 12:31:03 +00:00
bancika 03bc58eb96 Control number of "Recently Used" items from config.properties 2012-08-17 12:30:55 +00:00
bancika 17427a0071 2012-08-17 12:17:19 +00:00
bancika 39704e3625 Improved "Recently Used" toolbox, doesn't jump as you click 2012-08-17 11:38:01 +00:00
bancika 6ef7459d46 Move selected components with arrow keys (and ctrl/shift) 2012-08-17 10:41:31 +00:00
bancika a6448676f7 Move selected components with arrow keys (and ctrl/shift) 2012-08-17 10:41:19 +00:00
bancika 4cf6f9f4a5 Remove junk from BOM (eyelets, wires, traces) 2012-08-16 15:56:58 +00:00
bancika 162b67bf25 Remove junk from BOM (eyelets, wires, traces) 2012-08-16 15:51:21 +00:00
bancika ccc90dd3a6 Remove junk from BOM (eyelets, wires, traces) 2012-08-16 15:50:59 +00:00
bancika 237639b9a1 Remove junk from BOM (eyelets, wires, traces) 2012-08-16 15:50:46 +00:00
bancika 37b89fe3a2 2012-08-16 14:40:10 +00:00
bancika 860bb0071b improved toolbar click reliability 2012-08-16 14:32:37 +00:00
bancika 56fd800e77 added .diy associations 2012-08-16 11:03:46 +00:00
bancika 1a95e43f9f added .diy associations 2012-08-16 11:02:26 +00:00
bancika 9817aa549e added .diy associations 2012-08-16 10:58:53 +00:00
bancika c38bd87a7d Right click rotates component while laying out on the canvas 2012-08-16 10:24:00 +00:00
bancika 21e46b3835 Right click rotates component while laying out on the canvas 2012-08-16 10:23:51 +00:00
bancika 6a4508b4a9 2012-08-16 09:28:01 +00:00
bancika 33d3e03ffb minor changes 2012-08-16 09:27:05 +00:00
bancika 98c3804529 minor changes 2012-08-16 09:26:55 +00:00
bancika 4f88bb988a copy-paste performance improvement 2012-08-15 21:18:31 +00:00
bancika 5a4eeb2de2 graphics fix 2012-08-15 21:18:14 +00:00
bancika abf99285cf switch terminal size improvement 2012-03-31 17:12:13 +00:00
bancika e83a2bd5f8 removed beta 2012-03-30 01:58:24 +00:00
bancika 445a56f563 improved bring to front/back 2012-03-29 02:36:34 +00:00
bancika aa434048f3 9v battery snap 2012-03-28 02:04:08 +00:00
bancika 1b043abfe5 description update 2012-03-28 01:50:01 +00:00
bancika b08395ee27 lever guitar switch 2012-03-27 02:36:31 +00:00
bancika a23342f682 2012-03-22 01:05:20 +00:00
bancika 93a4978e68 single coil pickup 2012-03-21 02:42:12 +00:00
bancika 0d845677c4 added humbucker pickup 2012-03-19 00:33:47 +00:00
bancika ab10103e41 added humbucker pickup 2012-03-19 00:15:56 +00:00
bancika 0d17046170 add OS version to log 2012-03-18 13:39:10 +00:00
bancika 880e618e30 Fonts are exported to PDF 2012-03-18 02:16:20 +00:00
bancika 176abc2428 Plastic DC jack 2012-03-17 23:47:15 +00:00
bancika 061bc520c6 Plastic DC jack 2012-03-17 02:21:26 +00:00
bancika 9c9d6ecd70 Plastic DC jack 2012-03-17 02:15:24 +00:00
bancika d9f5e2e42b Plastic DC jack 2012-03-17 02:02:53 +00:00
bancika 0c1659cde0 added closed jack 2012-03-17 00:29:28 +00:00
bancika 53feb60b63 added closed jack 2012-03-17 00:17:22 +00:00
bancika 8c2700b92c added closed jack 2012-03-17 00:17:06 +00:00
bancika 298d575696 added cliff style jack 2012-03-15 01:58:41 +00:00
bancika 931138083f added cliff style jack 2012-03-15 01:19:28 +00:00
bancika f2a814e41c added cliff style jack 2012-03-15 00:56:20 +00:00
bancika d07965a3c0 added ground symbol 2012-03-11 17:15:27 +00:00
bancika 9e1f5c3ac8 added ground symbol 2012-03-11 17:11:51 +00:00
bancika 569a50e97a utf-8 2012-03-10 13:28:07 +00:00
bancika 80e7e3a487 2012-03-10 13:27:42 +00:00
bancika 5d73617af3 2012-03-10 04:09:25 +00:00
bancika 8169e3a6ba BJT symbol 2012-03-10 04:03:44 +00:00
bancika a7b48f4f52 BJT symbol 2012-03-10 03:47:30 +00:00
bancika 89bf22bcf8 UTF-8 2012-03-10 02:58:49 +00:00
bancika ae99ce2702 use UTF-8 2012-03-10 01:14:01 +00:00
bancika 61937d6d42 Add IC symbol 2012-03-05 03:11:45 +00:00
bancika e618a1e1ad Add IC symbol 2012-03-04 23:22:47 +00:00
bancika 513a229e64 Added MOSFET Symbol 2012-03-04 23:16:44 +00:00
bancika f834aa6d0b Added JFET Symbol 2012-03-04 23:03:41 +00:00
bancika 35d8b13d41 Added MOSFET Symbol 2012-03-04 22:42:33 +00:00
bancika 989e0a03e4 Added MOSFET Symbol 2012-03-04 22:41:37 +00:00
bancika c6cb77f4ef Added MOSFET Symbol 2012-03-04 22:37:05 +00:00
bancika af1a11e848 Added MOSFET Symbol 2012-03-04 22:32:42 +00:00
bancika 4bcff4a574 2012-03-04 18:43:36 +00:00
bancika 36f65423e0 Add IC symbol 2012-03-04 18:35:00 +00:00
bancika ef11c931a7 2012-03-04 16:28:54 +00:00
bancika 732a9954b7 Add IC symbol 2012-03-04 15:09:53 +00:00
bancika 2b5b904d8d IC component can display name or value 2012-03-04 15:09:43 +00:00
bancika 6ca16d07e6 Application breaks when resistance is set to 0 ohms 2012-03-04 15:09:12 +00:00
bancika 4f113f032d fixed out of bounds exc 2012-03-04 14:27:10 +00:00
bancika e572412f1e fixed to use new file paths 2012-02-26 13:40:03 +00:00
bancika dd9e9f054c Expand selection feature, useful for debugging
Limit length of text in the status bar using "and X more" suffix
2012-02-26 03:54:12 +00:00
bancika 4ee7381959 2012-02-20 03:22:01 +00:00
bancika d11a8b906a Do not hard-code voltage and power ratings 2012-02-12 18:45:34 +00:00
bancika 9fdd96c889 R instead of omega for resistance 2012-02-12 18:13:32 +00:00
bancika d776a3df32 2012-02-12 15:26:30 +00:00
bancika ebf06841a0 Select components from context menu even when they are under other components 2012-02-12 14:36:18 +00:00
bancika 616b09b4b2 2012-02-12 05:21:57 +00:00
bancika dccd91e56b Imperial ruler is divided to .1" instead of 1/4" 2012-02-12 05:17:08 +00:00
bancika 59c543da34 2012-02-12 03:54:24 +00:00
bancika 7c933fa0f3 v1 import improvements 2012-02-12 03:53:50 +00:00
bancika 8294caa8ba Smarter resistor labels; try not to overlap label with bands 2012-02-11 14:07:05 +00:00
bancika a7637767cd 2012-02-10 04:24:53 +00:00
bancika 2dccd41f41 do not put space between value and multiplier K, M, etc 2012-02-10 04:23:10 +00:00
bancika 2dfec28dc9 perfboards can show coordinates 2012-02-10 03:17:42 +00:00
bancika fe527eece2 2012-02-08 05:02:10 +00:00
bancika d459ea898c ctrl+shift toggles snap to grid 2012-02-08 04:48:31 +00:00
bancika 19cfca3df8 2012-02-08 04:48:08 +00:00
bancika 3d3a6e27d2 2012-02-02 04:30:25 +00:00
bancika 10884452fd 2012-02-02 04:29:45 +00:00
bancika 6d4c2a8141 2012-02-02 04:29:37 +00:00
bancika 66f4d98ff9 add more pin options 2012-02-02 04:26:59 +00:00
bancika a00028131f Adjustable solder pad hole size 2011-09-03 20:01:09 +00:00
bancika 7f2b973638 Better lead and label rendering when lead spacing is smaller than component body 2011-09-03 19:47:35 +00:00
bancika 144bfb01ad Select All should not include locked components 2011-09-03 19:38:15 +00:00
bancika 84d0da6308 Renumber function sometimes doesn't work as expected 2011-09-03 19:19:07 +00:00
bancika 0df3bc37a0 increase PNG resolution to 300dpi 2011-09-03 19:07:19 +00:00
bancika a0b43def22 move to new project directory names 2011-08-29 22:14:50 +00:00
bancika 602c98ead4 move to new project directory names 2011-08-29 21:41:09 +00:00
bancika 4b64917654 move to new project directory names 2011-08-29 21:16:26 +00:00
bancika 030ba71126 2011-08-29 21:16:09 +00:00
bancika eb4d08be68 move to new project directory names 2011-08-29 21:10:45 +00:00
bancika b642dc6cbd move to new project directory names 2011-08-29 20:57:51 +00:00
bancika 112bfdd3d0 move to new project directory names 2011-08-29 20:54:36 +00:00
bancika 79f83308d8 move to new project directory names 2011-08-29 20:46:53 +00:00
bancika 5df467a254 2011-08-28 21:43:25 +00:00
bancika 7c4d82b28c added recently used tab 2011-08-28 21:31:49 +00:00
bancika 6b7d1c4277 Renumber selected components by X or Y axis 2011-08-28 17:09:10 +00:00
bancika a0ae53d53c fixed method finding issues 2011-08-28 16:23:35 +00:00
bancika bd79ef2817 Component edit dialog allows changing property values even when they are not the same 2011-08-28 16:10:38 +00:00
bancika 69e2296c23 show mutual properties across different component types 2011-08-27 20:36:37 +00:00
bancika 7d3a7c30ca check file permission before using auto-save 2011-08-26 18:31:36 +00:00
bancika bea19f326c Auto-increment component names when copy-pasting 2011-08-26 18:18:53 +00:00
bancika ba694add0c allow 0 ohm resistors 2011-08-26 17:59:50 +00:00
bancika f137a398dc double click on a component button to select all of that type 2011-08-26 17:56:33 +00:00
bancika 15ac8ff2e9 increase PNG resolution 2011-08-07 19:23:50 +00:00
bancika 1213dcaeac increase PNG resolution 2011-08-07 19:23:23 +00:00
bancika 2ebcd1fe96 ctrl+click should never clear selection 2011-08-07 19:07:19 +00:00
bancika 943d123ca9 outline mode
improved auto-create for pads
2011-03-05 19:53:19 +00:00
bancika 79c29dc349 2011-03-03 21:05:47 +00:00
bancika 746b5fbe1a 2011-03-03 20:56:56 +00:00
bancika 365c195091 fix for drawing area and optimization 2011-03-02 18:14:39 +00:00
bancika d89a500a5f fix for drawing area and optimization 2011-03-02 18:13:34 +00:00
bancika 085732fb2c 2011-03-01 00:17:53 +00:00
bancika eab7654883 Curved traces and wires can have 2, 3 and 4 control points 2011-02-28 00:09:13 +00:00
bancika 5488657984 config menu order 2011-02-27 23:38:11 +00:00
bancika 1a256716db tube socket improvement 2011-02-27 23:30:05 +00:00
bancika 2b9c76e876 add file version info
improve image serialization
serialize points referenced in inches
2011-02-27 23:26:11 +00:00
bancika 5ae8a3477e add file version info
improve image serialization
serialize points referenced in inches
2011-02-27 23:23:51 +00:00
bancika 209e970c00 catch drag end outside the area 2011-02-27 22:56:40 +00:00
bancika ae96fb9eef label has editable font 2011-02-27 21:58:57 +00:00
bancika 401f2b5e6f label has editable font 2011-02-27 21:56:08 +00:00
bancika e2da0b884d vertical vero board 2011-02-27 20:48:18 +00:00
bancika bcf390b888 switchable wheel zoom 2011-02-27 19:25:39 +00:00
bancika 144e8f0cfe standing resistors, capacitors and diodes 2011-02-27 19:09:15 +00:00
bancika 84d744a80b switchable wheel zoom 2011-02-27 18:34:33 +00:00
bancika 5430ca71a3 added 6 pin IC 2011-02-26 21:12:45 +00:00
bancika 4665d5d42e added tube 2011-02-26 21:05:40 +00:00
bancika 275918d079 dnd collision improvement 2011-02-26 15:35:53 +00:00
bancika a83093519f 2011-02-26 11:30:05 +00:00
bancika 2e14929eb1 send to back/front renamed 2011-02-26 11:28:40 +00:00
bancika a0b7cdc30e auto-save added 2011-02-26 11:26:49 +00:00
bancika ab5c9ad143 code cleanup 2011-02-24 00:05:27 +00:00
bancika 4154225e71 auto-edit mode 2011-02-24 00:02:32 +00:00
bancika 3856af3e18 continuous component creation 2011-02-23 23:44:00 +00:00
bancika 80e7ebcbe9 auto-create pads 2011-02-23 20:42:40 +00:00
bancika abdf02eac8 configurable snap to grid 2011-02-18 22:17:03 +00:00
bancika 746aadd8a2 improve bring to front/send to back 2011-02-18 13:17:56 +00:00
bancika ac4496040f improve bring to front/send to back 2011-02-18 13:16:58 +00:00
bancika d810096030 relax logging 2011-02-16 19:10:57 +00:00
bancika 4727017be7 fix for default browser 2011-02-15 20:36:18 +00:00
bancika b2dae15ee6 fix for default browser 2011-02-15 19:18:01 +00:00
bancika 56e112ff81 don't show grid on the thumbnail 2011-02-13 11:46:53 +00:00
bancika 6f5926e18e removed unused theme members 2011-02-13 09:43:27 +00:00
bancika b1f4773b10 2011-02-12 20:59:04 +00:00
bancika e5d33fb80d switchable sticky points
added themes
fixed ruler precision
improved board rendering
2011-02-12 20:35:09 +00:00
bancika b8545d27a1 line tracing fix 2011-02-06 20:38:21 +00:00
bancika 70ac30473b use clip to improve performance 2011-02-06 18:27:50 +00:00
bancika 4774e97ba2 use clip to improve performance 2011-02-06 18:22:30 +00:00
bancika de7378c722 2011-02-06 16:23:29 +00:00
bancika e2b3ed1b0e configurable render quality 2011-02-06 16:01:57 +00:00
bancika 99d38feb1c improved speed 2011-02-03 23:42:07 +00:00
bancika a561f6a3f9 tweaked boards 2011-02-03 23:10:23 +00:00
bancika 6eee1525ee better scaling
added marshall board and trimmer
2011-02-03 21:47:16 +00:00
bancika 02d38bed01 added eyelet/turret 2011-01-31 22:47:21 +00:00
bancika b96bad2688 cleanup component area map on loading
fixed lead area mapping bug
2011-01-31 22:05:05 +00:00
bancika 12ca93e2c9 fixed color code rounding 2011-01-31 21:49:01 +00:00
bancika d9b9542883 configurable jumper color 2011-01-31 20:03:41 +00:00
bancika 9e04cff806 fixed lead alignment issue 2011-01-31 20:03:22 +00:00
bancika 16600328cc copy paste doesn't work for some components 2011-01-31 19:32:18 +00:00
bancika 85d7d8a450 fixed lead alignment issue 2011-01-31 00:19:57 +00:00
bancika f358b5d87b fixed lead alignment issue 2011-01-31 00:18:39 +00:00
bancika fa02280292 code cleanup 2011-01-30 23:45:25 +00:00
bancika 8ea53b6876 added capacitor symbol 2011-01-30 23:35:07 +00:00
bancika 4d6e994555 added resistor wattage and capacitor voltage 2011-01-30 21:50:24 +00:00
bancika 10581c51fb added abstract class for leaded schematic symbols and resistor symbol 2011-01-30 21:33:08 +00:00
bancika 2cf6b573a7 added abstract class for leaded schematic symbols and resistor symbol 2011-01-30 21:31:42 +00:00
bancika 629fb5fff7 2011-01-30 18:46:38 +00:00
bancika bc154608f4 allow property edit validation 2011-01-30 17:21:42 +00:00
bancika a8cc661d09 better error handling when drawing 2011-01-30 14:10:38 +00:00
bancika 0b10f0bfe3 V1 file importer can recognize hookup wire and transistors 2011-01-30 12:02:29 +00:00
bancika f435571aae added keyboard shortcuts to some menu options 2011-01-30 11:43:54 +00:00
bancika 6bb248032f added square pad 2011-01-30 11:32:55 +00:00
bancika 1b04023a93 added axial electrolytic 2011-01-29 22:38:46 +00:00
bancika a32c8c4c8d added axial electrolytic 2011-01-29 22:35:09 +00:00
bancika 4a89159c80 reset component selection when switching tabs 2011-01-29 22:00:33 +00:00
bancika e5113e110e reset component selection when switching tabs 2011-01-29 22:00:01 +00:00
bancika c2051fcea2 improved electrolytic cap and resistor 2011-01-29 21:56:43 +00:00
bancika a42592410e improved electrolytic cap and resistor 2011-01-29 21:55:51 +00:00
bancika 22185a2d14 Potentiometer misdraw at 180 degrees 2011-01-29 18:31:25 +00:00
bancika ac6aaf4e06 added LED 2011-01-29 13:47:00 +00:00
bancika 1be52c1dfa improved zooming 2011-01-29 09:49:28 +00:00
bancika 328d09123b removed sysout 2011-01-29 09:02:19 +00:00
bancika 04cd80b561 added TO220 transistor
improved status text
2011-01-29 08:59:53 +00:00
bancika 3a419ba3bc added transistor 2011-01-28 20:05:37 +00:00
bancika 971ceb7160 added template support 2011-01-28 19:21:35 +00:00
bancika e0d8990954 added template support 2011-01-28 19:19:05 +00:00
bancika a70ec95822 added template support 2011-01-28 19:13:49 +00:00
bancika 8aacf915e3 added template support 2011-01-28 18:57:21 +00:00
bancika 777d3f6deb added template support 2011-01-28 18:55:40 +00:00
bancika 7de327b9bd fixed point visibility on curved trace
added option to hide color bands on the resistor
2011-01-28 17:48:46 +00:00
bancika 11b7756a59 added resistor color codes
fixed double value parsing
2011-01-27 22:34:41 +00:00
bancika b3351ef081 version info 2011-01-27 20:17:06 +00:00
bancika b1dbf4f1d2 added action to right click menu 2011-01-27 19:52:59 +00:00
bancika 9161182924 added send to back/bring to front 2011-01-27 19:49:33 +00:00
bancika 94f769f785 added send to back/bring to front 2011-01-27 19:44:37 +00:00
bancika 6dffcd6349 added send to back/bring to front 2011-01-27 19:41:36 +00:00
bancika 6fad7a2427 fixed NPE and wrong undo/redo for ungroup 2011-01-27 19:21:34 +00:00
bancika 4ab6231590 refactored actions out
added right click menu
2011-01-27 19:16:40 +00:00
bancika 5de6caf073 fixed bug with file name when creating new file 2011-01-26 23:57:09 +00:00
bancika be7ab3412d optimize image saving/loading 2011-01-26 23:50:48 +00:00
bancika 3dd4a4c5e3 added worker thread 2011-01-26 21:49:57 +00:00
bancika fb6f973a6e added worker thread 2011-01-26 21:48:57 +00:00
bancika e8d45e1426 added image alpha 2011-01-26 21:06:51 +00:00
bancika 51c916cbb5 added image component 2011-01-26 20:09:15 +00:00
bancika a8ba97dc77 revived cut action 2011-01-26 19:45:44 +00:00
bancika 103860a42b added update file 2011-01-26 19:04:51 +00:00
bancika 126d629cdc refactored awt.transferable out of the presenter
fixed copy/paste between instances
2011-01-26 18:44:40 +00:00
bancika f28dda37a6 optimize refresh when creating new component 2011-01-25 22:48:51 +00:00
bancika 3a7fdeb792 allow curve shape control points to overlap 2011-01-25 21:38:37 +00:00
bancika 13e0cec8ad better logging 2011-01-25 19:13:07 +00:00
bancika df33d7fd6e improved IC 2011-01-24 21:28:53 +00:00
bancika 2f672bf2b4 round corners 2011-01-24 21:02:33 +00:00
bancika e84f77a7ca pulled out scripting because of locale issues 2011-01-24 20:58:18 +00:00
bancika efeaf92ccb ability to center label 2011-01-24 20:12:51 +00:00
bancika 8927b2c326 tweak control point visibility 2011-01-24 20:00:11 +00:00
bancika 3476d3a608 import text component 2011-01-24 19:49:04 +00:00
bancika 6c052403d3 import electrolytics 2011-01-24 19:40:22 +00:00
bancika 1322f48918 removed unused ode 2011-01-24 19:23:03 +00:00
bancika 62cbe4826f improved stick mechanism when more than one point is stuck 2011-01-24 19:13:09 +00:00
bancika 2aa8aed874 improved importer for v1 2011-01-24 18:54:04 +00:00
bancika 6d361283a1 Configurable wheel zoom 2011-01-24 18:21:57 +00:00
bancika b33b6b6495 show selection size on demand
removed scroll buttons in toolbox
2011-01-24 18:17:13 +00:00
bancika fb5baf9571 added transparency to pot 2011-01-23 23:54:24 +00:00
bancika 2d6927993e fixed creation bug with d&d 2011-01-23 23:47:35 +00:00
bancika 5806d17e56 added v1 conversion warnings 2011-01-23 23:25:20 +00:00
bancika fcc001cb98 reduced number of base layers 2011-01-23 23:18:45 +00:00
bancika 1de1b9d6ec refactored some swing out of the core parts 2011-01-23 22:57:52 +00:00
bancika 726f17aa7f refactor some swing references 2011-01-23 19:58:47 +00:00
bancika 72ae295a09 fixed NPE 2011-01-23 18:51:04 +00:00
453 changed files with 16259 additions and 5639 deletions
-14
View File
@@ -1,14 +0,0 @@
<map>
<entry>
<string>lastPath</string>
<string>C:\Documents and Settings\Branislav Stojkovic\Desktop</string>
</entry>
<entry>
<string>zoom</string>
<double>1.0</double>
</entry>
<entry>
<string>metric</string>
<boolean>true</boolean>
</entry>
</map>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-64
View File
@@ -1,64 +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.gui.MainFrame;
import org.diylc.presenter.Presenter;
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);
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,54 +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 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,259 +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 width;
protected Size height;
protected Point[] points = new Point[] {
new Point((int) (-DEFAULT_SIZE.convertToPixels() / 2), 0),
new Point(DEFAULT_SIZE.convertToPixels() / 2, 0) };
protected Color bodyColor = getDefaultBodyColor();
protected Color borderColor = getDefaultBorderColor();
protected Color labelColor = LABEL_COLOR;
protected Display display = Display.NAME;
protected AbstractLeadedComponent() {
super();
try {
this.width = getDefaultWidth().clone();
this.height = getDefaultHeight().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 width.
*/
protected abstract Size getDefaultWidth();
/**
* Returns default component height.
*
* @return
*/
protected abstract Size getDefaultHeight();
/**
* @return shape that represents component body. Shape should not be
* transformed and should be referenced to (0, 0).
*/
protected abstract Shape getBodyShape();
/**
* @return default component body color.
*/
protected abstract Color getDefaultBodyColor();
/**
* @return default component border color.
*/
protected abstract Color getDefaultBorderColor();
/**
* @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(defaultable = true)
public Size getWidth() {
return width;
}
public void setWidth(Size width) {
this.width = width;
}
@EditableProperty(defaultable = true)
public Size getHeight() {
return height;
}
public void setHeight(Size height) {
this.height = height;
}
@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,31 +0,0 @@
package org.diylc.core.measures;
public class Resistance extends AbstractMeasure<ResistanceUnit> {
private static final long serialVersionUID = 1L;
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 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);
}
}
-54
View File
@@ -1,54 +0,0 @@
package org.diylc.gui;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JComponent;
import org.diylc.common.BadPositionException;
import org.diylc.common.IPlugInPort;
/**
* Base interface for the main GUI component.
*
* @author Branislav Stojkovic
*/
public interface IView {
/**
* Adds a component to the view.
*
* @param component
* component to insert
* @param position
* target position
* @throws BadPositionException
*
* @see IPlugInPort#injectGUIComponent
*/
void addComponent(JComponent component, int position) throws BadPositionException;
/**
* Adds a menu action.
*
* @param action
* action to insert
* @param menuName
* target menu name
*
* @see IPlugInPort#injectMenuAction
*/
void addMenuAction(Action action, String menuName);
/**
* Adds a submenu to an existing menu.
*
* @param name
* @param icon
* @param parentMenuName
*/
void addSubmenu(String name, Icon icon, String parentMenuName);
void showMessage(String message, String title, int messageType);
int showConfirmDialog(String message, String title, int optionType, int messageType);
}
@@ -1,51 +0,0 @@
package org.diylc.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,79 +0,0 @@
package org.diylc.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,150 +0,0 @@
package org.diylc.plugins.canvas;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.EnumSet;
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.plugins.file.ProjectDrawingProvider;
import org.diylc.presenter.Presenter;
import com.diyfever.gui.miscutils.ConfigurationManager;
import com.diyfever.gui.ruler.IRulerListener;
import com.diyfever.gui.ruler.RulerScrollPane;
public class CanvasPlugin implements IPlugIn {
private static final Logger LOG = Logger.getLogger(CanvasPlugin.class);
private RulerScrollPane scrollPane;
private CanvasPanel canvasPanel;
private IPlugInPort plugInPort;
public CanvasPlugin() {
}
@Override
public void connect(IPlugInPort plugInPort) {
this.plugInPort = plugInPort;
try {
plugInPort.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);
}
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);
scrollPane.setMetric(metric);
scrollPane.setWheelScrollingEnabled(false);
scrollPane.addUnitListener(new IRulerListener() {
@Override
public void unitsChanged(boolean isMetric) {
plugInPort.setMetric(isMetric);
}
});
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;
}
@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();
}
// canvasPanel.validate();
// canvasPanel.repaint();
break;
case ZOOM_CHANGED:
refreshSize();
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 ruller 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);
}
}
@@ -1,316 +0,0 @@
package org.diylc.plugins.clipboard;
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.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.EnumSet;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.KeyStroke;
import org.apache.log4j.Logger;
import org.diylc.common.ComponentSelection;
import org.diylc.common.EventType;
import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort;
import org.diylc.common.PropertyWrapper;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Project;
import org.diylc.gui.DialogFactory;
import org.diylc.gui.editor.PropertyEditorDialog;
import org.diylc.images.IconLoader;
import com.diyfever.gui.ButtonDialog;
import com.diyfever.gui.undo.IUndoListener;
import com.diyfever.gui.undo.UndoHandler;
import com.rits.cloning.Cloner;
public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
private static final Logger LOG = Logger.getLogger(EditMenuPlugin.class);
private static final String EDIT_TITLE = "Edit";
private IPlugInPort plugInPort;
private Clipboard clipboard;
private Cloner cloner;
// private CutAction cutAction;
private CopyAction copyAction;
private PasteAction pasteAction;
private UndoHandler<Project> undoHandler;
public EditMenuPlugin() {
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
cloner = new Cloner();
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();
}
});
}
@Override
public void connect(IPlugInPort plugInPort) {
this.plugInPort = plugInPort;
plugInPort.injectMenuAction(undoHandler.getUndoAction(), EDIT_TITLE);
plugInPort.injectMenuAction(undoHandler.getRedoAction(), EDIT_TITLE);
plugInPort.injectMenuAction(null, EDIT_TITLE);
// cutAction = new CutAction();
// plugInPort.injectMenuAction(cutAction, EDIT_TITLE);
copyAction = new CopyAction();
plugInPort.injectMenuAction(copyAction, EDIT_TITLE);
pasteAction = new PasteAction();
plugInPort.injectMenuAction(pasteAction, EDIT_TITLE);
plugInPort.injectMenuAction(null, EDIT_TITLE);
plugInPort.injectMenuAction(new SelectAllAction(), EDIT_TITLE);
plugInPort.injectMenuAction(null, EDIT_TITLE);
plugInPort.injectMenuAction(new EditSelectionAction(), EDIT_TITLE);
plugInPort.injectMenuAction(new EditProjectAction(), EDIT_TITLE);
plugInPort.injectMenuAction(null, EDIT_TITLE);
plugInPort.injectMenuAction(new GroupAction(), EDIT_TITLE);
plugInPort.injectMenuAction(new UngroupAction(), 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();
// cutAction.setEnabled(enabled);
copyAction.setEnabled(enabled);
try {
pasteAction.setEnabled(clipboard.isDataFlavorAvailable(ComponentSelection.listFlavor));
} catch (Exception e) {
pasteAction.setEnabled(false);
}
}
class CutAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public CutAction() {
super();
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");
}
}
class CopyAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public CopyAction() {
super();
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(cloner.deepClone(plugInPort.getSelectedComponents()),
EditMenuPlugin.this);
}
}
class PasteAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public PasteAction() {
super();
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(ComponentSelection.listFlavor);
plugInPort.pasteComponents(cloner.deepClone(components));
} catch (Exception ex) {
LOG.error("Coule not paste.", ex);
}
}
}
class SelectAllAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public SelectAllAction() {
super();
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();
}
}
class GroupAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public GroupAction() {
super();
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();
}
}
class UngroupAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public UngroupAction() {
super();
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();
}
}
class EditProjectAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public EditProjectAction() {
super();
putValue(AbstractAction.NAME, "Edit Project");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E,
ActionEvent.CTRL_MASK));
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());
}
}
}
}
class EditSelectionAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public EditSelectionAction() {
super();
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());
}
}
}
}
// ClipboardOwner
@Override
public void lostOwnership(Clipboard clipboard, Transferable contents) {
refreshActions();
}
}
@@ -1,289 +0,0 @@
package org.diylc.plugins.file;
import java.awt.event.ActionEvent;
import java.awt.print.PrinterException;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.EnumSet;
import java.util.List;
import javax.swing.AbstractAction;
import org.diylc.common.EventType;
import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort;
import org.diylc.common.PropertyWrapper;
import org.diylc.gui.DialogFactory;
import org.diylc.gui.editor.PropertyEditorDialog;
import org.diylc.images.IconLoader;
import com.diyfever.gui.ButtonDialog;
import com.diyfever.gui.IDrawingProvider;
import com.diyfever.gui.export.DrawingExporter;
import com.lowagie.text.DocumentException;
/**
* 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 IPlugInPort plugInPort;
private ProjectDrawingProvider drawingProvider;
private TraceMaskDrawingProvider traceMaskDrawingProvider;
@Override
public void connect(IPlugInPort plugInPort) {
this.plugInPort = plugInPort;
this.drawingProvider = new ProjectDrawingProvider(plugInPort, false);
this.traceMaskDrawingProvider = new TraceMaskDrawingProvider(plugInPort);
plugInPort.injectMenuAction(new NewAction(), FILE_TITLE);
plugInPort.injectMenuAction(new OpenAction(), FILE_TITLE);
plugInPort.injectMenuAction(new SaveAction(), FILE_TITLE);
plugInPort.injectMenuAction(new SaveAsAction(), FILE_TITLE);
plugInPort.injectMenuAction(null, FILE_TITLE);
plugInPort.injectMenuAction(new ExportPDFAction(drawingProvider), FILE_TITLE);
plugInPort.injectMenuAction(new ExportPNGAction(drawingProvider), FILE_TITLE);
plugInPort.injectMenuAction(new PrintAction(drawingProvider), FILE_TITLE);
plugInPort.injectSubmenu(TRACE_MASK_TITLE, IconLoader.TraceMask.getIcon(), FILE_TITLE);
plugInPort
.injectMenuAction(new ExportPDFAction(traceMaskDrawingProvider), TRACE_MASK_TITLE);
plugInPort
.injectMenuAction(new ExportPNGAction(traceMaskDrawingProvider), TRACE_MASK_TITLE);
plugInPort.injectMenuAction(new PrintAction(traceMaskDrawingProvider), TRACE_MASK_TITLE);
plugInPort.injectMenuAction(new CreateBomAction(), FILE_TITLE);
plugInPort.injectMenuAction(null, FILE_TITLE);
plugInPort.injectMenuAction(new ExitAction(), FILE_TITLE);
}
class NewAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public NewAction() {
super();
putValue(AbstractAction.NAME, "New");
putValue(AbstractAction.SMALL_ICON, IconLoader.DocumentPlainYellow.getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
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());
}
}
}
}
class OpenAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public OpenAction() {
super();
putValue(AbstractAction.NAME, "Open");
putValue(AbstractAction.SMALL_ICON, IconLoader.FolderOut.getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
if (!plugInPort.allowFileAction()) {
return;
}
File file = DialogFactory.getInstance().showOpenDialog(FileFilterEnum.DIY.getFilter(),
null, FileFilterEnum.DIY.getExtensions()[0], null);
if (file != null) {
plugInPort.loadProjectFromFile(file.getAbsolutePath());
}
}
}
class SaveAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public SaveAction() {
super();
putValue(AbstractAction.NAME, "Save");
putValue(AbstractAction.SMALL_ICON, IconLoader.DiskBlue.getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
if (plugInPort.getCurrentFileName() == null) {
File file = DialogFactory.getInstance().showSaveDialog(
FileFilterEnum.DIY.getFilter(), null,
FileFilterEnum.DIY.getExtensions()[0], null);
if (file != null) {
plugInPort.saveProjectToFile(file.getAbsolutePath());
}
} else {
plugInPort.saveProjectToFile(plugInPort.getCurrentFileName());
}
}
}
class SaveAsAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public SaveAsAction() {
super();
putValue(AbstractAction.NAME, "Save As");
putValue(AbstractAction.SMALL_ICON, IconLoader.DiskBlue.getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
File file = DialogFactory.getInstance().showSaveDialog(FileFilterEnum.DIY.getFilter(),
null, FileFilterEnum.DIY.getExtensions()[0], null);
if (file != null) {
plugInPort.saveProjectToFile(file.getAbsolutePath());
}
}
}
class CreateBomAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public CreateBomAction() {
super();
putValue(AbstractAction.NAME, "Create B.O.M.");
putValue(AbstractAction.SMALL_ICON, IconLoader.BOM.getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
List<BomEntry> bom = BomMaker.getInstance().createBom(
plugInPort.getCurrentProject().getComponents());
BomDialog dialog = DialogFactory.getInstance().createBomDialog(bom);
dialog.setVisible(true);
}
}
class ExportPDFAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private IDrawingProvider drawingProvider;
public ExportPDFAction(IDrawingProvider drawingProvider) {
super();
this.drawingProvider = drawingProvider;
putValue(AbstractAction.NAME, "Export to PDF");
putValue(AbstractAction.SMALL_ICON, IconLoader.PDF.getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
File file = DialogFactory.getInstance().showSaveDialog(FileFilterEnum.PDF.getFilter(),
null, FileFilterEnum.PDF.getExtensions()[0], null);
if (file != null) {
try {
DrawingExporter.getInstance().exportPDF(this.drawingProvider, file);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (DocumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
class ExportPNGAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private IDrawingProvider drawingProvider;
public ExportPNGAction(IDrawingProvider drawingProvider) {
super();
this.drawingProvider = drawingProvider;
putValue(AbstractAction.NAME, "Export to PNG");
putValue(AbstractAction.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) {
DrawingExporter.getInstance().exportPNG(this.drawingProvider, file);
}
}
}
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.SMALL_ICON, IconLoader.Print.getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
try {
DrawingExporter.getInstance().print(this.drawingProvider);
} catch (PrinterException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
class ExitAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public ExitAction() {
super();
putValue(AbstractAction.NAME, "Exit");
putValue(AbstractAction.SMALL_ICON, IconLoader.Exit.getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
if (plugInPort.allowFileAction()) {
System.exit(0);
}
}
}
@Override
public EnumSet<EventType> getSubscribedEventTypes() {
return null;
}
@Override
public void processMessage(EventType eventType, Object... params) {
// TODO Auto-generated method stub
}
}
@@ -1,43 +0,0 @@
package org.diylc.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,113 +0,0 @@
package org.diylc.plugins.toolbox;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.ScrollPaneConstants;
import org.diylc.common.ComponentType;
import org.diylc.common.IPlugInPort;
import org.diylc.presenter.ComparatorFactory;
import org.diylc.presenter.Presenter;
/**
* Tabbed pane that shows all available components categorized into tabs.
*
* @author Branislav Stojkovic
*/
class ComponentTabbedPane extends JTabbedPane {
public static int SCROLL_STEP = Presenter.ICON_SIZE + ComponentButton.MARGIN * 2 + 2;
private static final long serialVersionUID = 1L;
private final IPlugInPort plugInPort;
public ComponentTabbedPane(IPlugInPort plugInPort) {
super();
this.plugInPort = plugInPort;
Map<String, List<ComponentType>> componentTypes = plugInPort.getComponentTypes();
List<String> categories = new ArrayList<String>(componentTypes.keySet());
Collections.sort(categories);
for (String category : categories) {
JPanel panel = createTab((componentTypes.get(category)));
addTab(category, panel);
}
setPreferredSize(new Dimension(-1, Presenter.ICON_SIZE + ComponentButton.MARGIN * 2 + 38));
}
private JPanel createTab(List<ComponentType> componentTypes) {
JPanel panel = new JPanel(new BorderLayout());
final JScrollPane scrollPane = createComponentScrollBar(componentTypes);
panel.setOpaque(false);
JButton leftButton = new JButton("<");
leftButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Rectangle rect = scrollPane.getVisibleRect();
if (rect.x > SCROLL_STEP) {
rect.translate(-SCROLL_STEP, 0);
} else {
rect.translate(-rect.x, 0);
}
}
});
leftButton.setMargin(new Insets(0, 2, 0, 2));
JButton rightButton = new JButton(">");
rightButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Rectangle rect = scrollPane.getVisibleRect();
if (rect.x + rect.width < scrollPane.getViewport().getSize().width - SCROLL_STEP) {
rect.translate(SCROLL_STEP, 0);
} else {
rect.translate(scrollPane.getViewport().getSize().width - rect.x - rect.width,
0);
}
}
});
rightButton.setMargin(new Insets(0, 2, 0, 2));
panel.add(leftButton, BorderLayout.WEST);
panel.add(scrollPane);
panel.add(rightButton, BorderLayout.EAST);
return panel;
}
private JScrollPane createComponentScrollBar(List<ComponentType> componentTypes) {
JScrollPane scrollPane = new JScrollPane(createComponentPanel(componentTypes));
scrollPane.setOpaque(false);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
return scrollPane;
}
private Component createComponentPanel(List<ComponentType> componentTypes) {
Container toolbar = new Container();
Collections.sort(componentTypes, ComparatorFactory.getInstance()
.getComponentTypeComparator());
toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.X_AXIS));
for (ComponentType componentType : componentTypes) {
JButton button = new ComponentButton(plugInPort, componentType);
toolbar.add(button);
}
return toolbar;
}
}
@@ -1,36 +0,0 @@
package org.diylc.plugins.toolbox;
import java.util.EnumSet;
import javax.swing.SwingConstants;
import org.diylc.common.BadPositionException;
import org.diylc.common.EventType;
import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort;
public class ToolBox implements IPlugIn {
@Override
public void connect(IPlugInPort plugInPort) {
try {
plugInPort.injectGUIComponent(new ComponentTabbedPane(plugInPort), SwingConstants.TOP);
} catch (BadPositionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public EnumSet<EventType> getSubscribedEventTypes() {
// TODO Auto-generated method stub
return null;
}
@Override
public void processMessage(EventType eventType, Object... params) {
// TODO Auto-generated method stub
}
}
@@ -1,184 +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.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<Class<?>, List<PropertyWrapper>> propertyCache;
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<Class<?>, List<PropertyWrapper>>();
}
public ComponentType createComponentTypeFrom(Class<? extends IDIYComponent<?>> clazz) {
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);
return componentType;
}
/**
* Extracts all editable properties from the component class.
*
* @param clazz
* @return
*/
public List<PropertyWrapper> extractProperties(Class<?> clazz) {
if (propertyCache.containsKey(clazz)) {
return cloner.deepClone(propertyCache.get(clazz));
}
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();
}
Method setter = clazz.getMethod("set" + method.getName().substring(3),
method.getReturnType());
PropertyWrapper property = new PropertyWrapper(name,
method.getReturnType(), method, setter, annotation.defaultable());
properties.add(property);
}
} catch (NoSuchMethodException e) {
LOG.debug("No matching setter found for \"" + method.getName()
+ "\". Skipping...");
}
}
}
propertyCache.put(clazz, 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;
}
}
@@ -1,182 +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() {
// TODO Auto-generated constructor stub
}
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);
}
public void updatePointByPoint(Point scaledPoint) {
potentialControlPoint = scaledPoint;
if (componentSlot != null) {
componentSlot.setControlPoint(scaledPoint, 1);
}
}
public void 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;
}
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);
}
}
}
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,306 +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 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.Jumper;
import org.diylc.components.connectivity.SolderPad;
import org.diylc.components.passive.RadialFilmCapacitor;
import org.diylc.components.passive.Resistor;
import org.diylc.components.semiconductors.DIL_IC;
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 XStream xStream = new XStream(new DomDriver());
private String currentFileName = null;
private boolean modified = false;
private MessageDispatcher<EventType> messageDispatcher;
public ProjectFileManager(MessageDispatcher<EventType> messageDispatcher) {
super();
this.messageDispatcher = messageDispatcher;
}
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) 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());
} else if (formatVersion.equals("2.0")) {
LOG.debug("Detected v2 file.");
project = parseV2File(doc.getDocumentElement());
} else {
throw new IllegalArgumentException("Unknown file format version: " + formatVersion);
}
}
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) {
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;
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("pad")) {
LOG.debug("Recognized " + nodeName);
String colorAttr = node.getAttributes().getNamedItem("Color").getNodeValue();
SolderPad pad = new SolderPad();
pad.setName(nameAttr);
// pad.setColor(Color.getColor(colorAttr));
pad.setControlPoint(convertV1CoordinatesToV3Point(referencePoint, x1Attr,
y1Attr), 0);
component = pad;
} else if (nodeName.equalsIgnoreCase("trace")) {
LOG.debug("Recognized " + nodeName);
String colorAttr = node.getAttributes().getNamedItem("Color").getNodeValue();
CopperTrace trace = new CopperTrace();
trace.setName(nameAttr);
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("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.setWidth(new Size(6d, SizeUnit.mm));
resistor.setHeight(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.setWidth(new Size(6d, SizeUnit.mm));
capacitor.setHeight(new Size(2d, SizeUnit.mm));
capacitor.setControlPoint(point1, 0);
capacitor.setControlPoint(point2, 1);
component = capacitor;
} 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);
ic.setControlPoint(point1, 0);
ic.setValue(valueAttr);
component = ic;
} else {
LOG.debug("Could not recognize component type " + nodeName);
}
if (component != null) {
project.getComponents().add(component);
}
}
}
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,657 +0,0 @@
package org.diylc.utils.dnd;
/* Copyright (c) 2003-2006 Timothy Wall, All Rights Reserved */
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.MouseEvent;
import java.awt.geom.Area;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
/**
* Provide a method for consistently augmenting the appearance of a given
* component by painting something on it <i>after</i> the component itself gets
* painted. If not explicitly removed via {@link #dispose}, an instance of this
* object will live as long as its target component.
* <p>
* By default, the decorator matches the location and size of the decorated
* component, but the bounds can be adjusted by overriding
* {@link #getDecorationBounds()}. The {@link #synch()} method should be called
* whenever the bounds returned by {@link #getDecorationBounds()} would change.
* <p>
* The decoration is clipped to the bounds set on the decoration, which does not
* necessarily need to be the same as the decorated component bounds. The
* decoration may extend beyond the decorated component bounds, or it may be
* reduced to a smaller region.
*/
// TODO: should probably do some locking on Component.getTreeLock()
// TODO: synch underlying cursor when decorator covers more than
// one component; the cursor should change if the decoration exceeds the
// component's bounds
public abstract class AbstractComponentDecorator {
public static final Rectangle DEFAULT_BOUNDS = null;
public static final int TOP = 0;
// Disabled for now, since it doesn't work properly
private static final int BOTTOM = -1;
/**
* Account for the difference between the decorator actual origin and the
* logical origin we want to pass to the {@link #paint} method.
*/
private Point originOffset = new Point(0, 0);
private Painter painter;
private JComponent component;
private Container parent;
private Listener listener;
private int layerOffset;
private int position;
private Rectangle bounds;
/** Create a decorator for the given component. */
public AbstractComponentDecorator(JComponent c) {
this(c, 1);
}
/**
* Create a decorator for the given component, indicating the layer offset
* from the target component. Negative values mean the decoration is painted
* <em>before</em> the target component is painted.
*/
public AbstractComponentDecorator(JComponent c, int layerOffset) {
this(c, layerOffset, TOP);
}
/**
* Create a decorator with the given position within its layer. Use
* {@link #TOP} to cover other decorations, or {@link #BOTTOM} to be covered
* by other decorations.
* <p>
* WARNING: BOTTOM doesn't currently work, probably a JLayeredPane bug in
* either the code or documentation.
*
* @see JLayeredPane
*/
public AbstractComponentDecorator(JComponent c, int layerOffset, int position) {
component = c;
this.layerOffset = layerOffset;
this.position = position;
this.bounds = DEFAULT_BOUNDS;
parent = c.getParent();
painter = new Painter();
listener = new Listener();
component.addHierarchyListener(listener);
component.addComponentListener(listener);
component.addPropertyChangeListener(listener);
attach();
}
/**
* Set the text to be displayed when the mouse is over the decoration.
*
* @see JComponent#setToolTipText(String)
*/
public void setToolTipText(String text) {
painter.setToolTipText(text);
}
/**
* Return the currently set default tooltip text.
*
* @see JComponent#setToolTipText
*/
public String getToolTipText() {
return painter.getToolTipText();
}
/**
* Provide for different tool tips depending on the actual location over the
* decoration. Note that if you <em>only</em> override this method, you must
* also invoke {@link #setToolTipText(String)} with a non-<span
* class="javakeyword">null</span> argument.
*
* @see JComponent#getToolTipText(MouseEvent)
*/
public String getToolTipText(MouseEvent e) {
return getToolTipText();
}
/**
* Indicate whether any of the decoration is visible. The decoration may be
* clipped by ancestor scroll panes or by being moved outside if the visible
* region of its parent window.
*/
public boolean isVisible() {
return painter.isVisible();
}
/** Use this to change the visibility of the decoration. */
public void setVisible(boolean visible) {
painter.setVisible(visible);
}
protected void attach() {
Window w = SwingUtilities.getWindowAncestor(component);
if (w instanceof RootPaneContainer) {
JLayeredPane lp = ((RootPaneContainer) w).getLayeredPane();
Component layeredChild = component;
int layer = JLayeredPane.DRAG_LAYER.intValue();
if (this instanceof BackgroundPainter) {
layer = ((BackgroundPainter) this).layer;
painter.setDecoratedLayer(layer);
} else if (layeredChild == lp) {
// Is this the best layer to use?
painter.setDecoratedLayer(layer);
} else {
while (layeredChild.getParent() != lp) {
layeredChild = layeredChild.getParent();
}
int base = lp.getLayer(layeredChild);
// NOTE: JLayeredPane doesn't properly repaint an overlapping
// child when an obscured child calls repaint() if the two
// are in the same layer, so we use the next-higher layer
// instead of simply using a different position within the
// layer.
layer = base + layerOffset;
if (layerOffset < 0) {
BackgroundPainter bp = (BackgroundPainter) lp
.getClientProperty(BackgroundPainter.key(base));
if (bp == null) {
bp = new BackgroundPainter(lp, base);
}
}
painter.setDecoratedLayer(base);
}
lp.add(painter, new Integer(layer), position);
} else {
// Always detach when the target component's window is null
// or is not a suitable container,
// otherwise we might prevent GC of the component
Container parent = painter.getParent();
if (parent != null) {
parent.remove(painter);
}
}
// Track size changes in any viewport parent
if (parent != null) {
parent.removeComponentListener(listener);
}
parent = component.getParent();
if (parent != null) {
parent.addComponentListener(listener);
}
synch();
}
/**
* Ensure the size of the decorator matches the current decoration bounds
* with appropriate clipping to viewports.
*/
protected void synch() {
Container painterParent = painter.getParent();
if (painterParent != null) {
Rectangle decorated = getDecorationBounds();
Rectangle clipRect = clipDecorationBounds(decorated);
Point pt = SwingUtilities
.convertPoint(component, clipRect.x, clipRect.y, painterParent);
if (clipRect.width <= 0 || clipRect.height <= 0) {
setPainterBounds(-1, -1, 0, 0);
setVisible(false);
} else {
setPainterBounds(pt.x, pt.y, clipRect.width, clipRect.height);
setVisible(true);
}
}
painter.repaint();
}
/**
* Adjust the painting offsets and size of the decoration to account for
* ancestor clipping. This might be due to scroll panes or having the
* decoration lie outside the parent layered pane.
*/
protected Rectangle clipDecorationBounds(Rectangle decorated) {
// Amount we have to translate the Graphics context
originOffset.x = decorated.x;
originOffset.y = decorated.y;
// If the the component is obscured (by a viewport or some
// other means), use the painter bounds to clip to the visible
// bounds. Doing may change the actual origin, so adjust our
// origin offset accordingly
Rectangle visible = getClippingRect(component, decorated);
Rectangle clipRect = decorated.intersection(visible);
if (decorated.x < visible.x)
originOffset.x += visible.x - decorated.x;
if (decorated.y < visible.y)
originOffset.y += visible.y - decorated.y;
return clipRect;
}
/**
* Return any clipping rectangle detected above the given component, in the
* coordinate space of the given component. The given rectangle is desired
* to be visible.
*/
private Rectangle getClippingRect(Container component, Rectangle desired) {
Rectangle clip = component instanceof JComponent ? ((JComponent) component)
.getVisibleRect()
: new Rectangle(0, 0, component.getWidth(), component.getHeight());
if (desired.x >= clip.x && desired.y >= clip.y
&& desired.x + desired.width <= clip.x + clip.width
&& desired.y + desired.height <= clip.y + clip.height) {
// desired rect is within the current clip rect
} else if (component.getParent() != null) {
// Only apply the clip if it is actually smaller than the
// component's visible area
if (component != painter.getParent() && clip.x > 0 && clip.y > 0
&& clip.width < component.getWidth() && clip.height < component.getHeight()) {
// Don't alter the original rectangle
desired = new Rectangle(desired);
// Check for clipping further up the hierarchy
desired.x += component.getX();
desired.y += component.getY();
clip = getClippingRect(component.getParent(), desired);
clip.x -= component.getX();
clip.y -= component.getY();
}
}
return clip;
}
/**
* Return the bounds, relative to the decorated component, of the
* decoration. The default covers the entire component. Note that this
* method will be called from the constructor, so be careful when overriding
* and referencing derived class state.
*/
protected Rectangle getDecorationBounds() {
return bounds != DEFAULT_BOUNDS ? bounds : new Rectangle(0, 0, component.getWidth(),
component.getHeight());
}
/**
* Change the bounds of the decoration, relative to the decorated component.
* The special value {@link #DEFAULT_BOUNDS} means the bounds will track the
* component bounds.
*/
public void setDecorationBounds(Rectangle bounds) {
if (bounds == DEFAULT_BOUNDS) {
this.bounds = bounds;
} else {
this.bounds = new Rectangle(bounds);
}
synch();
}
/**
* Change the bounds of the decoration, relative to the decorated component.
*/
public void setDecorationBounds(int x, int y, int w, int h) {
setDecorationBounds(new Rectangle(x, y, w, h));
}
protected void setPainterBounds(int x, int y, int w, int h) {
painter.setLocation(x, y);
painter.setSize(w, h);
repaint();
}
protected JComponent getComponent() {
return component;
}
protected JComponent getPainter() {
return painter;
}
/** Set the cursor to appear anywhere over the decoration bounds. */
public void setCursor(Cursor cursor) {
painter.setCursor(cursor);
}
/** Force a refresh of the underlying component and its decoration. */
public void repaint() {
component.repaint();
painter.repaint();
}
/** Stop decorating. */
public void dispose() {
component.removeHierarchyListener(listener);
component.removeComponentListener(listener);
component.removePropertyChangeListener(listener);
if (parent != null) {
parent.removeComponentListener(listener);
parent = null;
}
Container painterParent = painter.getParent();
if (painterParent != null) {
Rectangle bounds = painter.getBounds();
painterParent.remove(painter);
painterParent.repaint(bounds.x, bounds.y, bounds.width, bounds.height);
}
component.repaint();
component = null;
}
/**
* Define the decoration's appearance. The point (0,0) represents the upper
* left corner of the decorated component. The default clip mask will be the
* extents of the decoration bounds, as indicated by
* {@link #getDecorationBounds()}, which defaults to the decorated component
* bounds.
*/
public abstract void paint(Graphics g);
public String toString() {
return super.toString() + " on " + getComponent();
}
private static Field nComponents;
static {
try {
nComponents = Container.class.getDeclaredField("ncomponents");
nComponents.setAccessible(true);
} catch (Exception e) {
nComponents = null;
}
}
private static boolean useSimpleBackground() {
return nComponents == null;
}
/** Used to hook into the Swing painting architecture. */
private class Painter extends JComponent {
private int base;
private Cursor cursor;
public JComponent getComponent() {
return AbstractComponentDecorator.this.getComponent();
}
public void setDecoratedLayer(int base) {
this.base = base;
}
public int getDecoratedLayer() {
return base;
}
public boolean isBackgroundDecoration() {
return layerOffset < 0;
}
/** Set the cursor to something else. */
public void setCursor(Cursor cursor) {
Cursor oldCursor = getCursor();
// Make sure the cursor actually changed, otherwise
// we get cursor flicker (notably on w32 title bars)
if (oldCursor == null && cursor != null || oldCursor != null
&& !oldCursor.equals(cursor)) {
this.cursor = cursor;
super.setCursor(cursor);
}
}
/**
* Returns the cursor of the decorated component, or the last cursor set
* by {@link #setCursor}.
*/
public Cursor getCursor() {
return cursor != null ? cursor : component.getCursor();
}
/**
* Delegate to the containing decorator to perform the paint.
*/
public void paint(Graphics g) {
if (!component.isShowing())
return;
Graphics g2 = g.create();
g2.translate(-originOffset.x, -originOffset.y);
AbstractComponentDecorator.this.paint(g2);
g2.dispose();
/*
* g = g.create(); g.setClip(null); g.setColor(Color.red);
* g.drawRect(0, 0, getWidth()-1, getHeight()-1);
*/
}
/**
* Provide a decorator-specific tooltip, shown when within the
* decorator's bounds.
*/
public String getToolTipText(MouseEvent e) {
return AbstractComponentDecorator.this.getToolTipText(e);
}
public String toString() {
return "Painter for " + AbstractComponentDecorator.this;
}
}
/**
* Provides a shared background painting mechanism for multiple decorations.
* This ensures that the background is only painted once if more than one
* background decorator is applied.
*/
private static class BackgroundPainter extends AbstractComponentDecorator {
private static String key(int layer) {
return "backgroundPainter for layer " + layer;
}
private String key;
private int layer;
public BackgroundPainter(JLayeredPane p, int layer) {
super(p, 0, TOP);
this.layer = layer;
key = key(layer);
p.putClientProperty(key, this);
}
private int hideChildren(Container c) {
if (c == null)
return 0;
int value = c.getComponentCount();
try {
nComponents.set(c, new Integer(0));
} catch (Exception e) {
return c.getComponentCount();
}
return value;
}
private void restoreChildren(Container c, int count) {
if (c != null) {
try {
nComponents.set(c, new Integer(count));
} catch (Exception e) {
}
}
}
private void paintBackground(Graphics g, Component parent, JComponent jc) {
int x = jc.getX();
int y = jc.getY();
int w = jc.getWidth();
int h = jc.getHeight();
paintBackground(g.create(x, y, w, h), jc);
}
private void paintBackground(Graphics g, JComponent jc) {
if (jc.isOpaque()) {
if (useSimpleBackground()) {
g.setColor(jc.getBackground());
g.fillRect(0, 0, jc.getWidth(), jc.getHeight());
} else {
int count = hideChildren(jc);
boolean db = jc.isDoubleBuffered();
if (db)
jc.setDoubleBuffered(false);
jc.paint(g);
if (db)
jc.setDoubleBuffered(true);
restoreChildren(jc, count);
}
}
Component[] kids = jc.getComponents();
for (int i = 0; i < kids.length; i++) {
if (kids[i] instanceof JComponent) {
paintBackground(g, jc, (JComponent) kids[i]);
}
}
}
private List findOpaque(Component root) {
List list = new ArrayList();
if (root.isOpaque() && root instanceof JComponent) {
list.add(root);
((JComponent) root).setOpaque(false);
}
if (root instanceof Container) {
Component[] kids = ((Container) root).getComponents();
for (int i = 0; i < kids.length; i++) {
list.addAll(findOpaque(kids[i]));
}
}
return list;
}
private List findDoubleBuffered(Component root) {
List list = new ArrayList();
if (root.isDoubleBuffered() && root instanceof JComponent) {
list.add(root);
((JComponent) root).setDoubleBuffered(false);
}
if (root instanceof Container) {
Component[] kids = ((Container) root).getComponents();
for (int i = 0; i < kids.length; i++) {
list.addAll(findDoubleBuffered(kids[i]));
}
}
return list;
}
private void paintForeground(Graphics g, JComponent jc) {
List opaque = findOpaque(jc);
List db = findDoubleBuffered(jc);
jc.paint(g);
for (Iterator i = opaque.iterator(); i.hasNext();) {
((JComponent) i.next()).setOpaque(true);
}
for (Iterator i = db.iterator(); i.hasNext();) {
((JComponent) i.next()).setDoubleBuffered(true);
}
}
/** Walk the list of "background" decorators and paint them. */
public void paint(Graphics g) {
JLayeredPane lp = (JLayeredPane) getComponent();
Component[] kids = lp.getComponents();
// Construct an area of the intersection of all decorators
Area area = new Area();
List painters = new ArrayList();
List components = new ArrayList();
for (int i = kids.length - 1; i >= 0; i--) {
if (kids[i] instanceof Painter) {
Painter p = (Painter) kids[i];
if (p.isBackgroundDecoration() && p.getDecoratedLayer() == layer
&& p.isShowing()) {
painters.add(p);
area.add(new Area(p.getBounds()));
}
} else if (lp.getLayer(kids[i]) == layer && kids[i] instanceof JComponent) {
components.add(kids[i]);
}
}
if (painters.size() == 0) {
dispose();
return;
}
g.setClip(area);
// Paint background for that area
for (Iterator i = components.iterator(); i.hasNext();) {
JComponent c = (JComponent) i.next();
paintBackground(g, lp, c);
}
// Paint the bg decorators
for (Iterator i = painters.iterator(); i.hasNext();) {
Painter p = (Painter) i.next();
p.paint(g.create(p.getX(), p.getY(), p.getWidth(), p.getHeight()));
}
// Paint foreground for the area
for (Iterator i = components.iterator(); i.hasNext();) {
JComponent c = (JComponent) i.next();
paintForeground(g.create(c.getX(), c.getY(), c.getWidth(), c.getHeight()), c);
}
}
public void dispose() {
getComponent().putClientProperty(key, null);
super.dispose();
}
public String toString() {
return key + " on " + getComponent();
}
}
/** Tracks changes to component configuration. */
private final class Listener extends ComponentAdapter implements HierarchyListener,
PropertyChangeListener {
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0) {
attach();
}
}
public void propertyChange(PropertyChangeEvent e) {
if (JLayeredPane.LAYER_PROPERTY.equals(e.getPropertyName())) {
attach();
}
}
public void componentMoved(ComponentEvent e) {
// FIXME figure out why attach works and synch doesn't
// when painting a selection marquee over a decorated background
attach();
}
public void componentResized(ComponentEvent e) {
// FIXME figure out why attach works and synch doesn't
// when painting a selection marquee over a decorated background
attach();
}
public void componentHidden(ComponentEvent e) {
setVisible(false);
}
public void componentShown(ComponentEvent e) {
setVisible(true);
}
}
}
@@ -1,216 +0,0 @@
package org.diylc.utils.dnd;
/* Copyright 2006 Timothy Wall All Rights Reserved. */
import java.awt.AlphaComposite;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/**
* Provide a ghosted drag image which will appear on any instances of
* {@link RootPaneContainer} in the current VM. Its location in screen
* coordinates may be set via {@link #move}.
* <p>
* When the image is no longer needed, invoke {@link #dispose}, which hides the
* graphic immediately, or {@link #returnToOrigin}, which moves the image to its
* original location prior to invoking {@link #dispose}.
*/
public class GhostedDragImage extends AbstractComponentDecorator {
private Icon icon;
// drag origin, relative to drag source
private Point origin;
// current drag location, relative to drag source
private Point location;
// offset of the image from the cursor
private Point imageOffset;
private List ghosts = new ArrayList();
private Component dragSource;
private float ghostAlpha = 0.5f;
/**
* Create a ghosted drag image, using the given icon.
*
* @param dragSource
* source of the drag
* @param screenLocation
* screen location where the drag started
* @param icon
* image to be drawn
* @param imageOffset
* offset of the image from the cursor
*/
public GhostedDragImage(JComponent dragSource, Point screenLocation, Icon icon,
Point imageOffset) {
this(dragSource, dragSource.getRootPane().getLayeredPane(), screenLocation, icon,
imageOffset, true);
}
/**
* Create a ghosted drag image.
*
* @param dragSource
* source of the drag
* @param root
* layered pane on which ghosted image is drawn
* @param screenLocation
* initial location of image, in screen coordinates
* @param icon
* icon to use for the ghost image
* @param imageOffset
* offset of the image within the drag source
* @param trackFrames
* if true, creates additional ghosts for all extant frames which
* contain a {@link JLayeredPane} where the image can be painted.
*/
protected GhostedDragImage(JComponent dragSource, JLayeredPane root, Point screenLocation,
Icon icon, Point imageOffset, boolean trackFrames) {
super(root);
this.dragSource = dragSource;
this.icon = icon;
this.imageOffset = imageOffset;
Point loc = root.getLocationOnScreen();
setLocation(screenLocation.x - loc.x + imageOffset.x, screenLocation.y - loc.y
+ imageOffset.y);
if (trackFrames) {
Window w = SwingUtilities.getWindowAncestor(root);
Frame[] frames = Frame.getFrames();
// Log.debug("track " + frames.length + " other frames");
for (int i = 0; i < frames.length; i++) {
Frame frame = frames[i];
if (frame instanceof RootPaneContainer && frame.isShowing() && frame != w) {
// Log.debug("Track " + frame);
JLayeredPane p = ((RootPaneContainer) frame).getLayeredPane();
GhostedDragImage slave = new GhostedDragImage(dragSource, p, screenLocation,
icon, imageOffset, false);
ghosts.add(slave);
slave.move(screenLocation);
}
}
}
}
/** Set the transparency of the ghosted image. */
public void setAlpha(float alpha) {
ghostAlpha = alpha;
}
/**
* Ensure the decorator cursor matches the drag cursor, or we get cursor
* flicker when autoscrolling.
*/
public void setCursor(Cursor cursor) {
super.setCursor(cursor);
for (Iterator i = ghosts.iterator(); i.hasNext();) {
GhostedDragImage slave = (GhostedDragImage) i.next();
slave.setCursor(cursor);
}
}
/** Make all ghosted images go away. */
public void dispose() {
location = origin;
super.dispose();
for (Iterator i = ghosts.iterator(); i.hasNext();) {
GhostedDragImage slave = (GhostedDragImage) i.next();
slave.dispose();
}
}
/**
* Sets the location of the decoration within the layered pane. Keeps track
* of the location relative to the drag source to facilitate moving back
* with {@link #returnToOrigin}.
*/
private void setLocation(int x, int y) {
location = SwingUtilities.convertPoint(getComponent(), x, y, dragSource);
if (origin == null)
origin = location;
setDecorationBounds(x, y, icon.getIconWidth(), icon.getIconHeight());
}
// Setting this non-zero provides some buffer around the drag image
// which helps avoid cursor flicker as the cursor moves (especially
// repomgr, probably due to slow repaint times).
private static final int CURSOR_SIZE = 32;
/**
* Adjust the bounds of the painting component to allow some buffer to avoid
* cursor flicker when moving.
*/
protected Rectangle clipDecorationBounds(Rectangle decorated) {
decorated.x -= CURSOR_SIZE;
decorated.y -= CURSOR_SIZE;
decorated.width += CURSOR_SIZE * 2;
decorated.height += CURSOR_SIZE * 2;
return super.clipDecorationBounds(decorated);
}
/**
* Move the ghosted image to the requested location.
*
* @param screen
* Where to draw the image, in screen coordinates
*/
public void move(Point screen) {
// Log.debug("Move to " + screen);
Point loc = getComponent().getLocationOnScreen();
setLocation(screen.x - loc.x + imageOffset.x, screen.y - loc.y + imageOffset.y);
for (Iterator i = ghosts.iterator(); i.hasNext();) {
GhostedDragImage g = (GhostedDragImage) i.next();
// Log.debug("Move on other frame");
g.move(screen);
}
}
/** Paint the supplied image with transparency. */
public void paint(Graphics graphics) {
Rectangle r = getDecorationBounds();
Graphics2D g = (Graphics2D) graphics.create();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, ghostAlpha));
g.translate(CURSOR_SIZE, CURSOR_SIZE);
icon.paintIcon(getPainter(), g, r.x, r.y);
g.dispose();
}
private static final int SLIDE_INTERVAL = 1000 / 24;
/** Animate the ghosted image returning to its origin. */
public void returnToOrigin() {
setCursor(null);
final Timer timer = new Timer(SLIDE_INTERVAL, null);
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int dx = (origin.x - location.x) / 2;
int dy = (origin.y - location.y) / 2;
if (dx != 0 || dy != 0) {
Point loc = dragSource.getLocationOnScreen();
Point where = new Point(loc.x + location.x + dx - imageOffset.x, loc.y
+ location.y + dy - imageOffset.y);
move(where);
} else {
timer.stop();
dispose();
}
}
});
timer.start();
}
}
-11
View File
@@ -1,11 +0,0 @@
package org.diylc;
import java.util.List;
import org.diylc.plugins.online.model.ProjectEntity;
import com.diyfever.httpproxy.ParamName;
public interface ProjectSearch {
List<ProjectEntity> project_search(@ParamName("criteria") String criteria);
}
-38
View File
@@ -1,38 +0,0 @@
package org.diylc;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.BasicConfigurator;
import org.diylc.plugins.online.model.ProjectEntity;
import com.diyfever.httpproxy.ParamName;
import com.diyfever.httpproxy.PhpFlatProxy;
import com.diyfever.httpproxy.ProxyFactory;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// XStream xstream = new XStream(new JettisonMappedXmlDriver());
// xstream.setMode(XStream.NO_REFERENCES);
//
// List<ProjectEntity> projects = new ArrayList<ProjectEntity>();
// // projects.add(new ProjectEntity(1, "first project", "some text",
// // "bancika", "some category"));
// // projects.add(new ProjectEntity(2, "second project", "some text",
// // "bancika", "some category"));
// System.out.println(xstream.toXML(projects));
BasicConfigurator.configure();
ProjectSearch search = new ProxyFactory(new PhpFlatProxy()).createProxy(
ProjectSearch.class, "http://host07.dwhost.net/~diyfever/diylc/db/");
List<ProjectEntity> results = search.project_search("TestProject");
System.out.println(results);
}
}
-7
View File
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/DIYLC"/>
<classpathentry kind="output" path="bin"/>
</classpath>
Binary file not shown.
@@ -1,108 +0,0 @@
package org.diylc.components.misc;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Rectangle2D;
import org.diylc.components.AbstractComponent;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Project Information", author = "Branislav Stojkovic", category = "Misc", description = "Draws a box with general project information", instanceNamePrefix = "BOM", zOrder = IDIYComponent.ABOVE_COMPONENT, stretchable = false)
public class ProjectInformation extends AbstractComponent<Void> {
public static Size DEFAULT_SIZE = new Size(10d, SizeUnit.cm);
public static Color COLOR = Color.black;
public static String DEFAULT_TEXT = "No components to show in the Bill of Materials";
private static final long serialVersionUID = 1L;
private Point point = new Point(0, 0);
@Override
public void draw(Graphics2D g2d, ComponentState componentState, Project project,
IDrawingObserver drawingObserver) {
g2d.setFont(LABEL_FONT);
g2d.setColor(componentState == ComponentState.DRAGGING
|| componentState == ComponentState.SELECTED ? SELECTION_COLOR : COLOR);
// FontMetrics fontMetrics = g2d.getFontMetrics();
g2d.drawString(project.getTitle(), point.x, point.y);
}
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.setColor(Color.white);
g2d.fillRect(width / 8, 0, 6 * width / 8, height - 1);
g2d.setColor(Color.black);
g2d.drawRect(width / 8, 0, 6 * width / 8, height - 1);
g2d.setFont(LABEL_FONT.deriveFont(1f * 9 * width / 32).deriveFont(Font.PLAIN));
FontMetrics fontMetrics = g2d.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds("BOM", g2d);
int textHeight = (int) (rect.getHeight());
int textWidth = (int) (rect.getWidth());
// Center text horizontally and vertically.
int x = (width - textWidth) / 2 + 1;
int y = textHeight + 2;
g2d.drawString("BOM", x, y);
g2d.setFont(g2d.getFont().deriveFont(1f * 5 * width / 32));
fontMetrics = g2d.getFontMetrics();
rect = fontMetrics.getStringBounds("resistors", g2d);
x = (width - textWidth) / 2 + 1;
y = height / 2 + 2;
g2d.drawString("resistors", x, y);
y += rect.getHeight() - 1;
g2d.drawString("tubes", x, y);
y += rect.getHeight() - 1;
g2d.drawString("diodes", x, y);
}
@Override
public int getControlPointCount() {
return 1;
}
@Override
public Point getControlPoint(int index) {
return point;
}
@Override
public boolean isControlPointSticky(int index) {
return false;
}
@Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.NEVER;
}
@Override
public void setControlPoint(Point point, int index) {
this.point.setLocation(point);
}
@Deprecated
@Override
public Void getValue() {
return null;
}
@Override
public void setValue(Void value) {
}
}
@@ -1,102 +0,0 @@
package org.diylc.components.passive;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import org.diylc.components.AbstractLeadedComponent;
import org.diylc.core.CreationMethod;
import org.diylc.core.IDIYComponent;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Capacitance;
import org.diylc.core.measures.CapacitanceUnit;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Electrolytic Capacitor", author = "Branislav Stojkovic", category = "Passive", creationMethod = CreationMethod.POINT_BY_POINT, instanceNamePrefix = "C", description = "test", zOrder = IDIYComponent.COMPONENT)
public class ElectrolyticRadial extends AbstractLeadedComponent<Capacitance> {
private static final long serialVersionUID = 1L;
public static Size DEFAULT_SIZE = new Size(1d / 2, SizeUnit.in);
public static Color BODY_COLOR = Color.decode("#27408B");
public static Color BORDER_COLOR = BODY_COLOR.darker();
public static Color COVER_COLOR = Color.decode("#C3E4ED");
private Capacitance value = new Capacitance(1d, CapacitanceUnit.uF);
public ElectrolyticRadial() {
super();
}
@EditableProperty
public Capacitance getValue() {
return value;
}
public void setValue(Capacitance value) {
this.value = value;
}
public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.setColor(BODY_COLOR);
g2d.fillOval(6, 6, width - 12, width - 12);
g2d.setColor(BORDER_COLOR);
g2d.drawOval(6, 6, width - 12, width - 12);
}
@Override
protected void decorateComponentBody(Graphics2D g2d) {
int totalDiameter = getClosestOdd(getWidth().convertToPixels());
int coverDiameter = getClosestOdd(totalDiameter * 3 / 4);
g2d.setColor(COVER_COLOR);
int position = (totalDiameter - coverDiameter) / 2;
g2d.fillOval(position, position, coverDiameter, coverDiameter);
g2d.setColor(COVER_COLOR.darker());
g2d.drawLine(position + coverDiameter / 5, position + coverDiameter / 5, position + 4
* coverDiameter / 5, position + 4 * coverDiameter / 5);
g2d.drawLine(position + coverDiameter / 5, position + 4 * coverDiameter / 5, position + 4
* coverDiameter / 5, position + coverDiameter / 5);
}
@Override
protected Size getDefaultHeight() {
return null;
}
@Deprecated
@Override
public Size getHeight() {
return super.getHeight();
}
@Override
protected Size getDefaultWidth() {
// We'll reuse width property to set the diameter.
return DEFAULT_SIZE;
}
@EditableProperty(name = "Diameter")
@Override
public Size getWidth() {
return super.getWidth();
}
@Override
protected Color getDefaultBodyColor() {
return BODY_COLOR;
}
@Override
protected Color getDefaultBorderColor() {
return BORDER_COLOR;
}
@Override
protected Shape getBodyShape() {
return new Ellipse2D.Double(0f, 0f, getClosestOdd(getWidth().convertToPixels()),
getClosestOdd(getWidth().convertToPixels()));
}
}
@@ -1,78 +0,0 @@
package org.diylc.components.passive;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import org.diylc.components.AbstractLeadedComponent;
import org.diylc.core.CreationMethod;
import org.diylc.core.IDIYComponent;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Resistance;
import org.diylc.core.measures.ResistanceUnit;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Resistor", author = "Branislav Stojkovic", category = "Passive", creationMethod = CreationMethod.POINT_BY_POINT, instanceNamePrefix = "R", description = "test", zOrder = IDIYComponent.COMPONENT)
public class Resistor extends AbstractLeadedComponent<Resistance> {
private static final long serialVersionUID = 1L;
public static Size DEFAULT_WIDTH = new Size(1d / 2, SizeUnit.in);
public static Size DEFAULT_HEIGHT = new Size(1d / 8, SizeUnit.in);
public static Color BODY_COLOR = Color.decode("#82CFFD");
public static Color BORDER_COLOR = BODY_COLOR.darker();
private Resistance value = new Resistance(123d, ResistanceUnit.K);
public Resistor() {
super();
}
@EditableProperty
public Resistance getValue() {
return value;
}
public void setValue(Resistance value) {
this.value = value;
}
public void drawIcon(Graphics2D g2d, int width, int height) {
g2d.rotate(-Math.PI / 4, width / 2, height / 2);
g2d.setColor(LEAD_COLOR);
g2d.drawLine(0, height / 2, width, height / 2);
g2d.setColor(BODY_COLOR);
g2d.fillRect(4, height / 2 - 3, width - 8, 6);
g2d.setColor(BORDER_COLOR);
g2d.drawRect(4, height / 2 - 3, width - 8, 6);
}
@Override
protected Size getDefaultHeight() {
return DEFAULT_HEIGHT;
}
@Override
protected Size getDefaultWidth() {
return DEFAULT_WIDTH;
}
@Override
protected Color getDefaultBodyColor() {
return BODY_COLOR;
}
@Override
protected Color getDefaultBorderColor() {
return BORDER_COLOR;
}
@Override
protected Shape getBodyShape() {
return new Rectangle2D.Double(0f, 0f, getWidth().convertToPixels(),
getClosestOdd(getHeight().convertToPixels()));
}
}
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/log4j-1.2.15.jar"/>
<classpathentry kind="lib" path="lib/xstream-1.3.1.jar"/>
<classpathentry kind="lib" path="lib/junit-4.7.jar"/>
<classpathentry kind="lib" path="library/main.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/app-framework"/>
<classpathentry kind="lib" path="lib/jettison-1.0.1.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>DIYLC</name>
<name>diylc-core</name>
<comment></comment>
<projects>
</projects>
+82
View File
@@ -0,0 +1,82 @@
<project name="diylc-core" basedir="." default="jar">
<property name="src.dir" value="src" />
<property name="lib.dir" value="${basedir}/lib" />
<property name="build.dir" value="${basedir}/build" />
<property name="jar.dir" value="${build.dir}/jar" />
<property name="report.dir" value="${build.dir}/junitreport" />
<property name="classes.dir" value="${build.dir}/temp/${ant.project.name}/classes" />
<property name="test.classes.dir" value="${build.dir}/temp/${ant.project.name}/test.classes" />
<target name="clean">
<delete dir="${build.dir}" />
</target>
<!--change src dir-->
<target name="compile">
<mkdir dir="${classes.dir}" />
<echo>Compile with JDK ${java.runtime.version}</echo>
<javac encoding="8859_1" srcdir="${src.dir}" destdir="${classes.dir}" classpathref="class.path" />
</target>
<target name="resource.copy">
<copy todir="${classes.dir}">
<fileset dir="${src.dir}">
<exclude name="**/*.java" />
</fileset>
</copy>
</target>
<target name="lib.copy">
<copy todir="${jar.dir}/lib" overwrite="true">
<fileset dir="${basedir}/lib">
<exclude name="**/*dll" />
</fileset>
</copy>
<copy todir="${jar.dir}/library" overwrite="true">
<fileset dir="${basedir}/library">
<exclude name="**/*dll" />
</fileset>
</copy>
<copy todir="${jar.dir}" overwrite="true">
<fileset dir="${basedir}/lib/" includes="**/*.dll" />
</copy>
</target>
<path id="class.path">
<fileset dir="${basedir}">
<include name="lib/**/*.jar" />
<include name="library/**/*.jar" />
</fileset>
</path>
<manifestclasspath jarfile="${ant.project.name}.jar" property="manifest.class.path">
<classpath refid="class.path" />
</manifestclasspath>
<target name="jar" depends="clean, lib.copy, resource.copy, compile">
<jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
<manifest>
<attribute name="Built-By" value="${user.name}" />
<attribute name="Class-Path" value="${manifest.class.path}" />
</manifest>
</jar>
<copy todir="../diylc-swing/lib" overwrite="true">
<fileset dir="${jar.dir}" includes="${ant.project.name}.jar" />
</copy>
<copy todir="../diylc-library/lib" overwrite="true">
<fileset dir="${jar.dir}" includes="${ant.project.name}.jar" />
</copy>
</target>
<target name="javadoc">
<javadoc access="public" author="true" classpathref="class.path" destdir="doc" nodeprecated="false" nodeprecatedlist="false" noindex="false" nonavbar="false" notree="false" source="1.6" splitindex="true" use="true" version="true">
<fileset dir="${src.dir}">
<exclude name="**\.svn\**" />
<include name="**/*.java" />
</fileset>
</javadoc>
</target>
</project>
Binary file not shown.
@@ -4,6 +4,7 @@ import javax.swing.Icon;
import org.diylc.core.CreationMethod;
import org.diylc.core.IDIYComponent;
import org.diylc.core.annotations.BomPolicy;
/**
* Entity class used to describe a component type.
@@ -23,11 +24,14 @@ public class ComponentType {
private Icon icon;
private Class<? extends IDIYComponent<?>> instanceClass;
private double zOrder;
private boolean flexibleZOrder;
private boolean stretchable;
private BomPolicy bomPolicy;
public ComponentType(String name, String description, CreationMethod creationMethod,
String category, String namePrefix, String author, Icon icon,
Class<? extends IDIYComponent<?>> instanceClass, double zOrder, boolean stretchable) {
Class<? extends IDIYComponent<?>> instanceClass, double zOrder, boolean flexibleZOrder,
boolean stretchable, BomPolicy bomPolicy) {
super();
this.name = name;
this.description = description;
@@ -38,7 +42,9 @@ public class ComponentType {
this.icon = icon;
this.instanceClass = instanceClass;
this.zOrder = zOrder;
this.flexibleZOrder = flexibleZOrder;
this.stretchable = stretchable;
this.bomPolicy = bomPolicy;
}
public String getName() {
@@ -76,10 +82,18 @@ public class ComponentType {
public double getZOrder() {
return zOrder;
}
public boolean isFlexibleZOrder() {
return flexibleZOrder;
}
public boolean isStretchable() {
return stretchable;
}
public BomPolicy getBomPolicy() {
return bomPolicy;
}
@Override
public String toString() {
@@ -32,5 +32,9 @@ public enum DrawOption {
/**
* Anti-aliasing is used when drawing.
*/
ANTIALIASING;
ANTIALIASING,
/**
* Draw components in outline mode.
*/
OUTLINE_MODE;
}
@@ -48,10 +48,6 @@ public enum EventType {
* object containing selection size (x = width, y = height). Size is
* expressed in the default measure (cm for metric, inches for imperial).
*/
SELECTION_SIZE_CHANGED,
/**
* Called when display needs to be repainted. No parameters are passed.
*/
REPAINT,
/**
* Called when new component slot has been changed. The only parameter is
@@ -76,6 +72,12 @@ public enum EventType {
* current cursor location (not taking zoom into account).
*/
MOUSE_MOVED,
LAYER_STATE_CHANGED;
;
/**
* 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;
}
@@ -0,0 +1,5 @@
package org.diylc.common;
public enum HorizontalAlignment {
LEFT, CENTER, RIGHT
}
@@ -0,0 +1,22 @@
package org.diylc.common;
public interface IKeyProcessor {
public static final int VK_LEFT = 0x25;
public static final int VK_UP = 0x26;
public static final int VK_RIGHT = 0x27;
public static final int VK_DOWN = 0x28;
/**
* Notifies the presenter that a key hes been pressed on the canvas.
*
* @param key
* @param ctrlDown
* @param shiftDown
* @param altDown
*
* @return true if the event should be consumed
*/
boolean keyPressed(int key, boolean ctrlDown, boolean shiftDown,
boolean altDown);
}
@@ -0,0 +1,69 @@
package org.diylc.common;
import java.awt.Point;
public interface IMouseProcessor {
/**
* Notifies the presenter that mouse is clicked.
*
* Note: point coordinates are display based, i.e. scaled for zoom factor.
*
* @param point
* @param button
* @param ctrlDown
* @param shiftDown
* @param altDown
* @param clickCount
*/
void mouseClicked(Point point, int button, boolean ctrlDown, boolean shiftDown, boolean altDown,
int clickCount);
/**
* 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);
/**
* Notification that drag has been started from the specified point.
*
* Note: point coordinates are scaled for zoom factor.
*
* @param point
* @param dragAction
*/
void dragStarted(Point point, int dragAction);
/**
* 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);
/**
* Changes the current drag action during the dragging.
*
* @param dragAction
*/
void dragActionChanged(int dragAction);
/**
* Notification that drag has been ended in the specified point.
*
* Note: point coordinates are scaled for zoom factor.
*
* @param point
*/
void dragEnded(Point point);
}
@@ -1,6 +1,6 @@
package org.diylc.common;
import com.diyfever.gui.simplemq.IMessageListener;
import org.diylc.appframework.simplemq.IMessageListener;
/**
* Interface for plug-ins.
@@ -4,22 +4,17 @@ 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 javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.JPopupMenu.Separator;
import org.diylc.appframework.simplemq.IMessageListener;
import org.diylc.appframework.simplemq.MessageDispatcher;
import org.diylc.appframework.update.VersionNumber;
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;
import org.diylc.core.Theme;
/**
* Interface for communication between plug-ins and the application. Plug-ins
@@ -33,9 +28,33 @@ import com.diyfever.gui.update.VersionNumber;
* @see IMessageListener
* @see EventType
*/
public interface IPlugInPort {
public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyProcessor {
public static final String ANTI_ALIASING_KEY = "antiAliasing";
public static final String HI_QUALITY_RENDER_KEY = "hiQualityRender";
public static final String EXPORT_GRID_KEY = "exportGrid";
public static final String STICKY_POINTS_KEY = "stickyPoints";
public static final String METRIC_KEY = "metric";
public static final String SNAP_TO_GRID_KEY = "snapToGrid";
public static final String AUTO_PADS_KEY = "autoCreatePads";
public static final String CONTINUOUS_CREATION_KEY = "continuousCreation";
public static final String AUTO_EDIT_KEY = "autoEdit";
public static final String ABNORMAL_EXIT_KEY = "abnormalExit";
public static final String WHEEL_ZOOM_KEY = "wheelZoom";
public static final String OUTLINE_KEY = "outline";
public static final String THEME_KEY = "theme";
public static final String RECENT_COMPONENTS_KEY = "recentComponents";
public static final int DND_TOGGLE_STICKY = 0x1;
public static final int DND_TOGGLE_SNAP = 0x40000000;
public static final String CHECK_BOX_MENU_ITEM = "org.diylc.checkBoxMenuItem";
/**
* Mouse button constants.
*/
public static final int NOBUTTON = 0;
public static final int BUTTON1 = 1;
public static final int BUTTON2 = 2;
public static final int BUTTON3 = 3;
/**
* Returns size of the canvas that takes project dimensions into account as
@@ -91,8 +110,9 @@ public interface IPlugInPort {
* Saves the current project into the specified file.
*
* @param fileName
* @param isBackup
*/
void saveProjectToFile(String fileName);
void saveProjectToFile(String fileName, boolean isBackup);
/**
* @return the current file name.
@@ -132,49 +152,6 @@ public interface IPlugInPort {
*/
void draw(Graphics2D g2d, Set<DrawOption> drawOptions, IComponentFiler filter);
/**
* 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);
Double[] getAvailableZoomLevels();
/**
@@ -193,73 +170,6 @@ public interface IPlugInPort {
*/
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 ComponentSelection}.
*
* @return
*/
ComponentSelection 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.
*
@@ -308,14 +218,7 @@ public interface IPlugInPort {
*/
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);
void editSelection();
/**
* @return a list of editable properties of the current project.
@@ -328,6 +231,11 @@ public interface IPlugInPort {
* @param properties
*/
void applyPropertiesToProject(List<PropertyWrapper> properties);
/**
* Gets the current new component slot.
*/
ComponentType getNewComponentTypeSlot();
/**
* Sets the new component slot. Specified component type will be used to
@@ -351,6 +259,53 @@ public interface IPlugInPort {
* 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();
/**
* Causes the display to refresh.
*/
void refresh();
/**
* @return currently selected theme.
*/
Theme getSelectedTheme();
/**
* Changes the current theme.
*
* @param theme
*/
void setSelectedTheme(Theme theme);
/**
* Renumbers all the selected components.
*
* @param xAxisFirst
*/
void renumberSelectedComponents(boolean xAxisFirst);
}
@@ -0,0 +1,48 @@
package org.diylc.common;
import java.awt.Point;
import java.util.List;
import org.diylc.core.ExpansionMode;
import org.diylc.core.IDIYComponent;
public interface ISelectionProcessor {
/**
* Returns the current {@link ComponentTransferable}.
*
* @return
*/
List<IDIYComponent<?>> getSelectedComponents();
/**
* Updates the selection with the specified list of component. Also, updates
* control point map with all components that are stuck to the newly
* selected components.
*
* @param newSelection
*/
void updateSelection(List<IDIYComponent<?>> newSelection);
/**
* Finds all components at the specified location, sorted by z-index from
* top to bottom.
*
* @param point
* @return
*/
List<IDIYComponent<?>> findComponentsAt(Point point);
/**
* Expands the current selection to include surrounding components.
* Options are controlled with <code>expansionMode</code> flag.
*
* @param expansionMode
*/
void expandSelection(ExpansionMode expansionMode);
/**
* Selects all components in the project.
*/
void selectAll();
}
@@ -0,0 +1,34 @@
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);
}
@@ -0,0 +1,11 @@
package org.diylc.common;
public enum LabelPosition {
ABOVE, BELOW;
@Override
public String toString() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
@@ -32,7 +32,7 @@ public class ObjectCache {
if (basicStrokeMap.containsKey(width)) {
return basicStrokeMap.get(width);
}
Stroke stroke = new BasicStroke(width);
Stroke stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
basicStrokeMap.put(width, stroke);
return stroke;
}
@@ -0,0 +1,11 @@
package org.diylc.common;
public enum OrientationHV {
VERTICAL, HORIZONTAL;
@Override
public String toString() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
@@ -1,7 +1,8 @@
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.
@@ -14,23 +15,28 @@ public class PropertyWrapper implements Cloneable {
private String name;
private Class<?> type;
private Object value;
private Method setter;
private Method getter;
private String setter;
private String getter;
private boolean defaultable;
private IPropertyValidator validator;
private boolean unique = true;
private boolean changed = false;
public PropertyWrapper(String name, Class<?> type, Method getter, Method setter,
boolean defaultable) {
public PropertyWrapper(String name, Class<?> type, String getter,
String 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);
IllegalAccessException, InvocationTargetException,
SecurityException, NoSuchMethodException {
this.value = object.getClass().getMethod(getter).invoke(object);
}
// public void readUniqueFrom(IDIYComponent component)
@@ -43,8 +49,9 @@ public class PropertyWrapper implements Cloneable {
// }
public void writeTo(Object object) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
setter.invoke(object, value);
IllegalAccessException, InvocationTargetException,
SecurityException, NoSuchMethodException {
object.getClass().getMethod(setter, type).invoke(object, this.value);
}
public String getName() {
@@ -67,8 +74,24 @@ public class PropertyWrapper implements Cloneable {
return defaultable;
}
public void setDefaultable(boolean defaultable) {
this.defaultable = defaultable;
public IPropertyValidator getValidator() {
return validator;
}
public boolean isUnique() {
return unique;
}
public void setUnique(boolean unique) {
this.unique = unique;
}
public boolean isChanged() {
return changed;
}
public void setChanged(boolean changed) {
this.changed = changed;
}
// @Override
@@ -81,6 +104,15 @@ public class PropertyWrapper implements Cloneable {
// }
// return new Property(name, type, value);
// }
@Override
public Object clone() throws CloneNotSupportedException {
PropertyWrapper clone = new PropertyWrapper(this.name, this.type, this.getter,
this.setter, this.defaultable, this.validator);
clone.value = this.value;
clone.changed = this.changed;
clone.unique = this.unique;
return clone;
}
@Override
public int hashCode() {
@@ -91,7 +123,6 @@ public class PropertyWrapper implements Cloneable {
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;
}
@@ -126,11 +157,6 @@ public class PropertyWrapper implements Cloneable {
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;
}
@@ -0,0 +1,14 @@
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();
}
}
@@ -0,0 +1,5 @@
package org.diylc.common;
public enum VerticalAlignment {
TOP, CENTER, BOTTOM
}
@@ -0,0 +1,181 @@
package org.diylc.components;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import org.diylc.common.HorizontalAlignment;
import org.diylc.common.VerticalAlignment;
import org.diylc.core.IDIYComponent;
import org.diylc.core.annotations.EditableProperty;
/**
* Abstract implementation of {@link IDIYComponent} that contains component name
* and toString.
*
* IMPORTANT: to improve performance, all fields except for <code>Point</code>
* and <code>Point</code> arrays should be immutable. Failing to comply with
* this can result in annoying and hard to trace bugs.
*
* @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, 14);
public static Color METAL_COLOR = Color.decode("#236B8E");
@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(double x) {
return ((int) x / 2) * 2 + 1;
}
/**
* @param clip
* @return true if none of the control points lie in the clip rectangle.
*/
protected boolean checkPointsClipped(Shape clip) {
for (int i = 0; i < getControlPointCount(); i++) {
if (clip.contains(getControlPoint(i))) {
return false;
}
}
return true;
}
protected void drawCenteredText(Graphics2D g2d, String text, int x, int y,
HorizontalAlignment horizontalAlignment,
VerticalAlignment verticalAlignment) {
FontMetrics fontMetrics = g2d.getFontMetrics();
Rectangle stringBounds = fontMetrics.getStringBounds(text, g2d)
.getBounds();
Font font = g2d.getFont();
FontRenderContext renderContext = g2d.getFontRenderContext();
GlyphVector glyphVector = font.createGlyphVector(renderContext, text);
Rectangle visualBounds = glyphVector.getVisualBounds().getBounds();
int textX = 0;
switch (horizontalAlignment) {
case CENTER:
textX = x - stringBounds.width / 2;
break;
case LEFT:
textX = x;
break;
case RIGHT:
textX = x - stringBounds.width;
break;
}
int textY = 0;
switch (verticalAlignment) {
case TOP:
textY = y + stringBounds.height;
break;
case CENTER:
textY = y - visualBounds.height / 2 - visualBounds.y;
break;
case BOTTOM:
textY = y - visualBounds.y;
break;
}
g2d.drawString(text, textX, textY);
}
@SuppressWarnings("unchecked")
public IDIYComponent<T> clone() throws CloneNotSupportedException {
try {
// Instantiate object of the same type
AbstractComponent<T> newInstance = (AbstractComponent<T>) this
.getClass().getConstructors()[0].newInstance();
Class<?> clazz = this.getClass();
while (AbstractComponent.class.isAssignableFrom(clazz)) {
Field[] fields = clazz.getDeclaredFields();
clazz = clazz.getSuperclass();
// fields = this.getClass().getDeclaredFields();
// Copy over all non-static, non-final fields that are declared
// in
// AbstractComponent or one of it's child classes
for (Field field : fields) {
if (!Modifier.isStatic(field.getModifiers())
&& !Modifier.isFinal(field.getModifiers())) {
field.setAccessible(true);
Object value = field.get(this);
// Deep copy point arrays.
// TODO: something nicer
if (value != null
&& value.getClass().isArray()
&& value.getClass().getComponentType()
.isAssignableFrom(Point.class)) {
Object newArray = Array.newInstance(value
.getClass().getComponentType(), Array
.getLength(value));
for (int i = 0; i < Array.getLength(value); i++) {
Point p = (Point) Array.get(value, i);
Array.set(newArray, i, new Point(p));
}
value = newArray;
}
// Deep copy points.
// TODO: something nicer
if (value != null && value instanceof Point) {
value = new Point((Point) value);
}
field.set(newInstance, value);
}
}
}
return newInstance;
} catch (Exception e) {
throw new CloneNotSupportedException("Could not clone the component. Reason: " + e.getMessage());
}
}
}
@@ -24,12 +24,15 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
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 Point[] controlPoints = new Point[] {
new Point(0, 0),
new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), 0),
new Point((int) (DEFAULT_SIZE.convertToPixels() / 2), (int) (DEFAULT_SIZE
.convertToPixels())),
new Point((int) DEFAULT_SIZE.convertToPixels(), (int) DEFAULT_SIZE.convertToPixels()) };
protected Color color = getDefaultColor();
protected PointCount pointCount = PointCount.FOUR;
/**
* Draws the specified curve onto graphics.
@@ -37,6 +40,7 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
* @param curve
* @param g2d
* @param componentState
* @param theme
*/
protected abstract void drawCurve(CubicCurve2D curve, Graphics2D g2d,
ComponentState componentState);
@@ -59,8 +63,11 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
}
@Override
public void draw(Graphics2D g2d, ComponentState componentState, Project project,
IDrawingObserver drawingObserver) {
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode,
Project project, IDrawingObserver drawingObserver) {
if (checkPointsClipped(g2d.getClip())) {
return;
}
if (componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING) {
// Do not track guidelines.
drawingObserver.stopTracking();
@@ -93,29 +100,133 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
g2d.setComposite(oldComposite);
}
@EditableProperty(name = "Point Count")
public PointCount getPointCount() {
if (pointCount == null) {
pointCount = PointCount.FOUR;
}
return pointCount;
}
public void setPointCount(PointCount pointCount) {
this.pointCount = pointCount;
// Reset control points.
for (int i = 0; i < getControlPointCount(); i++) {
setControlPoint(getControlPoint(i), i);
}
}
@Override
public int getControlPointCount() {
return controlPoints.length;
switch (getPointCount()) {
case TWO:
return 2;
case THREE:
return 3;
case FOUR:
return 4;
}
return 0;
}
@Override
public boolean isControlPointSticky(int index) {
return index == 0 || index == 3;
return index == 0 || index == getControlPointCount() - 1;
}
@Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return index == 0 || index == 3 ? VisibilityPolicy.ALWAYS : VisibilityPolicy.WHEN_SELECTED;
return VisibilityPolicy.WHEN_SELECTED;
}
@Override
public boolean canControlPointOverlap(int index) {
// Only shape control points may overlap.
switch (getPointCount()) {
case TWO:
return false;
case THREE:
return index == 1;
case FOUR:
return index == 1 || index == 2;
}
return false;
}
@Override
public Point getControlPoint(int index) {
if (index == 0) {
return controlPoints[0];
}
switch (getPointCount()) {
case TWO:
switch (index) {
case 1:
return controlPoints[3];
}
case THREE:
switch (index) {
case 1:
return controlPoints[1];
case 2:
return controlPoints[3];
}
case FOUR:
switch (index) {
case 1:
return controlPoints[1];
case 2:
return controlPoints[2];
case 3:
return controlPoints[3];
}
}
return controlPoints[index];
}
@Override
public void setControlPoint(Point point, int index) {
controlPoints[index].setLocation(point);
if (index == 0) {
controlPoints[0].setLocation(point);
} else {
switch (getPointCount()) {
case TWO:
switch (index) {
case 1:
Point center = new Point((point.x + controlPoints[0].x) / 2,
(point.y + controlPoints[0].y) / 2);
controlPoints[1].setLocation(center);
controlPoints[2].setLocation(center);
controlPoints[3].setLocation(point);
break;
}
break;
case THREE:
switch (index) {
case 1:
controlPoints[1].setLocation(point);
controlPoints[2].setLocation(point);
break;
case 2:
controlPoints[3].setLocation(point);
break;
}
break;
case FOUR:
switch (index) {
case 1:
controlPoints[1].setLocation(point);
break;
case 2:
controlPoints[2].setLocation(point);
break;
case 3:
controlPoints[3].setLocation(point);
break;
}
break;
}
}
}
@EditableProperty
@@ -127,4 +238,12 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
this.color = color;
}
enum PointCount {
TWO, THREE, FOUR;
@Override
public String toString() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
}
@@ -0,0 +1,350 @@
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.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.common.Display;
import org.diylc.common.IPlugInPort;
import org.diylc.common.ObjectCache;
import org.diylc.core.ComponentState;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project;
import org.diylc.core.Theme;
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;
/**
* 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((int) (DEFAULT_SIZE.convertToPixels() / 2), 0) };
protected Color bodyColor = Color.white;
protected Color borderColor = Color.black;
protected Color labelColor = LABEL_COLOR;
protected Display display = Display.VALUE;
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, boolean outlineMode,
Project project, IDrawingObserver drawingObserver) {
double distance = points[0].distance(points[1]);
Shape shape = getBodyShape();
// If there's no body, just draw the line connecting the ending points.
if (shape == null) {
drawLead(g2d, componentState);
} else if (supportsStandingMode()
&& length.convertToPixels() > points[0].distance(points[1])) {
// When ending points are too close draw the component in standing
// mode.
int width = getClosestOdd(this.width.convertToPixels());
Shape body = new Ellipse2D.Double(points[0].x - width / 2, points[0].y - width / 2,
width, width);
Composite oldComposite = g2d.getComposite();
if (alpha < MAX_ALPHA) {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha
/ MAX_ALPHA));
}
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
g2d.fill(body);
g2d.setComposite(oldComposite);
Color finalBorderColor;
if (outlineMode) {
Theme theme = (Theme) ConfigurationManager.getInstance().readObject(
IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
finalBorderColor = componentState == ComponentState.SELECTED
|| componentState == ComponentState.DRAGGING ? SELECTION_COLOR : theme
.getOutlineColor();
} else {
finalBorderColor = componentState == ComponentState.SELECTED
|| componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor;
}
g2d.setColor(finalBorderColor);
g2d.draw(body);
if (!outlineMode) {
drawLead(g2d, componentState);
}
} else {
// Normal mode with component body in the center and two lead parts.
Rectangle shapeRect = shape.getBounds();
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.
AffineTransform oldTransform = g2d.getTransform();
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));
}
if (bodyColor != null) {
if (bodyColor != null) {
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor);
g2d.fill(shape);
}
}
decorateComponentBody(g2d, outlineMode);
g2d.setComposite(oldComposite);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
Color finalBorderColor;
if (outlineMode) {
Theme theme = (Theme) ConfigurationManager.getInstance().readObject(
IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
finalBorderColor = componentState == ComponentState.SELECTED
|| componentState == ComponentState.DRAGGING ? SELECTION_COLOR : theme
.getOutlineColor();
} else {
finalBorderColor = componentState == ComponentState.SELECTED
|| componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor;
}
g2d.setColor(finalBorderColor);
g2d.draw(shape);
// Go back to the original transformation to draw leads.
if (!outlineMode) {
AffineTransform textTransform = g2d.getTransform();
g2d.setTransform(oldTransform);
if (length.convertToPixels() > points[0].distance(points[1])) {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
}
int leadThickness = getClosestOdd(getLeadThickness());
double leadLength = (distance - shapeRect.width) / 2 - leadThickness / 2;
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness));
Color leadColor = shouldShadeLeads() ? getLeadColor(componentState).darker()
: getLeadColor(componentState);
g2d.setColor(leadColor);
int endX = (int) (points[0].x + Math.cos(theta) * leadLength);
int endY = (int) Math.round(points[0].y + Math.sin(theta) * leadLength);
g2d.drawLine(points[0].x, points[0].y, endX, endY);
endX = (int) (points[1].x + Math.cos(theta - Math.PI) * leadLength);
endY = (int) Math.round(points[1].y + Math.sin(theta - Math.PI) * leadLength);
g2d.drawLine(points[1].x, points[1].y, endX, endY);
if (shouldShadeLeads()) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(leadThickness - 2));
leadColor = getLeadColor(componentState);
g2d.setColor(leadColor);
g2d.drawLine(points[0].x, points[0].y, (int) (points[0].x + Math.cos(theta)
* leadLength), (int) (points[0].y + Math.sin(theta) * leadLength));
g2d.drawLine(points[1].x, points[1].y, (int) (points[1].x + Math.cos(theta
- Math.PI)
* leadLength), (int) (points[1].y + Math.sin(theta - Math.PI)
* leadLength));
}
g2d.setComposite(oldComposite);
g2d.setTransform(textTransform);
}
// Draw label.
g2d.setFont(LABEL_FONT);
Color finalLabelColor;
if (outlineMode) {
Theme theme = (Theme) ConfigurationManager.getInstance().readObject(
IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
finalLabelColor = componentState == ComponentState.SELECTED
|| componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED : theme
.getOutlineColor();
} else {
finalLabelColor = componentState == ComponentState.SELECTED
|| componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED
: labelColor;
}
g2d.setColor(finalLabelColor);
FontMetrics fontMetrics = g2d.getFontMetrics();
String label = display == Display.NAME ? getName() : getValue().toString();
Rectangle2D textRect = fontMetrics.getStringBounds(label, g2d);
// Don't offset in outline mode.
int offset = outlineMode ? 0 : getLabelOffset((int) shapeRect.getWidth(), (int) textRect.getWidth());
// 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);
offset = -offset;
}
g2d.drawString(label, (int) (shapeRect.width - textRect.getWidth()) / 2 + offset,
calculateLabelYCoordinate(shapeRect, textRect, fontMetrics));
g2d.setTransform(oldTransform);
}
}
private void drawLead(Graphics2D g2d, ComponentState componentState) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness()));
Color leadColor = shouldShadeLeads() ? getLeadColor(componentState).darker()
: getLeadColor(componentState);
g2d.setColor(leadColor);
g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y);
if (shouldShadeLeads()) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(getLeadThickness() - 2));
leadColor = getLeadColor(componentState);
g2d.setColor(leadColor);
g2d.drawLine(points[0].x, points[0].y, points[1].x, points[1].y);
}
}
protected void decorateComponentBody(Graphics2D g2d, boolean outlineMode) {
// Do nothing.
}
protected int calculateLabelYCoordinate(Rectangle2D shapeRect, Rectangle2D textRect,
FontMetrics fontMetrics) {
return (int) (shapeRect.getHeight() - textRect.getHeight()) / 2 + fontMetrics.getAscent();
}
protected boolean shouldShadeLeads() {
return true;
}
protected boolean supportsStandingMode() {
return false;
}
protected int getLabelOffset(int bodyWidth, int labelWidth) {
return 0;
}
/**
* @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 int getLeadThickness() {
return (int) LEAD_THICKNESS.convertToPixels();
}
/**
* @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;
}
}
@@ -0,0 +1,72 @@
package org.diylc.components;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.geom.Rectangle2D;
import org.diylc.common.LabelPosition;
import org.diylc.core.ComponentState;
import org.diylc.core.annotations.EditableProperty;
public abstract class AbstractSchematicLeadedSymbol<T> extends AbstractLeadedComponent<T> {
private static final long serialVersionUID = 1L;
public static Color COLOR = Color.blue;
public static Color LEAD_COLOR = Color.black;
protected LabelPosition labelPosition = LabelPosition.ABOVE;
public AbstractSchematicLeadedSymbol() {
super();
// We don't want to fill the body, so use null.
this.bodyColor = null;
this.borderColor = COLOR;
}
@Override
public Color getBodyColor() {
return super.getBodyColor();
}
@Override
protected boolean shouldShadeLeads() {
return false;
}
@Override
protected int getLeadThickness() {
return 1;
}
@Override
protected int calculateLabelYCoordinate(Rectangle2D shapeRect, Rectangle2D textRect,
FontMetrics fontMetrics) {
if (labelPosition == LabelPosition.ABOVE) {
return -1;
} else {
return (int) (shapeRect.getHeight() + textRect.getHeight() - 1);
}
}
@EditableProperty(name = "Label position")
public LabelPosition getLabelPosition() {
return labelPosition;
}
@Override
@EditableProperty(name = "Color")
public Color getBorderColor() {
return super.getBorderColor();
}
public void setLabelPosition(LabelPosition labelPosition) {
this.labelPosition = labelPosition;
}
@Override
protected Color getLeadColor(ComponentState componentState) {
return componentState == ComponentState.SELECTED
|| componentState == ComponentState.DRAGGING ? SELECTION_COLOR : LEAD_COLOR;
}
}
@@ -0,0 +1,13 @@
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 {
}
}
@@ -0,0 +1,8 @@
package org.diylc.core;
public enum ExpansionMode {
ALL,
SAME_TYPE,
IMMEDIATE,
}
@@ -30,15 +30,11 @@ import org.diylc.core.annotations.EditableProperty;
*/
public interface IDIYComponent<T> extends Serializable {
public static final int BELOW_CHASSIS = 1;
public static final int CHASSIS = 2;
public static final int ABOVE_CHASSIS = 3;
public static final int BELOW_BOARD = 4;
public static final int BOARD = 5;
public static final int ABOVE_BOARD = 6;
public static final int BELOW_COMPONENT = 7;
public static final int COMPONENT = 8;
public static final int ABOVE_COMPONENT = 9;
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.
@@ -84,9 +80,22 @@ public interface IDIYComponent<T> extends Serializable {
* @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);
/**
@@ -94,10 +103,12 @@ public interface IDIYComponent<T> extends Serializable {
*
* @param g2d
* @param componentState
* @param outlineMode
* @param project
* @param drawingObserver
*/
void draw(Graphics2D g2d, ComponentState componentState, Project project,
void draw(Graphics2D g2d, ComponentState componentState,
boolean outlineMode, Project project,
IDrawingObserver drawingObserver);
/**
@@ -109,4 +120,11 @@ public interface IDIYComponent<T> extends Serializable {
* @param height
*/
void drawIcon(Graphics2D g2d, int width, int height);
/**
* Clones the component.
*
* @return
*/
IDIYComponent<T> clone() throws CloneNotSupportedException;
}
@@ -0,0 +1,16 @@
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;
}
+41
View File
@@ -0,0 +1,41 @@
package org.diylc.core;
import java.io.File;
import java.util.List;
import java.util.Set;
import org.diylc.common.PropertyWrapper;
/**
* 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;
public static final String CHECK_BOX_MENU_ITEM = "org.diylc.checkBoxMenuItem";
public static final String RADIO_BUTTON_GROUP_KEY = "org.diylc.radioButtonGroup";
void showMessage(String message, String title, int messageType);
int showConfirmDialog(String message, String title, int optionType, int messageType);
boolean editProperties(List<PropertyWrapper> properties, Set<PropertyWrapper> defaultedProperties);
File promptFileSave();
}
@@ -2,11 +2,15 @@ package org.diylc.core;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.diylc.appframework.update.VersionNumber;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.annotations.PositiveMeasureValidator;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@@ -26,6 +30,8 @@ public class Project implements Serializable {
public static Size DEFAULT_HEIGHT = new Size(21d, SizeUnit.cm);
public static Size DEFAULT_GRID_SPACING = new Size(0.1d, SizeUnit.in);
private VersionNumber fileVersion;
private String title;
private String author;
private String description;
@@ -92,7 +98,7 @@ public class Project implements Serializable {
this.height = height;
}
@EditableProperty(name = "Grid spacing")
@EditableProperty(name = "Grid spacing", validatorClass = SpacingValidator.class)
public Size getGridSpacing() {
return gridSpacing;
}
@@ -118,10 +124,18 @@ public class Project implements Serializable {
public Set<Set<IDIYComponent<?>>> getGroups() {
return groups;
}
public Set<Integer> getLockedLayers() {
return lockedLayers;
}
public VersionNumber getFileVersion() {
return fileVersion;
}
public void setFileVersion(VersionNumber fileVersion) {
this.fileVersion = fileVersion;
}
@Override
public int hashCode() {
@@ -177,21 +191,58 @@ public class Project implements Serializable {
return false;
return true;
}
@Override
public String toString() {
return title;
}
// @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;
// }
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(0.5d, SizeUnit.mm)) < 0) {
throw new ValidationException("must be at least 0.5mm");
}
if (size.compareTo(new Size(1d, SizeUnit.in)) > 0) {
throw new ValidationException("must be less than 1in");
}
}
}
@Override
public Project clone() {
Project project = new Project();
project.setTitle(this.getTitle());
project.setAuthor(this.getAuthor());
project.setDescription(this.getDescription());
project.setFileVersion(this.getFileVersion());
project.setGridSpacing(this.getGridSpacing());
project.setHeight(this.getHeight());
project.setWidth(this.getWidth());
project.getLockedLayers().addAll(this.getLockedLayers());
Map<IDIYComponent<?>, IDIYComponent<?>> cloneMap = new HashMap<IDIYComponent<?>, IDIYComponent<?>>();
for (IDIYComponent<?> component : this.components) {
try {
IDIYComponent<?> clone = component.clone();
project.getComponents().add(clone);
cloneMap.put(component, clone);
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
for (Set<IDIYComponent<?>> group : this.groups) {
Set<IDIYComponent<?>> cloneGroup = new HashSet<IDIYComponent<?>>();
for (IDIYComponent<?> component : group) {
cloneGroup.add(cloneMap.get(component));
}
project.groups.add(cloneGroup);
}
return project;
}
}
+86
View File
@@ -0,0 +1,86 @@
package org.diylc.core;
import java.awt.Color;
import java.io.Serializable;
public class Theme implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private Color bgColor;
private Color gridColor;
private Color outlineColor;
public Theme(String name, Color bgColor, Color gridColor, Color outlineColor) {
super();
this.name = name;
this.bgColor = bgColor;
this.gridColor = gridColor;
this.outlineColor = outlineColor;
}
public String getName() {
return name;
}
public Color getBgColor() {
return bgColor;
}
public Color getGridColor() {
return gridColor;
}
public Color getOutlineColor() {
return outlineColor;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((bgColor == null) ? 0 : bgColor.hashCode());
result = prime * result + ((gridColor == null) ? 0 : gridColor.hashCode());
result = prime * result + ((outlineColor == null) ? 0 : outlineColor.hashCode());
result = prime * result + ((name == null) ? 0 : name.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;
Theme other = (Theme) obj;
if (bgColor == null) {
if (other.bgColor != null)
return false;
} else if (!bgColor.equals(other.bgColor))
return false;
if (gridColor == null) {
if (other.gridColor != null)
return false;
} else if (!gridColor.equals(other.gridColor))
return false;
if (outlineColor == null) {
if (other.outlineColor != null)
return false;
} else if (!outlineColor.equals(other.outlineColor))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return name;
}
}
@@ -0,0 +1,11 @@
package org.diylc.core;
public class ValidationException extends Exception {
private static final long serialVersionUID = 1L;
public ValidationException(String message) {
super(message);
}
}
@@ -0,0 +1,7 @@
package org.diylc.core.annotations;
public enum BomPolicy {
SHOW_ALL_NAMES,
SHOW_ONLY_TYPE_NAME,
NEVER_SHOW,
}
@@ -53,10 +53,22 @@ public @interface ComponentDescriptor {
*/
double zOrder();
/**
* @return true if the component may go beyond it's predefined layer. In
* that case, <code>zOrder</code> is used as initial z order of the
* component.
*/
boolean flexibleZOrder() default false;
/**
* @return when false, moving one control point will cause all the others to
* move together with it.
*/
boolean stretchable() default true;
/**
* @return controls what should be shown the BOM
*/
BomPolicy bomPolicy() default BomPolicy.SHOW_ALL_NAMES;
}
@@ -3,6 +3,9 @@ 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>
@@ -30,4 +33,10 @@ public @interface EditableProperty {
* @return
*/
boolean defaultable() default true;
/**
* Class of validator to use to
* @return
*/
Class<? extends IPropertyValidator> validatorClass() default AllowAllValidator.class;
}
@@ -0,0 +1,20 @@
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.");
}
}
}
@@ -4,6 +4,13 @@ import java.io.Serializable;
import java.text.DecimalFormat;
import java.text.Format;
/***
* Immutable measure class.
*
* @author bancika
*
* @param <T>
*/
public class AbstractMeasure<T extends Enum<? extends Unit>> implements Serializable, Cloneable {
private static final long serialVersionUID = 1L;
@@ -13,8 +20,8 @@ public class AbstractMeasure<T extends Enum<? extends Unit>> implements Serializ
protected Double value;
protected T unit;
public AbstractMeasure() {
}
// public AbstractMeasure() {
// }
public AbstractMeasure(Double value, T unit) {
super();
@@ -26,22 +33,22 @@ public class AbstractMeasure<T extends Enum<? extends Unit>> implements Serializ
return value;
}
public void setValue(Double value) {
this.value = value;
}
// public void setValue(Double value) {
// this.value = value;
// }
public T getUnit() {
return unit;
}
public void setUnit(T multiplier) {
this.unit = multiplier;
}
// public void setUnit(T multiplier) {
// this.unit = multiplier;
// }
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
// @Override
// public Object clone() throws CloneNotSupportedException {
// return super.clone();
// }
@Override
public int hashCode() {
@@ -76,6 +83,6 @@ public class AbstractMeasure<T extends Enum<? extends Unit>> implements Serializ
@Override
public String toString() {
return format.format(value) + " " + unit;
return format.format(value) + unit;
}
}
@@ -4,10 +4,10 @@ public class Capacitance extends AbstractMeasure<CapacitanceUnit> {
private static final long serialVersionUID = 1L;
public Capacitance() {
super();
// TODO Auto-generated constructor stub
}
// public Capacitance() {
// super();
// // TODO Auto-generated constructor stub
// }
public Capacitance(Double value, CapacitanceUnit unit) {
super(value, unit);
@@ -2,7 +2,7 @@ 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");
pF(1, "pF"), nF(1e3, "nF"), uF(1e6, "uF"), mF(1e9, "mF"), F(1e12, "F");
double factor;
String display;
@@ -4,10 +4,10 @@ public class Inductance extends AbstractMeasure<InductanceUnit> {
private static final long serialVersionUID = 1L;
public Inductance() {
super();
// TODO Auto-generated constructor stub
}
// public Inductance() {
// super();
// // TODO Auto-generated constructor stub
// }
public Inductance(Double value, InductanceUnit unit) {
super(value, unit);
@@ -0,0 +1,31 @@
package org.diylc.core.measures;
public class Power extends AbstractMeasure<PowerUnit> {
private static final long serialVersionUID = 1L;
// public Power() {
// super();
// // TODO Auto-generated constructor stub
// }
public Power(Double value, PowerUnit unit) {
super(value, unit);
// TODO Auto-generated constructor stub
}
@Override
public Power clone() throws CloneNotSupportedException {
return new Power(value, unit);
}
public static Power parseCapacitance(String value) {
for (PowerUnit unit : PowerUnit.values()) {
if (value.toLowerCase().endsWith(unit.toString().toLowerCase())) {
value = value.substring(0, value.length() - unit.toString().length() - 1).trim();
return new Power(Double.parseDouble(value), unit);
}
}
throw new IllegalArgumentException("Could not parse power: " + value);
}
}
@@ -0,0 +1,24 @@
package org.diylc.core.measures;
public enum PowerUnit implements Unit {
MW(1e-1, "mW"), W(1, "W"), KW(1e3, "KW");
double factor;
String display;
private PowerUnit(double factor, String display) {
this.factor = factor;
this.display = display;
}
@Override
public double getFactor() {
return factor;
}
@Override
public String toString() {
return display;
}
}
@@ -0,0 +1,98 @@
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;
if (getValue() == 0) {
switch (resistorColorCode) {
case _4_BAND:
bands = new Color[3];
bands[0] = COLOR_DIGITS[0];
bands[1] = COLOR_DIGITS[0];
bands[2] = COLOR_MULTIPLIER[2];
break;
case _5_BAND:
bands = new Color[4];
bands[0] = COLOR_DIGITS[0];
bands[1] = COLOR_DIGITS[0];
bands[2] = COLOR_DIGITS[0];
bands[3] = COLOR_MULTIPLIER[2];
break;
default:
bands = new Color[] {};
}
} else {
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) (base / 10)];
bands[1] = COLOR_DIGITS[(int) (base % 10)];
bands[2] = COLOR_MULTIPLIER[multiplier + 2];
break;
case _5_BAND:
bands = new Color[4];
bands[0] = COLOR_DIGITS[(int) (base / 100)];
bands[1] = COLOR_DIGITS[(int) (base / 10 % 10)];
bands[2] = COLOR_DIGITS[(int) (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()).trim();
return new Resistance(Double.parseDouble(value), unit);
}
}
throw new IllegalArgumentException("Could not parse resistance: " + value);
}
}
@@ -2,7 +2,7 @@ package org.diylc.core.measures;
public enum ResistanceUnit implements Unit {
R(1, "\u03a9"), K(1e3, "K"), M(1e6, "M");
R(1, "\u2126"), K(1e3, "K"), M(1e6, "M");
double factor;
String display;
@@ -2,27 +2,27 @@ package org.diylc.core.measures;
import org.diylc.utils.Constants;
public class Size extends AbstractMeasure<SizeUnit> {
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() {
// super();
// // TODO Auto-generated constructor stub
// }
public Size(Double value, SizeUnit unit) {
super(value, unit);
// TODO Auto-generated constructor stub
}
public int convertToPixels() {
public double 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);
return getValue() * getUnit().getFactor() / SizeUnit.in.getFactor() * Constants.PIXELS_PER_INCH;
}
@Override
@@ -39,4 +39,9 @@ public class Size extends AbstractMeasure<SizeUnit> {
}
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());
}
}
@@ -0,0 +1,31 @@
package org.diylc.core.measures;
public class Voltage extends AbstractMeasure<VoltageUnit> {
private static final long serialVersionUID = 1L;
// public Voltage() {
// super();
// // TODO Auto-generated constructor stub
// }
public Voltage(Double value, VoltageUnit unit) {
super(value, unit);
// TODO Auto-generated constructor stub
}
@Override
public Voltage clone() throws CloneNotSupportedException {
return new Voltage(value, unit);
}
public static Voltage parseCapacitance(String value) {
for (VoltageUnit unit : VoltageUnit.values()) {
if (value.toLowerCase().endsWith(unit.toString().toLowerCase())) {
value = value.substring(0, value.length() - unit.toString().length() - 1).trim();
return new Voltage(Double.parseDouble(value), unit);
}
}
throw new IllegalArgumentException("Could not parse voltage: " + value);
}
}
@@ -0,0 +1,24 @@
package org.diylc.core.measures;
public enum VoltageUnit implements Unit {
MV(1e-1, "mV"), V(1, "V"), KV(1e3, "KV");
double factor;
String display;
private VoltageUnit(double factor, String display) {
this.factor = factor;
this.display = display;
}
@Override
public double getFactor() {
return factor;
}
@Override
public String toString() {
return display;
}
}
@@ -30,7 +30,8 @@ public enum IconLoader {
"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");
"edit_component.png"), Size("size.png"), Front("front.png"), Back("back.png"), Pens(
"pens.png"), Sort("sort.png"), ElementsSelection("elements_selection.png");
protected String name;

Some files were not shown because too many files have changed in this diff Show More