]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/operationsymbols/OperationSymbols.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / elementclass / operationsymbols / OperationSymbols.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.g2d.elementclass.operationsymbols;\r
13 \r
14 import java.awt.BasicStroke;\r
15 import java.awt.Color;\r
16 import java.awt.Font;\r
17 import java.awt.Graphics2D;\r
18 import java.awt.Polygon;\r
19 import java.awt.Shape;\r
20 import java.awt.Stroke;\r
21 import java.awt.geom.Ellipse2D;\r
22 import java.awt.geom.Path2D;\r
23 import java.awt.geom.Rectangle2D;\r
24 import java.util.EnumSet;\r
25 \r
26 import org.simantics.g2d.image.Image;\r
27 import org.simantics.g2d.image.impl.Shadow;\r
28 import org.simantics.g2d.image.impl.Shadow.ShadowParameters;\r
29 import org.simantics.g2d.utils.GeometryUtils;\r
30 import org.simantics.g2d.utils.PathUtils;\r
31 import org.simantics.scenegraph.Node;\r
32 import org.simantics.scenegraph.g2d.G2DParentNode;\r
33 import org.simantics.utils.ObjectUtils;\r
34 \r
35 /**\r
36  * @author Toni Kalajainen\r
37  */\r
38 public class OperationSymbols {\r
39 \r
40     static final double SHADOW_SIZE = 100;\r
41     static final Color BORDER_COLOR = Color.GRAY;\r
42     static final Color FILL_COLOR = Color.GRAY;\r
43     static final Color SECONDARY_COLOR = Color.GREEN;\r
44     static final ShadowParameters SHADOW = new ShadowParameters(0.5, Color.BLACK, 2);\r
45 \r
46     static final Color HOT = new Color(50, 50, 200);\r
47     static final Color COLD = new Color(190, 190, 255);\r
48 \r
49     public static final BoilerHeatExchanger[] BOILER_HES = new BoilerHeatExchanger[] {\r
50         new BoilerHeatExchanger(null, HOT, HOT, null, HOT),\r
51         new BoilerHeatExchanger(HOT, null, COLD, COLD, HOT),\r
52         new BoilerHeatExchanger(HOT, null, COLD, null, HOT),\r
53         new BoilerHeatExchanger(HOT, null, null, HOT, HOT)\r
54     };\r
55 \r
56     public static final Image BOILER_SYMBOL = new BoilerSymbol2(FILL_COLOR, FILL_COLOR, BOILER_HES);\r
57     public static final Image BOILER_SHADOW = new Shadow(BOILER_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
58 \r
59     public static final Image COMPRESSOR_SYMBOL = new CompressorSymbol(FILL_COLOR, BORDER_COLOR);\r
60     public static final Image COMPRESSOR_SHADOW = new Shadow(COMPRESSOR_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
61 \r
62     public static final Image NO_SPIN_SYMBOL = new NoSpinSymbol(FILL_COLOR, BORDER_COLOR);\r
63     public static final Image NO_SPIN_SHADOW = new Shadow(NO_SPIN_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
64 \r
65     public static final Image CONTROLVALVE_SYMBOL = new ControlValveSymbol(BORDER_COLOR, FILL_COLOR);\r
66     public static final Image CONTROLVALVE_SHADOW = new Shadow(CONTROLVALVE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
67 \r
68     public static final Image THREEWAYVALVE_SYMBOL = new ThreeWayValveSymbol(BORDER_COLOR, FILL_COLOR);\r
69     public static final Image THREEWAYVALVE_SHADOW = new Shadow(THREEWAYVALVE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
70 \r
71     public static final Image HEATEXCHANGER_SYMBOL = new HeatExchangerSymbol(BORDER_COLOR, FILL_COLOR);\r
72     public static final Image HEATEXCHANGER_SHADOW = new Shadow(HEATEXCHANGER_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
73 \r
74     public static final Image PUMP_SYMBOL = new PumpSymbol(BORDER_COLOR, FILL_COLOR);\r
75     public static final Image PUMP_SHADOW = new Shadow(PUMP_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
76 \r
77     public static final Image SHUTOFFVALVE_SYMBOL = new ShutoffValveSymbol(BORDER_COLOR, FILL_COLOR);\r
78     public static final Image SHUTOFFVALVE_SHADOW = new Shadow(SHUTOFFVALVE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
79 \r
80     public static final Image SWITCH_SYMBOL = new SwitchSymbol(BORDER_COLOR);\r
81     public static final Image SWITCH_SHADOW = new Shadow(SWITCH_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
82 \r
83     public static final Image TURBINE_SYMBOL = new TurbineSymbol(BORDER_COLOR, FILL_COLOR);\r
84     public static final Image TURBINE_SHADOW = new Shadow(TURBINE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
85 \r
86     public static final Image VOLTAGETRANSFORMER_SYMBOL = new VoltageTransformerSymbol(SECONDARY_COLOR, BORDER_COLOR);\r
87     public static final Image VOLTAGETRANSFORMER_SHADOW = new Shadow(VOLTAGETRANSFORMER_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
88 \r
89     public static final Image CHIMNEY_SYMBOL = new ChimneySymbol(SECONDARY_COLOR, BORDER_COLOR);\r
90     public static final Image CHIMNEY_SHADOW = new Shadow(CHIMNEY_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
91 \r
92     public static final Image GENERATOR_SYMBOL = new GeneratorSymbol(SECONDARY_COLOR, BORDER_COLOR);\r
93     public static final Image GENERATOR_SHADOW = new Shadow(GENERATOR_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
94 \r
95     public static final Image TANK_SYMBOL = new TankSymbol(new Rectangle2D.Double(0,0, 20.0, 8.0), 2.0, SECONDARY_COLOR, BORDER_COLOR);\r
96     public static final Image TANK_SHADOW = new Shadow(TANK_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
97 \r
98     public static final Image TANK2_SYMBOL = new Tank2Symbol(new Rectangle2D.Double(0,0, 20.0, 8.0), 2.0, SECONDARY_COLOR, BORDER_COLOR, HOT);\r
99     public static final Image TANK2_SHADOW = new Shadow(TANK2_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
100 \r
101     public static class BoilerSymbol extends PS implements Image {\r
102         public static final int DIM = 10;\r
103         public static final Polygon SHAPE =\r
104             new Polygon(new int[] {-DIM, -DIM, 0, DIM, DIM, 0}, new int[] {2*DIM, -2*DIM, -3*DIM, -2*DIM, 2*DIM, 3*DIM}, 6);\r
105         public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
106 \r
107         public BoilerSymbol(Color bc, Color fc) {\r
108             super(SHAPE.getBounds2D(), bc, fc, null, null);\r
109         }\r
110         @Override\r
111         public void paint(Graphics2D g) {\r
112 //                      if (fc!=null) {\r
113 //                              g.setColor(fc);\r
114 //                              g.fill(SHAPE);\r
115 //                      }\r
116 //                      if (bc!=null) {\r
117 //                              g.setColor(bc);\r
118 //                              g.draw(SHAPE);\r
119 //                      }\r
120         }\r
121     }\r
122 \r
123     public static class BoilerHeatExchanger {\r
124         public final Color color;\r
125         public final Color topLeft, topRight, bottomLeft, bottomRight;\r
126         public BoilerHeatExchanger(Color topLeft, Color topRight,\r
127                 Color bottomLeft, Color bottomRight,\r
128                 Color color) {\r
129             this.bottomLeft = bottomLeft;\r
130             this.bottomRight = bottomRight;\r
131             this.color = color;\r
132             this.topLeft = topLeft;\r
133             this.topRight = topRight;\r
134         }\r
135     }\r
136 \r
137     public static class BoilerSymbol2 extends PS implements Image {\r
138 \r
139         public static Path2D HE = PathUtils.path(10,0, 0,0, 0,5, 5,10, -5,10, 0,15, 0,20);\r
140 \r
141         public static Rectangle2D getBoilerRect(BoilerHeatExchanger ... hes)\r
142         {\r
143             return new Rectangle2D.Double(-10, 0, 20, hes.length*25+25);\r
144         }\r
145 \r
146         public static Shape getBoilerShape(BoilerHeatExchanger ... hes)\r
147         {\r
148             Path2D p = new Path2D.Double();\r
149             p.moveTo(-10, 10);\r
150             p.lineTo(  0,  0);\r
151             p.lineTo( 10, 10);\r
152             double h = hes.length * 25;\r
153             p.lineTo( 10, h+15);\r
154             p.lineTo(  0, h+25);\r
155             p.lineTo(-10, h+15);\r
156             p.closePath();\r
157             return p;\r
158         }\r
159 \r
160         private final Shape shape;\r
161         private final BoilerHeatExchanger [] hes;\r
162 \r
163         public BoilerSymbol2(Color fc, Color bc, BoilerHeatExchanger ... hes) {\r
164             super( getBoilerRect(hes), bc, fc, null, null);\r
165             shape = getBoilerShape(hes);\r
166             this.hes = hes;\r
167         }\r
168 \r
169         @Override\r
170         public void paint(Graphics2D g) {\r
171             if (fc!=null) {\r
172                 g.setColor(fc);\r
173                 g.fill(shape);\r
174             }\r
175             if (bc!=null) {\r
176                 g.setColor(bc);\r
177                 g.draw(shape);\r
178             }\r
179             // paint heat exchangers\r
180             g.translate(0, 15);\r
181             for (BoilerHeatExchanger he : hes)\r
182             {\r
183                 g.setColor(he.color);\r
184                 g.draw(HE);\r
185                 if (he.topLeft!=null) {\r
186                     g.setColor(he.topLeft);\r
187                     g.drawLine(-10, 0, 0, 0);\r
188                 }\r
189                 if (he.topRight!=null) {\r
190                     g.setColor(he.topRight);\r
191                     g.drawLine(0, 0, 10, 0);\r
192                 }\r
193                 if (he.bottomLeft!=null) {\r
194                     g.setColor(he.bottomLeft);\r
195                     g.drawLine(-10, 20, 0, 20);\r
196                 }\r
197                 if (he.bottomRight!=null) {\r
198                     g.setColor(he.bottomRight);\r
199                     g.drawLine(0, 20, 10, 20);\r
200                 }\r
201                 g.translate(0, 25);\r
202             }\r
203         }\r
204     }\r
205 \r
206     public static class ChimneySymbol extends PS implements Image {\r
207 \r
208         public static final int DIM = 10;\r
209         public static final int D2 = 8;\r
210         public static final Shape C1 = new Ellipse2D.Double(-DIM, -DIM, DIM*2, DIM*2);\r
211         public static final Shape C2 = new Ellipse2D.Double(-D2, -D2, D2*2, D2*2);\r
212 \r
213         public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-10, -10, 20, 40);\r
214 \r
215         public ChimneySymbol(Color fc, Color bc) {\r
216             super( BOUNDS, bc, fc, null, null);\r
217             assert(bc!=null);\r
218         }\r
219 \r
220         @Override\r
221         public void paint(Graphics2D g) {\r
222             g.setColor(fc);\r
223             g.fill(C2);\r
224             g.fillRect(-5, 14, 10, 8);\r
225             g.setColor(bc);\r
226             g.draw(C1);\r
227             g.draw(C2);\r
228 \r
229             g.drawLine(0, DIM, 0, 15);\r
230             g.drawRect(-5, 14, 10, 8);\r
231             g.drawLine(-5, 14, 5, 22);\r
232         }\r
233     }\r
234 \r
235 \r
236     public static class GeneratorSymbol extends PS implements Image {\r
237 \r
238         public static final int DIM = 10;\r
239         public static final Shape C1 = new Ellipse2D.Double(-DIM, -DIM, DIM*2, DIM*2);\r
240 \r
241         public static final Rectangle2D BOUNDS = C1.getBounds2D();\r
242         private final static Font FONT = Font.decode("Serif-12");\r
243 \r
244         public GeneratorSymbol(Color fc, Color bc) {\r
245             super( BOUNDS, bc, fc, null, null);\r
246             assert(bc!=null && fc!=null);\r
247         }\r
248 \r
249         @Override\r
250         public void paint(Graphics2D g) {\r
251             g.setColor(fc);\r
252             g.fill(C1);\r
253             g.setColor(bc);\r
254             g.draw(C1);\r
255             g.setFont(FONT);\r
256             g.drawString("G", -4, 4);\r
257         }\r
258     }\r
259 \r
260     public static class NoSpinSymbol extends PS {\r
261         public NoSpinSymbol(Color fc, Color bc) {\r
262             super(BOUNDS, bc, fc, null, null);\r
263         }\r
264         public static final Stroke STROKE = new BasicStroke(1.5f);\r
265         public static final int DIM = 10;\r
266         public static final int D2 = 8;\r
267         public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-DIM, -DIM, 2*DIM, 2*DIM);\r
268         public static final Shape CIRCLE = new Ellipse2D.Double(-D2, -D2, D2*2, D2*2);\r
269 \r
270         @Override\r
271         public void paint(Graphics2D g) {\r
272             g.setStroke(STROKE);\r
273             g.setColor(fc);\r
274             g.fillRect(-DIM, -DIM, DIM*2, DIM*2);\r
275             g.setColor(bc);\r
276             g.drawRect(-DIM, -DIM, DIM*2, DIM*2);\r
277             g.draw(CIRCLE);\r
278             g.drawLine(-DIM/3, -DIM/3, DIM/3, DIM/3);\r
279             g.drawLine(DIM/3, -DIM/3, -DIM/3, DIM/3);\r
280         }\r
281     }\r
282 \r
283     public static class ControlValveSymbol extends PS implements Image {\r
284 \r
285         public static final Stroke STROKE = new BasicStroke(1.5f);\r
286         public static final int D = 10;\r
287         public static final Path2D SHAPE =\r
288             PathUtils.closedPath(-D,-D, -D,D, D,-D, D,D );\r
289         public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
290 \r
291         public ControlValveSymbol(Color bc, Color fc) {\r
292             super(BOUNDS, bc, fc, null, null);\r
293         }\r
294         @Override\r
295         public void paint(Graphics2D g) {\r
296             if (fc!=null) {\r
297                 g.setColor(fc);\r
298                 g.fill(SHAPE);\r
299             }\r
300             if (bc!=null) {\r
301                 g.setColor(bc);\r
302                 g.draw(SHAPE);\r
303             }\r
304         }\r
305     }\r
306 \r
307     public static class ThreeWayValveSymbol extends PS implements Image {\r
308 \r
309         public static final Stroke STROKE = new BasicStroke(1.5f);\r
310         public static final int D = 10;\r
311         public static final Path2D SHAPE =\r
312             PathUtils.closedPath(-D,D*2/3, -D,-D*2/3, 0,0, -D*2/3,-D, D*2/3,-D, 0,0, D,D*2/3, D,-D*2/3, 0,0 );\r
313         public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
314 \r
315         public ThreeWayValveSymbol(Color bc, Color fc) {\r
316             super(BOUNDS, bc, fc, null, null);\r
317         }\r
318         @Override\r
319         public void paint(Graphics2D g) {\r
320             if (fc!=null) {\r
321                 g.setColor(fc);\r
322                 g.fill(SHAPE);\r
323             }\r
324             if (bc!=null) {\r
325                 g.setColor(bc);\r
326                 g.draw(SHAPE);\r
327             }\r
328         }\r
329     }\r
330 \r
331 \r
332     public static class HeatExchangerSymbol extends PS {\r
333 \r
334         public HeatExchangerSymbol(Color bc, Color fc) {\r
335             super(BOUNDS, bc, fc, null, null);\r
336         }\r
337         public static final Stroke STROKE = new BasicStroke(1.5f);\r
338         public static final int D = 10;\r
339         public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-D, -D, 2*D, 2*D);\r
340         public static final int xPoints[] = new int [] {-D, 0, 0, -D/2, D/2, 0, 0, D};\r
341         public static final int yPoints[] = new int [] {D/2, D/2, D/8, 0, 0, -D/8, -D/2, -D/2};\r
342 \r
343         @Override\r
344         public void paint(Graphics2D g) {\r
345             g.setColor(fc);\r
346             g.fill(BOUNDS);\r
347             g.setColor(bc);\r
348             g.draw(BOUNDS);\r
349             g.setStroke(STROKE);\r
350             g.drawPolyline(xPoints, yPoints, xPoints.length);\r
351         }\r
352     }\r
353 \r
354     public static class PumpSymbol extends PS {\r
355 \r
356         public PumpSymbol(Color bc, Color fc) {\r
357             super(BOUNDS, bc, fc, null, null);\r
358         }\r
359         public static final Stroke STROKE = new BasicStroke(1.5f);\r
360         public static final int DIM = 10;\r
361         public static final int D2 = 12;\r
362         public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-D2, -D2, 2*D2, 2*D2);\r
363         public static final Shape CIRCLE = new Ellipse2D.Double(-D2, -D2, D2*2, D2*2);\r
364         public static final Polygon SHAPE =\r
365             new Polygon(new int[] {-DIM, -DIM, 0, 0, DIM, 0, 0}, new int[] {DIM/4, -DIM/4, -DIM/4, -DIM, 0, DIM, DIM/4}, 7);\r
366 \r
367         @Override\r
368         public void paint(Graphics2D g) {\r
369             g.setColor(fc);\r
370             g.fill(CIRCLE);\r
371             g.setColor(bc);\r
372             g.setStroke( STROKE );\r
373             g.draw(CIRCLE);\r
374             g.draw(SHAPE);\r
375         }\r
376     }\r
377 \r
378 \r
379     public static class ShutoffValveSymbol extends PS implements Image {\r
380 \r
381         public static final Stroke STROKE = new BasicStroke(1.5f);\r
382         public static final int DIM = 10;\r
383         public static final Path2D SHAPE =\r
384             PathUtils.closedPath(-DIM,-DIM, -DIM,DIM, DIM,-DIM, DIM,DIM );\r
385         public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
386 \r
387         public ShutoffValveSymbol(Color bc, Color fc) {\r
388             super(BOUNDS, bc, fc, null, null);\r
389         }\r
390         @Override\r
391         public void paint(Graphics2D g) {\r
392             if (fc!=null) {\r
393                 g.setColor(fc);\r
394                 g.fill(SHAPE);\r
395             }\r
396             if (bc!=null) {\r
397                 g.setColor(bc);\r
398                 g.draw(SHAPE);\r
399                 g.drawLine(0, -DIM, 0, DIM);\r
400             }\r
401         }\r
402     }\r
403 \r
404 \r
405     public static class SwitchSymbol extends PS {\r
406 \r
407         public SwitchSymbol(Color bc) {\r
408             super(BOUNDS, bc, null, null, null);\r
409         }\r
410         public static final Stroke STROKE = new BasicStroke(1.5f);\r
411         public static final int D = 10;\r
412         public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-D, -D, 2*D, 2*D);\r
413 \r
414         @Override\r
415         public void paint(Graphics2D g) {\r
416             g.setColor(bc);\r
417             g.setStroke(STROKE);\r
418 \r
419             g.drawLine(0, -D, 0, D);\r
420             g.drawLine(-D/4, -D/2, D/4, -D/2);\r
421             g.drawLine(-D, 0, D, 0);\r
422             g.drawLine(-D/4, D/2, D/4, D/2);\r
423         }\r
424     }\r
425 \r
426 \r
427     public static class TurbineSymbol extends PS implements Image {\r
428 \r
429         public static final int DIM = 10;\r
430         public static final Polygon SHAPE =\r
431             new Polygon(new int[] {-DIM, -DIM, DIM, DIM}, new int[] {-DIM, DIM, DIM*2, -DIM*2}, 4);\r
432         public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
433 \r
434         public TurbineSymbol(Color bc, Color fc) {\r
435             super(BOUNDS, bc, fc, null, null);\r
436         }\r
437         @Override\r
438         public void paint(Graphics2D g) {\r
439             if (fc!=null) {\r
440                 g.setColor(fc);\r
441                 g.fill(SHAPE);\r
442             }\r
443             if (bc!=null) {\r
444                 g.setColor(bc);\r
445                 g.draw(SHAPE);\r
446             }\r
447         }\r
448     }\r
449 \r
450     public static class CompressorSymbol extends PS implements Image {\r
451 \r
452         public static final int DIM = 10;\r
453         public static final Polygon SHAPE =\r
454             new Polygon(new int[] {DIM, DIM, -DIM, -DIM}, new int[] {-DIM, DIM, DIM*2, -DIM*2}, 4);\r
455         public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
456 \r
457         public CompressorSymbol(Color bc, Color fc) {\r
458             super(BOUNDS, bc, fc, null, null);\r
459         }\r
460         @Override\r
461         public void paint(Graphics2D g) {\r
462             if (fc!=null) {\r
463                 g.setColor(fc);\r
464                 g.fill(SHAPE);\r
465             }\r
466             if (bc!=null) {\r
467                 g.setColor(bc);\r
468                 g.draw(SHAPE);\r
469             }\r
470         }\r
471     }\r
472 \r
473     public static class VoltageTransformerSymbol extends PS implements Image {\r
474 \r
475         public static final Stroke STROKE = new BasicStroke(1.5f);\r
476         public static final int DIM = 10;\r
477         public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-DIM, -DIM*1.7, 2*DIM, 2*DIM*1.7);\r
478         public static final Shape CIRCLE = new Ellipse2D.Double(-DIM, -DIM, DIM*2, DIM*2);\r
479 \r
480         public VoltageTransformerSymbol(Color c1, Color c2) {\r
481             super(BOUNDS, null, null, c1, c2);\r
482         }\r
483         @Override\r
484         public void paint(Graphics2D g) {\r
485             g.setStroke(STROKE);\r
486             Graphics2D sg = (Graphics2D) g.create();\r
487 \r
488             sg.clipRect(-DIM*2, -DIM*2, DIM*4, DIM*2);\r
489             sg.setColor(c1);\r
490             sg.translate(0, -0.7*DIM);\r
491             sg.draw(CIRCLE);\r
492             sg.setColor(c2);\r
493             sg.translate(0, 1.4*DIM);\r
494             sg.draw(CIRCLE);\r
495             sg.dispose();\r
496 \r
497             g.clipRect(-DIM*2, 0, DIM*4, DIM*2);\r
498             g.setColor(c2);\r
499             g.translate(0, 0.7*DIM);\r
500             g.draw(CIRCLE);\r
501             g.setColor(c1);\r
502             g.translate(0, -1.4*DIM);\r
503             g.draw(CIRCLE);\r
504         }\r
505     }\r
506 \r
507     public static class TankSymbol extends PS implements Image {\r
508 \r
509         /**\r
510          * Create tank shape.\r
511          * @param r rectangle\r
512          * @param cap cap size\r
513          * @return tank shape\r
514          */\r
515         public static Path2D createTankShape(Rectangle2D r, double cap)\r
516         {\r
517             double x1 = r.getMinX();\r
518             double y1 = r.getMinY();\r
519             double x2 = r.getMaxX();\r
520             double y2 = r.getMaxY();\r
521             Path2D p = new Path2D.Double();\r
522             p.moveTo(x1+cap, y1);\r
523             p.lineTo(x2-cap, y1);\r
524             p.quadTo(x2,y1, x2,y1+cap);\r
525             p.lineTo(x2, y2-cap);\r
526             p.quadTo(x2, y2, x2-cap, y2);\r
527             p.lineTo(x1+cap, y2);\r
528             p.quadTo(x1, y2, x1, y2-cap);\r
529             p.lineTo(x1, y1+cap);\r
530             p.quadTo(x1, y1, x1+cap, y1);\r
531             return p;\r
532         }\r
533 \r
534         Path2D shape;\r
535 \r
536         public TankSymbol(Rectangle2D rect, double cap, Color bc, Color fc) {\r
537             super(rect, bc, fc, null, null);\r
538             shape = createTankShape(rect, cap);\r
539         }\r
540 \r
541         @Override\r
542         public void paint(Graphics2D g) {\r
543             g.setColor(fc);\r
544             g.setStroke(GeometryUtils.BASIC_STROKE);\r
545             g.fill(shape);\r
546             if (bc!=null) {\r
547                 g.setColor(bc);\r
548                 g.draw(shape);\r
549             }\r
550         }\r
551 \r
552     }\r
553 \r
554     public static class Tank2Symbol extends PS implements Image {\r
555 \r
556         public static Path2D createWShape()\r
557         {\r
558             Path2D p = new Path2D.Double();\r
559             double k = Math.sqrt(2);\r
560             p.moveTo(-1, -1);\r
561             p.quadTo(0, -k, 1, -1);\r
562             p.quadTo(k, 0, 1, 1);\r
563             p.quadTo(0, k, -1, 1);\r
564             p.quadTo(-k, 0, -1, -1);\r
565             p.lineTo(-1, 1);\r
566             p.lineTo(0,0);\r
567             p.lineTo(1, 1);\r
568             p.lineTo(1, -1);\r
569             return p;\r
570         }\r
571 \r
572         Path2D shape;\r
573         Path2D shape2;\r
574 \r
575         public Tank2Symbol(Rectangle2D rect, double cap, Color bc, Color fc, Color a1) {\r
576             super(rect, bc, fc, a1, null);\r
577             shape = TankSymbol.createTankShape(rect, cap);\r
578             shape2 = createWShape();\r
579         }\r
580 \r
581         @Override\r
582         public void paint(Graphics2D g) {\r
583             g.setColor(fc);\r
584             g.setStroke(GeometryUtils.BASIC_STROKE);\r
585             g.setStroke(new BasicStroke(0.3f));\r
586             g.fill(shape);\r
587             if (bc!=null) {\r
588                 g.setColor(bc);\r
589                 g.draw(shape);\r
590             }\r
591             g.setColor(c1);\r
592             double d = Math.min(bounds.getHeight(), bounds.getWidth());\r
593             g.translate(bounds.getMinX()+d/2, bounds.getMinY()+d/2);\r
594             g.scale(d/3, d/3);\r
595             g.draw(shape2);\r
596         }\r
597 \r
598     }\r
599 \r
600     private abstract static class PS implements Image {\r
601 \r
602 \r
603         public final Rectangle2D bounds;\r
604         public final Color c1;\r
605         public final Color c2;\r
606         public final Color bc;\r
607         public final Color fc;\r
608         private final int hash;\r
609         public PS(Rectangle2D bounds, Color bc, Color fc, Color c1, Color c2) {\r
610             this.bounds = bounds;\r
611             this.bc = bc;\r
612             this.fc = fc;\r
613             this.c1 = c1;\r
614             this.c2 = c2;\r
615             int hash = this.getClass().hashCode();\r
616             if (bc!=null) hash += 3 * bc.hashCode();\r
617             if (fc!=null) hash += 5 * fc.hashCode();\r
618             if (c1!=null) hash += 7 * c1.hashCode();\r
619             if (c2!=null) hash += 11 * c2.hashCode();\r
620             this.hash = hash;\r
621         }\r
622 \r
623         @Override\r
624         public int hashCode() {\r
625             return hash;\r
626         }\r
627 \r
628         @Override\r
629         public boolean equals(Object obj) {\r
630             if (!obj.getClass().equals(getClass()))return false;\r
631             PS other = (PS) obj;\r
632             return\r
633             ObjectUtils.objectEquals(other.c1, c1) &&\r
634             ObjectUtils.objectEquals(other.c2, c2) &&\r
635             ObjectUtils.objectEquals(other.fc, fc) &&\r
636             ObjectUtils.objectEquals(other.bc, bc);\r
637         }\r
638         @Override\r
639         public Rectangle2D getBounds() {\r
640             return bounds;\r
641         }\r
642 \r
643         @Override\r
644         public Shape getOutline() {\r
645             return bounds;\r
646         }\r
647 \r
648         @Override\r
649         public Node init(G2DParentNode g) {\r
650 //                      return init(g);\r
651             return null;\r
652         }\r
653 \r
654         public void paint(Graphics2D g2d) { // FIXME: get rid of this\r
655 \r
656         }\r
657 \r
658         @Override\r
659         public void addImageListener(ImageListener listener) {\r
660         }\r
661 \r
662         static EnumSet<Feature> caps = EnumSet.of(Feature.Vector);\r
663         @Override\r
664         public EnumSet<Feature> getFeatures() {\r
665             return caps;\r
666         }\r
667 \r
668         @Override\r
669         public void removeImageListener(ImageListener listener) {\r
670         }\r
671 \r
672     }\r
673 \r
674 }\r