/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.g2d.elementclass.operationsymbols; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.Ellipse2D; import java.awt.geom.Path2D; import java.awt.geom.Rectangle2D; import java.util.EnumSet; import org.simantics.g2d.image.Image; import org.simantics.g2d.image.impl.Shadow; import org.simantics.g2d.image.impl.Shadow.ShadowParameters; import org.simantics.g2d.utils.GeometryUtils; import org.simantics.g2d.utils.PathUtils; import org.simantics.scenegraph.Node; import org.simantics.scenegraph.g2d.G2DParentNode; import org.simantics.utils.ObjectUtils; /** * @author Toni Kalajainen */ public class OperationSymbols { static final double SHADOW_SIZE = 100; static final Color BORDER_COLOR = Color.GRAY; static final Color FILL_COLOR = Color.GRAY; static final Color SECONDARY_COLOR = Color.GREEN; static final ShadowParameters SHADOW = new ShadowParameters(0.5, Color.BLACK, 2); static final Color HOT = new Color(50, 50, 200); static final Color COLD = new Color(190, 190, 255); public static final BoilerHeatExchanger[] BOILER_HES = new BoilerHeatExchanger[] { new BoilerHeatExchanger(null, HOT, HOT, null, HOT), new BoilerHeatExchanger(HOT, null, COLD, COLD, HOT), new BoilerHeatExchanger(HOT, null, COLD, null, HOT), new BoilerHeatExchanger(HOT, null, null, HOT, HOT) }; public static final Image BOILER_SYMBOL = new BoilerSymbol2(FILL_COLOR, FILL_COLOR, BOILER_HES); public static final Image BOILER_SHADOW = new Shadow(BOILER_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image COMPRESSOR_SYMBOL = new CompressorSymbol(FILL_COLOR, BORDER_COLOR); public static final Image COMPRESSOR_SHADOW = new Shadow(COMPRESSOR_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image NO_SPIN_SYMBOL = new NoSpinSymbol(FILL_COLOR, BORDER_COLOR); public static final Image NO_SPIN_SHADOW = new Shadow(NO_SPIN_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image CONTROLVALVE_SYMBOL = new ControlValveSymbol(BORDER_COLOR, FILL_COLOR); public static final Image CONTROLVALVE_SHADOW = new Shadow(CONTROLVALVE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image THREEWAYVALVE_SYMBOL = new ThreeWayValveSymbol(BORDER_COLOR, FILL_COLOR); public static final Image THREEWAYVALVE_SHADOW = new Shadow(THREEWAYVALVE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image HEATEXCHANGER_SYMBOL = new HeatExchangerSymbol(BORDER_COLOR, FILL_COLOR); public static final Image HEATEXCHANGER_SHADOW = new Shadow(HEATEXCHANGER_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image PUMP_SYMBOL = new PumpSymbol(BORDER_COLOR, FILL_COLOR); public static final Image PUMP_SHADOW = new Shadow(PUMP_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image SHUTOFFVALVE_SYMBOL = new ShutoffValveSymbol(BORDER_COLOR, FILL_COLOR); public static final Image SHUTOFFVALVE_SHADOW = new Shadow(SHUTOFFVALVE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image SWITCH_SYMBOL = new SwitchSymbol(BORDER_COLOR); public static final Image SWITCH_SHADOW = new Shadow(SWITCH_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image TURBINE_SYMBOL = new TurbineSymbol(BORDER_COLOR, FILL_COLOR); public static final Image TURBINE_SHADOW = new Shadow(TURBINE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image VOLTAGETRANSFORMER_SYMBOL = new VoltageTransformerSymbol(SECONDARY_COLOR, BORDER_COLOR); public static final Image VOLTAGETRANSFORMER_SHADOW = new Shadow(VOLTAGETRANSFORMER_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image CHIMNEY_SYMBOL = new ChimneySymbol(SECONDARY_COLOR, BORDER_COLOR); public static final Image CHIMNEY_SHADOW = new Shadow(CHIMNEY_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image GENERATOR_SYMBOL = new GeneratorSymbol(SECONDARY_COLOR, BORDER_COLOR); public static final Image GENERATOR_SHADOW = new Shadow(GENERATOR_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image TANK_SYMBOL = new TankSymbol(new Rectangle2D.Double(0,0, 20.0, 8.0), 2.0, SECONDARY_COLOR, BORDER_COLOR); public static final Image TANK_SHADOW = new Shadow(TANK_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static final Image TANK2_SYMBOL = new Tank2Symbol(new Rectangle2D.Double(0,0, 20.0, 8.0), 2.0, SECONDARY_COLOR, BORDER_COLOR, HOT); public static final Image TANK2_SHADOW = new Shadow(TANK2_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE); public static class BoilerSymbol extends PS implements Image { public static final int DIM = 10; public static final Polygon SHAPE = 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); public static final Rectangle2D BOUNDS = SHAPE.getBounds2D(); public BoilerSymbol(Color bc, Color fc) { super(SHAPE.getBounds2D(), bc, fc, null, null); } @Override public void paint(Graphics2D g) { // if (fc!=null) { // g.setColor(fc); // g.fill(SHAPE); // } // if (bc!=null) { // g.setColor(bc); // g.draw(SHAPE); // } } } public static class BoilerHeatExchanger { public final Color color; public final Color topLeft, topRight, bottomLeft, bottomRight; public BoilerHeatExchanger(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight, Color color) { this.bottomLeft = bottomLeft; this.bottomRight = bottomRight; this.color = color; this.topLeft = topLeft; this.topRight = topRight; } } public static class BoilerSymbol2 extends PS implements Image { public static Path2D HE = PathUtils.path(10,0, 0,0, 0,5, 5,10, -5,10, 0,15, 0,20); public static Rectangle2D getBoilerRect(BoilerHeatExchanger ... hes) { return new Rectangle2D.Double(-10, 0, 20, hes.length*25+25); } public static Shape getBoilerShape(BoilerHeatExchanger ... hes) { Path2D p = new Path2D.Double(); p.moveTo(-10, 10); p.lineTo( 0, 0); p.lineTo( 10, 10); double h = hes.length * 25; p.lineTo( 10, h+15); p.lineTo( 0, h+25); p.lineTo(-10, h+15); p.closePath(); return p; } private final Shape shape; private final BoilerHeatExchanger [] hes; public BoilerSymbol2(Color fc, Color bc, BoilerHeatExchanger ... hes) { super( getBoilerRect(hes), bc, fc, null, null); shape = getBoilerShape(hes); this.hes = hes; } @Override public void paint(Graphics2D g) { if (fc!=null) { g.setColor(fc); g.fill(shape); } if (bc!=null) { g.setColor(bc); g.draw(shape); } // paint heat exchangers g.translate(0, 15); for (BoilerHeatExchanger he : hes) { g.setColor(he.color); g.draw(HE); if (he.topLeft!=null) { g.setColor(he.topLeft); g.drawLine(-10, 0, 0, 0); } if (he.topRight!=null) { g.setColor(he.topRight); g.drawLine(0, 0, 10, 0); } if (he.bottomLeft!=null) { g.setColor(he.bottomLeft); g.drawLine(-10, 20, 0, 20); } if (he.bottomRight!=null) { g.setColor(he.bottomRight); g.drawLine(0, 20, 10, 20); } g.translate(0, 25); } } } public static class ChimneySymbol extends PS implements Image { public static final int DIM = 10; public static final int D2 = 8; public static final Shape C1 = new Ellipse2D.Double(-DIM, -DIM, DIM*2, DIM*2); public static final Shape C2 = new Ellipse2D.Double(-D2, -D2, D2*2, D2*2); public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-10, -10, 20, 40); public ChimneySymbol(Color fc, Color bc) { super( BOUNDS, bc, fc, null, null); assert(bc!=null); } @Override public void paint(Graphics2D g) { g.setColor(fc); g.fill(C2); g.fillRect(-5, 14, 10, 8); g.setColor(bc); g.draw(C1); g.draw(C2); g.drawLine(0, DIM, 0, 15); g.drawRect(-5, 14, 10, 8); g.drawLine(-5, 14, 5, 22); } } public static class GeneratorSymbol extends PS implements Image { public static final int DIM = 10; public static final Shape C1 = new Ellipse2D.Double(-DIM, -DIM, DIM*2, DIM*2); public static final Rectangle2D BOUNDS = C1.getBounds2D(); private final static Font FONT = Font.decode("Serif-12"); public GeneratorSymbol(Color fc, Color bc) { super( BOUNDS, bc, fc, null, null); assert(bc!=null && fc!=null); } @Override public void paint(Graphics2D g) { g.setColor(fc); g.fill(C1); g.setColor(bc); g.draw(C1); g.setFont(FONT); g.drawString("G", -4, 4); } } public static class NoSpinSymbol extends PS { public NoSpinSymbol(Color fc, Color bc) { super(BOUNDS, bc, fc, null, null); } public static final Stroke STROKE = new BasicStroke(1.5f); public static final int DIM = 10; public static final int D2 = 8; public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-DIM, -DIM, 2*DIM, 2*DIM); public static final Shape CIRCLE = new Ellipse2D.Double(-D2, -D2, D2*2, D2*2); @Override public void paint(Graphics2D g) { g.setStroke(STROKE); g.setColor(fc); g.fillRect(-DIM, -DIM, DIM*2, DIM*2); g.setColor(bc); g.drawRect(-DIM, -DIM, DIM*2, DIM*2); g.draw(CIRCLE); g.drawLine(-DIM/3, -DIM/3, DIM/3, DIM/3); g.drawLine(DIM/3, -DIM/3, -DIM/3, DIM/3); } } public static class ControlValveSymbol extends PS implements Image { public static final Stroke STROKE = new BasicStroke(1.5f); public static final int D = 10; public static final Path2D SHAPE = PathUtils.closedPath(-D,-D, -D,D, D,-D, D,D ); public static final Rectangle2D BOUNDS = SHAPE.getBounds2D(); public ControlValveSymbol(Color bc, Color fc) { super(BOUNDS, bc, fc, null, null); } @Override public void paint(Graphics2D g) { if (fc!=null) { g.setColor(fc); g.fill(SHAPE); } if (bc!=null) { g.setColor(bc); g.draw(SHAPE); } } } public static class ThreeWayValveSymbol extends PS implements Image { public static final Stroke STROKE = new BasicStroke(1.5f); public static final int D = 10; public static final Path2D SHAPE = 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 ); public static final Rectangle2D BOUNDS = SHAPE.getBounds2D(); public ThreeWayValveSymbol(Color bc, Color fc) { super(BOUNDS, bc, fc, null, null); } @Override public void paint(Graphics2D g) { if (fc!=null) { g.setColor(fc); g.fill(SHAPE); } if (bc!=null) { g.setColor(bc); g.draw(SHAPE); } } } public static class HeatExchangerSymbol extends PS { public HeatExchangerSymbol(Color bc, Color fc) { super(BOUNDS, bc, fc, null, null); } public static final Stroke STROKE = new BasicStroke(1.5f); public static final int D = 10; public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-D, -D, 2*D, 2*D); public static final int xPoints[] = new int [] {-D, 0, 0, -D/2, D/2, 0, 0, D}; public static final int yPoints[] = new int [] {D/2, D/2, D/8, 0, 0, -D/8, -D/2, -D/2}; @Override public void paint(Graphics2D g) { g.setColor(fc); g.fill(BOUNDS); g.setColor(bc); g.draw(BOUNDS); g.setStroke(STROKE); g.drawPolyline(xPoints, yPoints, xPoints.length); } } public static class PumpSymbol extends PS { public PumpSymbol(Color bc, Color fc) { super(BOUNDS, bc, fc, null, null); } public static final Stroke STROKE = new BasicStroke(1.5f); public static final int DIM = 10; public static final int D2 = 12; public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-D2, -D2, 2*D2, 2*D2); public static final Shape CIRCLE = new Ellipse2D.Double(-D2, -D2, D2*2, D2*2); public static final Polygon SHAPE = 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); @Override public void paint(Graphics2D g) { g.setColor(fc); g.fill(CIRCLE); g.setColor(bc); g.setStroke( STROKE ); g.draw(CIRCLE); g.draw(SHAPE); } } public static class ShutoffValveSymbol extends PS implements Image { public static final Stroke STROKE = new BasicStroke(1.5f); public static final int DIM = 10; public static final Path2D SHAPE = PathUtils.closedPath(-DIM,-DIM, -DIM,DIM, DIM,-DIM, DIM,DIM ); public static final Rectangle2D BOUNDS = SHAPE.getBounds2D(); public ShutoffValveSymbol(Color bc, Color fc) { super(BOUNDS, bc, fc, null, null); } @Override public void paint(Graphics2D g) { if (fc!=null) { g.setColor(fc); g.fill(SHAPE); } if (bc!=null) { g.setColor(bc); g.draw(SHAPE); g.drawLine(0, -DIM, 0, DIM); } } } public static class SwitchSymbol extends PS { public SwitchSymbol(Color bc) { super(BOUNDS, bc, null, null, null); } public static final Stroke STROKE = new BasicStroke(1.5f); public static final int D = 10; public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-D, -D, 2*D, 2*D); @Override public void paint(Graphics2D g) { g.setColor(bc); g.setStroke(STROKE); g.drawLine(0, -D, 0, D); g.drawLine(-D/4, -D/2, D/4, -D/2); g.drawLine(-D, 0, D, 0); g.drawLine(-D/4, D/2, D/4, D/2); } } public static class TurbineSymbol extends PS implements Image { public static final int DIM = 10; public static final Polygon SHAPE = new Polygon(new int[] {-DIM, -DIM, DIM, DIM}, new int[] {-DIM, DIM, DIM*2, -DIM*2}, 4); public static final Rectangle2D BOUNDS = SHAPE.getBounds2D(); public TurbineSymbol(Color bc, Color fc) { super(BOUNDS, bc, fc, null, null); } @Override public void paint(Graphics2D g) { if (fc!=null) { g.setColor(fc); g.fill(SHAPE); } if (bc!=null) { g.setColor(bc); g.draw(SHAPE); } } } public static class CompressorSymbol extends PS implements Image { public static final int DIM = 10; public static final Polygon SHAPE = new Polygon(new int[] {DIM, DIM, -DIM, -DIM}, new int[] {-DIM, DIM, DIM*2, -DIM*2}, 4); public static final Rectangle2D BOUNDS = SHAPE.getBounds2D(); public CompressorSymbol(Color bc, Color fc) { super(BOUNDS, bc, fc, null, null); } @Override public void paint(Graphics2D g) { if (fc!=null) { g.setColor(fc); g.fill(SHAPE); } if (bc!=null) { g.setColor(bc); g.draw(SHAPE); } } } public static class VoltageTransformerSymbol extends PS implements Image { public static final Stroke STROKE = new BasicStroke(1.5f); public static final int DIM = 10; public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-DIM, -DIM*1.7, 2*DIM, 2*DIM*1.7); public static final Shape CIRCLE = new Ellipse2D.Double(-DIM, -DIM, DIM*2, DIM*2); public VoltageTransformerSymbol(Color c1, Color c2) { super(BOUNDS, null, null, c1, c2); } @Override public void paint(Graphics2D g) { g.setStroke(STROKE); Graphics2D sg = (Graphics2D) g.create(); sg.clipRect(-DIM*2, -DIM*2, DIM*4, DIM*2); sg.setColor(c1); sg.translate(0, -0.7*DIM); sg.draw(CIRCLE); sg.setColor(c2); sg.translate(0, 1.4*DIM); sg.draw(CIRCLE); sg.dispose(); g.clipRect(-DIM*2, 0, DIM*4, DIM*2); g.setColor(c2); g.translate(0, 0.7*DIM); g.draw(CIRCLE); g.setColor(c1); g.translate(0, -1.4*DIM); g.draw(CIRCLE); } } public static class TankSymbol extends PS implements Image { /** * Create tank shape. * @param r rectangle * @param cap cap size * @return tank shape */ public static Path2D createTankShape(Rectangle2D r, double cap) { double x1 = r.getMinX(); double y1 = r.getMinY(); double x2 = r.getMaxX(); double y2 = r.getMaxY(); Path2D p = new Path2D.Double(); p.moveTo(x1+cap, y1); p.lineTo(x2-cap, y1); p.quadTo(x2,y1, x2,y1+cap); p.lineTo(x2, y2-cap); p.quadTo(x2, y2, x2-cap, y2); p.lineTo(x1+cap, y2); p.quadTo(x1, y2, x1, y2-cap); p.lineTo(x1, y1+cap); p.quadTo(x1, y1, x1+cap, y1); return p; } Path2D shape; public TankSymbol(Rectangle2D rect, double cap, Color bc, Color fc) { super(rect, bc, fc, null, null); shape = createTankShape(rect, cap); } @Override public void paint(Graphics2D g) { g.setColor(fc); g.setStroke(GeometryUtils.BASIC_STROKE); g.fill(shape); if (bc!=null) { g.setColor(bc); g.draw(shape); } } } public static class Tank2Symbol extends PS implements Image { public static Path2D createWShape() { Path2D p = new Path2D.Double(); double k = Math.sqrt(2); p.moveTo(-1, -1); p.quadTo(0, -k, 1, -1); p.quadTo(k, 0, 1, 1); p.quadTo(0, k, -1, 1); p.quadTo(-k, 0, -1, -1); p.lineTo(-1, 1); p.lineTo(0,0); p.lineTo(1, 1); p.lineTo(1, -1); return p; } Path2D shape; Path2D shape2; public Tank2Symbol(Rectangle2D rect, double cap, Color bc, Color fc, Color a1) { super(rect, bc, fc, a1, null); shape = TankSymbol.createTankShape(rect, cap); shape2 = createWShape(); } @Override public void paint(Graphics2D g) { g.setColor(fc); g.setStroke(GeometryUtils.BASIC_STROKE); g.setStroke(new BasicStroke(0.3f)); g.fill(shape); if (bc!=null) { g.setColor(bc); g.draw(shape); } g.setColor(c1); double d = Math.min(bounds.getHeight(), bounds.getWidth()); g.translate(bounds.getMinX()+d/2, bounds.getMinY()+d/2); g.scale(d/3, d/3); g.draw(shape2); } } private abstract static class PS implements Image { public final Rectangle2D bounds; public final Color c1; public final Color c2; public final Color bc; public final Color fc; private final int hash; public PS(Rectangle2D bounds, Color bc, Color fc, Color c1, Color c2) { this.bounds = bounds; this.bc = bc; this.fc = fc; this.c1 = c1; this.c2 = c2; int hash = this.getClass().hashCode(); if (bc!=null) hash += 3 * bc.hashCode(); if (fc!=null) hash += 5 * fc.hashCode(); if (c1!=null) hash += 7 * c1.hashCode(); if (c2!=null) hash += 11 * c2.hashCode(); this.hash = hash; } @Override public int hashCode() { return hash; } @Override public boolean equals(Object obj) { if (!obj.getClass().equals(getClass()))return false; PS other = (PS) obj; return ObjectUtils.objectEquals(other.c1, c1) && ObjectUtils.objectEquals(other.c2, c2) && ObjectUtils.objectEquals(other.fc, fc) && ObjectUtils.objectEquals(other.bc, bc); } @Override public Rectangle2D getBounds() { return bounds; } @Override public Shape getOutline() { return bounds; } @Override public Node init(G2DParentNode g) { // return init(g); return null; } public void paint(Graphics2D g2d) { // FIXME: get rid of this } @Override public void addImageListener(ImageListener listener) { } static EnumSet caps = EnumSet.of(Feature.Vector); @Override public EnumSet getFeatures() { return caps; } @Override public void removeImageListener(ImageListener listener) { } } }