KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSci > swing > JBarGraph


1 package JSci.swing;
2
3 import java.awt.*;
4 import java.awt.geom.Point2D JavaDoc;
5 import java.text.DecimalFormat JavaDoc;
6 import java.text.NumberFormat JavaDoc;
7 import java.text.ParseException JavaDoc;
8 import JSci.awt.*;import JSci.maths.ExtraMath;
9
10 /**
11 * A bar graph Swing component.
12 * Multiple series are side-by-side.
13 * @version 1.2
14 * @author Ismael Orenstein
15 */

16 public class JBarGraph extends JCategoryGraph2D {
17         /**
18         * Bar colors.
19         */

20         protected Color barColor[]={Color.blue,Color.green,Color.red,Color.yellow,Color.cyan,Color.lightGray,Color.magenta,Color.orange,Color.pink};
21         /**
22         * Min and max data points.
23         */

24         protected float minY,maxY;
25         /**
26         * Axis scaling.
27         */

28         private final float yIncPixels = 40.0f;
29         private float yInc;
30         private boolean autoYInc = true;
31         private float xScale,yScale;
32         protected int barWidth;
33         /**
34         * Padding.
35         */

36         protected final int barPad=0;
37         /**
38         * Axis numbering.
39         */

40         protected boolean numbering=true;
41         protected NumberFormat JavaDoc yNumberFormat = new DecimalFormat JavaDoc("##0.0");
42         /**
43         * Constructs a bar graph.
44         */

45         public JBarGraph(CategoryGraph2DModel cgm) {
46                 super(cgm);
47                 dataChanged(new GraphDataEvent(model));
48         }
49         /**
50         * Implementation of GraphDataListener.
51         * Application code will not use this method explicitly, it is used internally.
52         */

53         public void dataChanged(GraphDataEvent e) {
54                 minY=0.0f;
55                 maxY=Float.NEGATIVE_INFINITY;
56                 model.firstSeries();
57                 do {
58                         for(int i=0;i<model.seriesLength();i++) {
59                                 float tmp=model.getValue(i);
60                                 minY=Math.min(tmp,minY);
61                                 maxY=Math.max(tmp,maxY);
62                         }
63                 } while(model.nextSeries());
64                 if(minY==maxY) {
65                         minY-=0.5f;
66                         maxY+=0.5f;
67                 }
68                 setNumbering(numbering);
69         }
70         /**
71         * Sets the bar color of the nth series.
72         * @param n the index of the series.
73         * @param c the line color.
74         */

75         public final void setColor(int n,Color c) {
76                 barColor[n]=c;
77                 redraw();
78         }
79         /**
80         * Gets the bar color of the nth series.
81         * @param n the index of the series.
82         */

83         public final Color getColor(int n) {
84                 return barColor[n];
85         }
86         /**
87         * Turns axis numbering on/off.
88         */

89         public final void setNumbering(boolean flag) {
90                 numbering=flag;
91                 leftAxisPad=axisPad;
92                 if(numbering && getFont() != null) {
93                         // adjust leftAxisPad to accomodate y-axis numbering
94
final FontMetrics metrics = getFontMetrics(getFont());
95                         final int maxYNumLen = metrics.stringWidth(yNumberFormat.format(maxY));
96                         final int minYNumLen = metrics.stringWidth(yNumberFormat.format(minY));
97                         final int yNumPad = Math.max(minYNumLen, maxYNumLen);
98                         leftAxisPad+=yNumPad;
99                 }
100                 rescale();
101         }
102         public void addNotify() {
103                 super.addNotify();
104                 // getFont() is now not null
105
// recalculate padding
106
setNumbering(numbering);
107         }
108         /**
109         * Sets the display format used for axis numbering.
110         * Convenience method.
111         * @see #setYNumberFormat(NumberFormat)
112         */

113         public final void setNumberFormat(NumberFormat JavaDoc format) {
114                 yNumberFormat = format;
115                 setNumbering(numbering);
116         }
117         /**
118         * Sets the display format used for y-axis numbering.
119         */

120         public final void setYNumberFormat(NumberFormat JavaDoc format) {
121                 yNumberFormat = format;
122                 setNumbering(numbering);
123         }
124         /**
125         * Sets the y-axis numbering increment.
126         * @param dy use 0.0f for auto-adjusting (default).
127         */

128         public final void setYIncrement(float dy) {
129                 if(dy < 0.0f) {
130                         throw new IllegalArgumentException JavaDoc("Increment should be positive.");
131                 } else if(dy == 0.0f) {
132                         if(!autoYInc) {
133                                 autoYInc = true;
134                                 rescale();
135                         }
136                 } else {
137                         autoYInc = false;
138                         if(dy != yInc) {
139                                 yInc = dy;
140                                 rescale();
141                         }
142                 }
143         }
144         /**
145         * Returns the y-axis numbering increment.
146         */

147         public final float getYIncrement() {
148                 return yInc;
149         }
150     public final float getYMinimum() {
151         return minY;
152     }
153     public final float getYMaximum() {
154         return maxY;
155     }
156         /**
157         * Draws the graph axes.
158         */

159         protected final void drawAxes(Graphics g) {
160                 g.setColor(getForeground());
161 // axis - Swing optimised
162
if(minY > 0.0f) {
163                         g.drawLine(leftAxisPad-scalePad,getHeight()-axisPad,getWidth()-(axisPad-scalePad),getHeight()-axisPad);
164                 } else {
165                         g.drawLine(leftAxisPad-scalePad,origin.y,getWidth()-(axisPad-scalePad),origin.y);
166                 }
167                 g.drawLine(origin.x,axisPad-scalePad,origin.x,getHeight()-(axisPad-scalePad));
168 // x-axis labels
169
for(int x=0; x<model.seriesLength(); x++) {
170             drawXLabel(g, x);
171                 }
172 // numbering
173
if(numbering) {
174 // y-axis numbering
175
for(double y=yInc; y<=maxY; y+=yInc) {
176                 drawYLabel(g, (float) y);
177                         }
178                         for(double y=-yInc; y>=minY; y-=yInc) {
179                 drawYLabel(g, (float) y);
180                         }
181                 }
182         }
183     protected void drawXLabel(Graphics g, int x) {
184         Point p = dataToScreen(x+1.0f, 0.0f);
185         String JavaDoc str = model.getCategory(x);
186                 FontMetrics metrics = g.getFontMetrics();
187         int strWidth = metrics.stringWidth(str);
188                 int strHeight = metrics.getHeight();
189         boolean numberingAbove = (maxY <= 0.0f);
190         if(numberingAbove) {
191                     g.drawLine(p.x,p.y,p.x,p.y-5);
192             g.drawString(str, dataToScreen(x+0.5f-0.5f*strWidth/xScale, 0.0f).x, origin.y-5);
193         } else {
194             g.drawLine(p.x,p.y,p.x,p.y+5);
195             g.drawString(str, dataToScreen(x+0.5f-0.5f*strWidth/xScale, 0.0f).x, origin.y+strHeight);
196         }
197     }
198     protected void drawYLabel(Graphics g, float y) {
199         Point p = dataToScreen(0.0f, y);
200         String JavaDoc str = yNumberFormat.format(y);
201                 FontMetrics metrics = g.getFontMetrics();
202         int strWidth = metrics.stringWidth(str);
203                 int strHeight = metrics.getHeight();
204         g.drawLine(p.x, p.y, p.x-5, p.y);
205         g.drawString(str, p.x-8-strWidth, p.y+strHeight/3);
206     }
207         /**
208         * Draws the graph bars.
209         */

210         protected void drawBars(Graphics g) {
211 // bars
212
int numSeries=1;
213                 model.firstSeries();
214                 while(model.nextSeries())
215                         numSeries++;
216                 if(numSeries==1) {
217                         for(int i=0;i<model.seriesLength();i++)
218                                 drawBar(g, i, model.getValue(i), barColor[0], barWidth, 0);
219                 } else {
220                         final float subBarWidth = ((float)barWidth)/((float)numSeries);
221                         final int subBarPixelWidth = Math.round(subBarWidth);
222                         for(int i=0;i<model.seriesLength();i++) {
223                                 // draw
224
model.firstSeries();
225                                 for(int j=0;j<numSeries;j++) {
226                                         drawBar(g, i, model.getValue(i), barColor[j], subBarPixelWidth, Math.round(j*subBarWidth));
227                                         model.nextSeries();
228                                 }
229                         }
230                 }
231         }
232         /**
233         * Draws a bar.
234         */

235         private void drawBar(Graphics g, int pos, float value, Color color, int width, int xoffset) {
236                 final Point p = dataToScreen(pos, value);
237                 final int y = (value<0.0f ? origin.y : p.y);
238                 final int dy=Math.abs(p.y-origin.y);
239                 g.setColor(color);
240                 g.fillRect(p.x+barPad+xoffset, y, width, dy);
241                 g.setColor(Color.black);
242                 g.drawRect(p.x+barPad+xoffset, y, width, dy);
243         }
244         /**
245         * Paint the graph.
246         */

247         protected void offscreenPaint(Graphics g) {
248                 drawBars(g);
249                 drawAxes(g);
250         }
251         /**
252         * Reshapes the bar graph to the specified bounding box.
253         */

254         public final void setBounds(int x,int y,int width,int height) {
255                 super.setBounds(x,y,width,height);
256                 rescale();
257         }
258         /**
259         * Rescales the bar graph.
260         */

261         protected final void rescale() {
262                 final Dimension minSize=getMinimumSize();
263                 // Swing optimised
264
final int thisWidth=Math.max(getWidth(),minSize.width);
265                 final int thisHeight=Math.max(getHeight(),minSize.height);
266                 xScale = (float)(thisWidth-(leftAxisPad+axisPad)) / (float)model.seriesLength();
267             float deltaY;
268             if(minY > 0.0f)
269                 deltaY = maxY;
270             else if(maxY < 0.0)
271                 deltaY = -minY;
272             else
273                 deltaY = maxY-minY;
274                 yScale = (float) ((double)(thisHeight-2*axisPad) / (double)(deltaY));
275                 if(autoYInc) {
276                         yInc = (float) ExtraMath.round((double)yIncPixels/(double)yScale, 1);
277                         if(yInc == 0.0f)
278                                 yInc = Float.MIN_VALUE;
279                 }
280                 barWidth=Math.round(xScale-2*barPad);
281                 origin.x=leftAxisPad;
282                 origin.y=thisHeight-axisPad+Math.round(minY*yScale);
283                 redraw();
284         }
285         /**
286         * Converts a data point to screen coordinates.
287         */

288         protected final Point dataToScreen(float x,float y) {
289                 return new Point(origin.x+Math.round(xScale*x),origin.y-Math.round(yScale*y));
290         }
291         /**
292         * Converts a screen point to data coordinates.
293         */

294         protected final Point2D.Float JavaDoc screenToData(Point p) {
295                 double x = (double)(p.x-origin.x) / (double)xScale;
296                 double y = (double)(origin.y-p.y) / (double)yScale;
297                 return new Point2D.Float JavaDoc((float)x, (float)y);
298         }
299 }
300
Popular Tags