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  import com.cosylab.gui.components.gauger.ScaleTransform.ArcSegment;
24  import com.cosylab.gui.components.gauger.ScaleTransform.RectangleSegment;
25  import com.cosylab.gui.components.range2.Tick;
26  //import com.cosylab.gui.components.range.Tick;
27  
28  import java.awt.BasicStroke;
29  import java.awt.Color;
30  import java.awt.FontMetrics;
31  import java.awt.Graphics2D;
32  import java.awt.Point;
33  import java.awt.Rectangle;
34  import java.awt.geom.Arc2D;
35  import java.awt.geom.Ellipse2D;
36  import java.awt.geom.Line2D;
37  import java.awt.geom.Point2D;
38  
39  
40  /**
41   * ScaleTransformRenderer renders the gauger component defined by ScaleTransform.
42   * This class is responsible for interpreting the transform and rendering
43   * background, scale and ticks. Renderer will render custom defined
44   * scale segments.
45   *
46   * @author <a href="mailto:ales.pucelj@cosylab.com">Ales Pucelj</a>
47   * @version $id$
48   */
49  public class ScaleTransformRenderer
50  {
51  	private Gauger gauger;
52  	private ScaleTransform transform;
53  
54  	/**
55  	 * Creates a new ScaleTransformRenderer object.
56  	 *
57  	 * @param gauger Gauger which this transform will render.
58  	 */
59  	public ScaleTransformRenderer(Gauger gauger)
60  	{
61  		super();
62  		this.gauger = gauger;
63  	}
64  
65  	/**
66  	 * Renders background of gauger. Fills the area with background color of
67  	 * gauger.
68  	 *
69  	 * @param g Context to render to.
70  	 */
71  	public void renderBackground(Graphics2D g)
72  	{
73  		g.setColor(gauger.getBackground());
74  
75  		g.fillRect(0, 0, gauger.getWidth(), gauger.getHeight());
76  	}
77  
78  	protected void renderRectangleSegment(Graphics2D g,
79  	    ScaleTransform.RectangleSegment segment, int n, int i)
80  	{
81  		Rectangle r = segment.rect;
82  
83  		int x1 = r.x;
84  		int x2 = r.x + r.width;
85  		int y1 = r.y;
86  		int y2 = r.y + r.height;
87  
88  		g.fillRect(x1, y1, r.width, r.height);
89  
90  		g.setColor(Color.black);
91  
92  		g.drawLine(x1, y1, x2, y1);
93  		g.drawLine(x1 + 1, y1 + 1, x2 - 1, y1 + 1);
94  
95  		if(i == 0) {
96  			g.drawLine(x1, y1 + 1, x1, y2);
97  			g.drawLine(x1 + 1, y1 + 1, x1 + 1, y2 - 1);
98  		}
99  
100 		g.setColor(Color.white);
101 
102 		g.drawLine(x1 + 1, y2, x2, y2);
103 		g.drawLine(x1 + 2, y2 - 1, x2, y2 - 1);
104 
105 		if(i == n - 1) {
106 			g.drawLine(x2, y1 + 1, x2, y2);
107 			g.drawLine(x2 - 1, y1 + 2, x2, y2);
108 		}
109 	}
110 
111 	/**
112 	 * Renders scale. Renders individual scale segments.
113 	 *
114 	 * @param g Graphic context to render to.
115 	 */
116 	public void renderScale(Graphics2D g)
117 	{
118 		ScaleTransform.ScaleSegment segment;
119 
120 		int n = transform.getSegmentCount();
121 
122 		g.setColor(gauger.getScaleColor());
123 
124 		for(int i = 0; i < n; i++) {
125 			segment = transform.getSegment(i);
126 
127 			if(segment instanceof ScaleTransform.RectangleSegment) {
128 				renderRectangleSegment(g, (RectangleSegment)segment, n, i);
129 			}
130 
131 			if(segment instanceof ScaleTransform.ArcSegment) {
132 				renderArcSegment(g, (ArcSegment)segment, n, i);
133 			}
134 		}
135 	}
136 
137 	/**
138 	 * Renders borders and background of an arc segment. 
139 	 *
140 	 * @param g Graphic context to render to.
141 	 * @param segment Segment to render.
142 	 * @param n Total number of segments.
143 	 * @param i Current segment index.
144 	 */
145 	public void renderArcSegment(Graphics2D g, ArcSegment segment, int n, int i)
146 	{
147 		double r = segment.rInner;
148 		double R = segment.rOuter;
149 
150 		Point p1 = new Point();
151 		Point p2 = new Point();
152 
153 		g.translate(segment.center.getX(), segment.center.getY());
154 
155 		Arc2D arc = new Arc2D.Double();
156 
157 		g.setColor(gauger.getScaleColor());
158 
159 		arc.setArcType(Arc2D.PIE);
160 
161 		arc.setFrame(-R, -R, 2 * R, 2 * R);
162 		arc.setAngleStart(segment.startAngle);
163 		arc.setAngleExtent(-segment.arcAngle);
164 		g.fill(arc);
165 
166 		arc.setArcType(Arc2D.PIE);
167 		
168 		g.setColor(gauger.getBackground());
169 		arc.setFrame(-r, -r, 2 * r, 2 * r);
170 		arc.setAngleStart(segment.startAngle);
171 		arc.setAngleExtent(-segment.arcAngle);
172 		g.fill(arc);
173 
174 		Ellipse2D circle = new Ellipse2D.Double();
175 
176 		g.setColor(gauger.getBackground());
177 
178 		circle.setFrame(-r, -r, 2 * r, 2 * r);
179 		g.fill(circle);
180 
181 		arc.setArcType(Arc2D.OPEN);
182 
183 		g.setColor(Color.WHITE);
184 		arc.setFrame(-r, -r, 2 * r, 2 * r);
185 		arc.setAngleStart(segment.startAngle+0.03);
186 		arc.setAngleExtent(-segment.arcAngle-0.03);
187 		g.draw(arc);
188 
189 		BasicStroke s = new BasicStroke((float)2.0);
190 		g.setStroke(s);
191 
192 		if(i == n - 1) {
193 			double phi = segment.startAngle - segment.arcAngle;
194 			PolarPoint.polarToCartesian(p1, r, phi);
195 			PolarPoint.polarToCartesian(p2, R, phi);
196 
197 			g.drawLine(p1.x, p1.y, p2.x, p2.y);
198 		}
199 
200 		g.setColor(Color.BLACK);
201 
202 		if(i == 0) {
203 			PolarPoint.polarToCartesian(p1, r, segment.startAngle);
204 			PolarPoint.polarToCartesian(p2, R, segment.startAngle);
205 
206 			g.drawLine(p1.x, p1.y, p2.x, p2.y);
207 		}
208 
209 		g.setColor(Color.BLACK);
210 
211 		arc.setFrame(-R - 1, -R - 1, 2 * R + 2, 2 * R + 2);
212 		arc.setAngleStart(segment.startAngle);
213 		arc.setAngleExtent(-segment.arcAngle + 0.03);
214 
215 		g.draw(arc);
216 
217 		g.translate(-segment.center.getX(), -segment.center.getY());
218 	}
219 
220 	/**
221 	 * Renders ticks and tick labels.
222 	 *
223 	 * @param g Graphic context to render to.
224 	 */
225 	public void renderTicks(Graphics2D g)
226 	{
227 		//Tick[] ticks=null; /* edit apikus */
228 		Tick[] ticks = gauger.getTicks(); 
229 
230 		if((ticks == null) || (ticks.length < 2)) {
231 			return;
232 		}
233 
234 		final FontMetrics metrics = g.getFontMetrics();
235 		Tick tick;
236 		double xOfs;
237 		double phi;
238 		final int n = ticks.length;
239 
240 		g.setStroke(new BasicStroke(1.0f));
241 		g.setColor(Color.black);
242 		g.setFont(gauger.getTickTextFont());
243 
244 		Line2D line = new Line2D.Double();
245 
246 		Point2D p1 = transform.mapUVtoXY(0.5, 0);
247 //		Point2D p2 = transform.mapUVtoXY(0.5, 10000.0);
248 		//xOfs = -p1.distance(p2) * 0.0001;
249 		xOfs = -transform.scaleHeight(0.5);
250 		double mult = 1.0;
251 		if (Math.abs(xOfs) < 2*metrics.getHeight()) {
252 			mult = 0.5;
253 		}
254 
255 		final float textOffs = (float)(xOfs * 0.6*mult);
256 		final double minorOffs = xOfs * 0.25*mult;
257 		final double majorOffs = xOfs * 0.5 *mult;
258 
259 		for(int i = 0; i < n; i++) {
260 			tick = ticks[i];
261 
262 			transform.mapUVtoXY(tick.proportional, 0.0, p1);
263 
264 			phi = transform.getAngle(tick.proportional);
265 
266 			g.translate(p1.getX(), p1.getY());
267 			g.rotate(-phi);
268 
269 			if(tick.major) {
270 				line.setLine(0, 0, 0, majorOffs);
271 
272 				xOfs = -metrics.getStringBounds(tick.text, g).getCenterX();
273 
274 				g.drawString(tick.text, (float)xOfs, textOffs);
275 			} else {
276 				line.setLine(0, 0, 0, minorOffs);
277 			}
278 
279 			g.draw(line);
280 
281 			g.rotate(phi);
282 			g.translate(-p1.getX(), -p1.getY());
283 		}
284 	}
285 
286 	/**
287 	 * Render entire gauger.
288 	 *
289 	 * @param transform Transform used for rendering.
290 	 * @param g Graphic context to render to.
291 	 */
292 	public void render(ScaleTransform transform, Graphics2D g)
293 	{
294 		this.transform = transform;
295 		renderBackground(g);
296 		renderScale(g);
297 		renderTicks(g);
298 	}
299 }
300 
301 /* __oOo__ */