View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of CosyBeans-Common.
5    *
6    * CosyBeans-Common is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * CosyBeans-Common is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with CosyBeans-Common.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.gui.components.gauger;
21  
22  import com.cosylab.gui.components.Gauger;
23  
24  import java.awt.Color;
25  import java.awt.Graphics2D;
26  import java.awt.Point;
27  import java.awt.Polygon;
28  import java.awt.Rectangle;
29  
30  
31  /**
32   * Component defining and rendering the needle.
33   *
34   * @author <a href="mailto:ales.pucelj@cosylab.com">Ales Pucelj</a>
35   * @version $id$
36   */
37  public class Needle implements ActiveElement
38  {
39  	/* Scale appearance */
40  
41  	/** Relative length of needle as fraction of scale space height */
42  	private final static double RELATIVE_NEEDLE_SIZE = 0.6;
43  	//private static final int DISTANCE_SIGNIFICANT_CHANGE = 2;
44  	//private static final double ANGLE_SIGNIFICANT_CHANGE = 10;
45  	//private static final int DEFAULT_SIZE = 15;
46  	//private static final double DEFAULT_ANGLE = 90;
47  	private static final double DEFAULT_RATIO = 7.0;
48  	private Gauger gauger;
49  	private boolean changeSignificant;
50  	private Point p;
51  	private double angle;
52  	private Rectangle bounds = new Rectangle(0, 0, 0, 0);
53  	private double currentPosition = 0.5;
54  	protected ScaleTransform transform = null;
55  	private double[] xValues = new double[3];
56  	private double[] yValues = new double[3];
57  	private Polygon poly = new Polygon(new int[3], new int[3], 3);
58  	private boolean outOfBounds=false;
59  	
60  	/**
61  	 * Needle constructor comment.
62  	 *
63  	 * @param gauger on which the needle will be rendered.
64  	 */
65  	public Needle(Gauger gauger)
66  	{
67  		p = new Point();
68  		angle = 0;
69  		this.gauger = gauger;
70  		changeSignificant = true;
71  	}
72  
73  	/**
74  	 * Updates the polygon representation of the needle.
75  	 */
76  	protected synchronized void calculatePolygon()
77  	{
78  		double sin = Math.sin(angle);
79  		double cos = Math.cos(angle);
80  
81  		for(int i = 0; i < xValues.length; i++) {
82  			double xi = xValues[i];
83  			double yi = yValues[i];
84  			poly.xpoints[i] = (int)(xi * sin - yi * cos + p.x);
85  			poly.ypoints[i] = (int)(xi * cos + yi * sin + p.y);
86  		}
87  
88  		poly.invalidate();
89  
90  		bounds = poly.getBounds();
91  		bounds.grow(3, 3);
92  	}
93  
94  	private synchronized final void invalidate()
95  	{
96  		double size = transform.scaleHeight(0.5) * RELATIVE_NEEDLE_SIZE;
97  		double s = (size / DEFAULT_RATIO);
98  		yValues[0] = -s;
99  		xValues[0] = 0;
100 
101 		yValues[1] = 0;
102 		xValues[1] = -size;
103 
104 		yValues[2] = s;
105 		xValues[2] = 0;
106 	}
107 
108 	/**
109 	 * Returns bounding rectangle of needle.
110 	 *
111 	 * @return Bounding rectangle of needle.
112 	 */
113 	public Rectangle getBounds()
114 	{
115 		return bounds;
116 	}
117 
118 	/**
119 	 * Returns true if needle has moved enough to require immediate redraw.
120 	 *
121 	 * @return True if needle should be redrawn immediatelly.
122 	 */
123 	public boolean isChangeSignificant()
124 	{
125 		return changeSignificant;
126 	}
127 
128 	protected void updatePosition(double x)
129 	{
130 		if((transform != null)) {
131 			changeSignificant = true;
132 
133 		//checkChangeSignificant(tempPoint1.x, tempPoint1.y, phi);
134 			if(changeSignificant) {
135 				transform.mapUVtoXY(x, 0, p);
136 
137 				angle = transform.getAngle(x);
138 				calculatePolygon();
139 			}
140 		}
141 	}
142 
143 	/**
144 	 * Sets position of needle in scale space coordinates. Value is relative
145 	 * position between 0.0 and 1.0 inclusively.
146 	 *
147 	 * @param proportionalPosition New position of needle.
148 	 */
149 	public void setPosition(double proportionalPosition)
150 	{
151 		updatePosition(proportionalPosition);
152 
153 		if(changeSignificant) {
154 			currentPosition = proportionalPosition;
155 		}
156 	}
157 
158 	/**
159 	 * Renders needle.
160 	 *
161 	 * @see ActiveElement#render(Graphics2D)
162 	 */
163 	public synchronized void render(Graphics2D g)
164 	{
165 	
166 		double position = (gauger.getValue()-gauger.getMinimum())/(gauger.getMaximum() - gauger.getMinimum());
167 
168 		if(outOfBounds == ( (position < 0) || (position>1.0) )) {
169 			g.setColor(gauger.getOutOfBoundsColor());
170 		} else if( (position <= gauger.getLowAlarmLimit()) || (position>=gauger.getHighAlarmLimit()) ){
171 			g.setColor(gauger.getAlarmColor());
172 		} else if( (position <= gauger.getLowWarningLimit()) || (position>=gauger.getHighWarningLimit()) ){ 
173 			g.setColor(gauger.getWarningColor());
174 		} else{
175 			g.setColor(gauger.getNeedleColor());
176 		}
177 		
178 		g.fillPolygon(poly);
179 		g.drawPolygon(poly);
180 
181 		g.setColor(Color.BLACK);
182 
183 		g.drawLine(poly.xpoints[0], poly.ypoints[0], poly.xpoints[1],
184 		    poly.ypoints[1]);
185 	}
186 
187 	/**
188 	 * Sets transform defining the gauger. This transform is used to render the
189 	 * needle at appropriate position and angle.
190 	 *
191 	 * @see ActiveElement#setTransform(ScaleTransform)
192 	 */
193 	public void setTransform(ScaleTransform transform)
194 	{
195 		this.transform = transform;
196 		invalidate();
197 		updatePosition(currentPosition);
198 	}
199 	
200 	/**
201 	 * NOT IMPLEMENTED!
202 	 * Returns true if value is out of bounds.
203 	 * 
204 	 * @return
205 	 */
206 	public boolean isOutOfBounds(){
207 		return outOfBounds;
208 	}
209 }
210 
211 /* __oOo__ */