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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.g2d.elementclass.operationsymbols;
\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
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
36 * @author Toni Kalajainen
\r
38 public class OperationSymbols {
\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
46 static final Color HOT = new Color(50, 50, 200);
\r
47 static final Color COLD = new Color(190, 190, 255);
\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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
107 public BoilerSymbol(Color bc, Color fc) {
\r
108 super(SHAPE.getBounds2D(), bc, fc, null, null);
\r
111 public void paint(Graphics2D g) {
\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
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
137 public static class BoilerSymbol2 extends PS implements Image {
\r
139 public static Path2D HE = PathUtils.path(10,0, 0,0, 0,5, 5,10, -5,10, 0,15, 0,20);
\r
141 public static Rectangle2D getBoilerRect(BoilerHeatExchanger ... hes)
\r
143 return new Rectangle2D.Double(-10, 0, 20, hes.length*25+25);
\r
146 public static Shape getBoilerShape(BoilerHeatExchanger ... hes)
\r
148 Path2D p = new Path2D.Double();
\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
160 private final Shape shape;
\r
161 private final BoilerHeatExchanger [] hes;
\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
170 public void paint(Graphics2D g) {
\r
179 // paint heat exchangers
\r
180 g.translate(0, 15);
\r
181 for (BoilerHeatExchanger he : hes)
\r
183 g.setColor(he.color);
\r
185 if (he.topLeft!=null) {
\r
186 g.setColor(he.topLeft);
\r
187 g.drawLine(-10, 0, 0, 0);
\r
189 if (he.topRight!=null) {
\r
190 g.setColor(he.topRight);
\r
191 g.drawLine(0, 0, 10, 0);
\r
193 if (he.bottomLeft!=null) {
\r
194 g.setColor(he.bottomLeft);
\r
195 g.drawLine(-10, 20, 0, 20);
\r
197 if (he.bottomRight!=null) {
\r
198 g.setColor(he.bottomRight);
\r
199 g.drawLine(0, 20, 10, 20);
\r
201 g.translate(0, 25);
\r
206 public static class ChimneySymbol extends PS implements Image {
\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
213 public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-10, -10, 20, 40);
\r
215 public ChimneySymbol(Color fc, Color bc) {
\r
216 super( BOUNDS, bc, fc, null, null);
\r
221 public void paint(Graphics2D g) {
\r
224 g.fillRect(-5, 14, 10, 8);
\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
236 public static class GeneratorSymbol extends PS implements Image {
\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
241 public static final Rectangle2D BOUNDS = C1.getBounds2D();
\r
242 private final static Font FONT = Font.decode("Serif-12");
\r
244 public GeneratorSymbol(Color fc, Color bc) {
\r
245 super( BOUNDS, bc, fc, null, null);
\r
246 assert(bc!=null && fc!=null);
\r
250 public void paint(Graphics2D g) {
\r
256 g.drawString("G", -4, 4);
\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
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
271 public void paint(Graphics2D g) {
\r
272 g.setStroke(STROKE);
\r
274 g.fillRect(-DIM, -DIM, DIM*2, DIM*2);
\r
276 g.drawRect(-DIM, -DIM, DIM*2, DIM*2);
\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
283 public static class ControlValveSymbol extends PS implements Image {
\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
291 public ControlValveSymbol(Color bc, Color fc) {
\r
292 super(BOUNDS, bc, fc, null, null);
\r
295 public void paint(Graphics2D g) {
\r
307 public static class ThreeWayValveSymbol extends PS implements Image {
\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
315 public ThreeWayValveSymbol(Color bc, Color fc) {
\r
316 super(BOUNDS, bc, fc, null, null);
\r
319 public void paint(Graphics2D g) {
\r
332 public static class HeatExchangerSymbol extends PS {
\r
334 public HeatExchangerSymbol(Color bc, Color fc) {
\r
335 super(BOUNDS, bc, fc, null, null);
\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
344 public void paint(Graphics2D g) {
\r
349 g.setStroke(STROKE);
\r
350 g.drawPolyline(xPoints, yPoints, xPoints.length);
\r
354 public static class PumpSymbol extends PS {
\r
356 public PumpSymbol(Color bc, Color fc) {
\r
357 super(BOUNDS, bc, fc, null, null);
\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
368 public void paint(Graphics2D g) {
\r
372 g.setStroke( STROKE );
\r
379 public static class ShutoffValveSymbol extends PS implements Image {
\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
387 public ShutoffValveSymbol(Color bc, Color fc) {
\r
388 super(BOUNDS, bc, fc, null, null);
\r
391 public void paint(Graphics2D g) {
\r
399 g.drawLine(0, -DIM, 0, DIM);
\r
405 public static class SwitchSymbol extends PS {
\r
407 public SwitchSymbol(Color bc) {
\r
408 super(BOUNDS, bc, null, null, null);
\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
415 public void paint(Graphics2D g) {
\r
417 g.setStroke(STROKE);
\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
427 public static class TurbineSymbol extends PS implements Image {
\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
434 public TurbineSymbol(Color bc, Color fc) {
\r
435 super(BOUNDS, bc, fc, null, null);
\r
438 public void paint(Graphics2D g) {
\r
450 public static class CompressorSymbol extends PS implements Image {
\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
457 public CompressorSymbol(Color bc, Color fc) {
\r
458 super(BOUNDS, bc, fc, null, null);
\r
461 public void paint(Graphics2D g) {
\r
473 public static class VoltageTransformerSymbol extends PS implements Image {
\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
480 public VoltageTransformerSymbol(Color c1, Color c2) {
\r
481 super(BOUNDS, null, null, c1, c2);
\r
484 public void paint(Graphics2D g) {
\r
485 g.setStroke(STROKE);
\r
486 Graphics2D sg = (Graphics2D) g.create();
\r
488 sg.clipRect(-DIM*2, -DIM*2, DIM*4, DIM*2);
\r
490 sg.translate(0, -0.7*DIM);
\r
493 sg.translate(0, 1.4*DIM);
\r
497 g.clipRect(-DIM*2, 0, DIM*4, DIM*2);
\r
499 g.translate(0, 0.7*DIM);
\r
502 g.translate(0, -1.4*DIM);
\r
507 public static class TankSymbol extends PS implements Image {
\r
510 * Create tank shape.
\r
511 * @param r rectangle
\r
512 * @param cap cap size
\r
513 * @return tank shape
\r
515 public static Path2D createTankShape(Rectangle2D r, double cap)
\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
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
542 public void paint(Graphics2D g) {
\r
544 g.setStroke(GeometryUtils.BASIC_STROKE);
\r
554 public static class Tank2Symbol extends PS implements Image {
\r
556 public static Path2D createWShape()
\r
558 Path2D p = new Path2D.Double();
\r
559 double k = Math.sqrt(2);
\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
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
582 public void paint(Graphics2D g) {
\r
584 g.setStroke(GeometryUtils.BASIC_STROKE);
\r
585 g.setStroke(new BasicStroke(0.3f));
\r
592 double d = Math.min(bounds.getHeight(), bounds.getWidth());
\r
593 g.translate(bounds.getMinX()+d/2, bounds.getMinY()+d/2);
\r
600 private abstract static class PS implements Image {
\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
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
624 public int hashCode() {
\r
629 public boolean equals(Object obj) {
\r
630 if (!obj.getClass().equals(getClass()))return false;
\r
631 PS other = (PS) obj;
\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
639 public Rectangle2D getBounds() {
\r
644 public Shape getOutline() {
\r
649 public Node init(G2DParentNode g) {
\r
654 public void paint(Graphics2D g2d) { // FIXME: get rid of this
\r
659 public void addImageListener(ImageListener listener) {
\r
662 static EnumSet<Feature> caps = EnumSet.of(Feature.Vector);
\r
664 public EnumSet<Feature> getFeatures() {
\r
669 public void removeImageListener(ImageListener listener) {
\r