1 6 7 package analyzer.charts; 8 9 import java.awt.BasicStroke ; 10 import java.awt.BorderLayout ; 11 import java.awt.Color ; 12 import java.awt.Dimension ; 13 import java.awt.GradientPaint ; 14 import java.awt.Graphics ; 15 import java.awt.Graphics2D ; 16 import java.awt.GridLayout ; 17 import java.awt.Image ; 18 import java.awt.Rectangle ; 19 import java.awt.RenderingHints ; 20 import java.awt.Shape ; 21 import java.awt.Stroke ; 22 import java.awt.event.ComponentEvent ; 23 import java.awt.event.WindowAdapter ; 24 import java.awt.event.WindowEvent ; 25 import java.awt.event.WindowListener ; 26 import java.awt.geom.AffineTransform ; 27 import java.awt.geom.Arc2D ; 28 import java.awt.geom.GeneralPath ; 29 import java.awt.geom.Rectangle2D ; 30 31 import javax.swing.ImageIcon ; 32 import javax.swing.JComponent ; 33 import javax.swing.JFrame ; 34 import javax.swing.JLabel ; 35 import javax.swing.JPanel ; 36 37 public class ChartMaker extends JPanel { 38 public static final int LineChart = 0; 39 40 public static final int ColumnChart = 1; 41 42 public static final int PieChart = 2; 43 44 public static final int PLainEffect = 0; 45 46 public static final int Gradientffect = 1; 47 48 public static final int ImageEffect = 2; 49 50 protected int m_chartType = LineChart; 51 52 protected JLabel titleLabel; 53 54 protected ChartPanel chartPanel; 55 56 protected int dataLength; 57 58 protected int[] xData; 59 60 protected int[] yData; 61 62 protected int xMin; 63 64 protected int xMax; 65 66 protected int yMin; 67 68 protected int yMax; 69 70 protected double[] pieData; 71 72 protected int m_effectIndex = PLainEffect; 73 74 protected Stroke stroke; 75 76 protected GradientPaint gradient; 77 78 protected Image foregroundImage; 79 80 protected Color lineColor = Color.black; 81 82 protected Color columnColor = Color.blue; 83 84 protected int columnWidth = 12; 85 86 protected boolean drawShadow = false; 87 88 public ChartMaker(int type, int nData, int[] yData, String text) { 89 this(type, nData, null, yData, text); 90 } 91 92 public ChartMaker(int type, int nData, int[] xD, int[] yD, String text) { 93 super(new BorderLayout ()); 94 setBackground(Color.white); 95 titleLabel = new JLabel (text, JLabel.CENTER); 96 add(titleLabel, BorderLayout.NORTH); 97 98 m_chartType = type; 99 100 if (xData == null) { 101 xData = new int[nData]; 102 for (int k = 0; k < nData; k++) 103 xData[k] = k; 104 } 105 if (yD == null) 106 throw new IllegalArgumentException ("yData can't be null"); 107 if (nData > yD.length) 108 throw new IllegalArgumentException ("Insufficient yData length"); 109 if (nData > xD.length) 110 throw new IllegalArgumentException ("Insufficient xData length"); 111 dataLength = nData; 112 xData = xD; 113 yData = yD; 114 115 xMin = xMax = 0; yMin = yMax = 0; 117 for (int k = 0; k < dataLength; k++) { 118 xMin = Math.min(xMin, xData[k]); 119 xMax = Math.max(xMax, xData[k]); 120 yMin = Math.min(yMin, yData[k]); 121 yMax = Math.max(yMax, yData[k]); 122 } 123 if (xMin == xMax) 124 xMax++; 125 if (yMin == yMax) 126 yMax++; 127 128 if (m_chartType == PieChart) { 129 double sum = 0; 130 for (int k = 0; k < dataLength; k++) { 131 yData[k] = Math.max(yData[k], 0); 132 sum += yData[k]; 133 } 134 pieData = new double[dataLength]; 135 for (int k = 0; k < dataLength; k++) 136 pieData[k] = yData[k] * 360.0 / sum; 137 } 138 139 chartPanel = new ChartPanel(); 140 add(chartPanel, BorderLayout.CENTER); 141 } 142 143 public void setEffectIndex(int effectIndex) { 144 m_effectIndex = effectIndex; 145 repaint(); 146 } 147 148 public int getEffectIndex() { 149 return m_effectIndex; 150 } 151 152 public void setStroke(Stroke s) { 153 stroke = s; 154 chartPanel.repaint(); 155 } 156 157 public void setForegroundImage(Image img) { 158 foregroundImage = img; 159 repaint(); 160 } 161 162 public Image getForegroundImage() { 163 return foregroundImage; 164 } 165 166 public Stroke getStroke() { 167 return stroke; 168 } 169 170 public void setGradient(GradientPaint g) { 171 gradient = g; 172 repaint(); 173 } 174 175 public GradientPaint getGradient() { 176 return gradient; 177 } 178 179 public void setColumnWidth(int c) { 180 columnWidth = c; 181 chartPanel.calcDimensions(); 182 chartPanel.repaint(); 183 } 184 185 public int setColumnWidth() { 186 return columnWidth; 187 } 188 189 public void setColumnColor(Color c) { 190 columnColor = c; 191 chartPanel.repaint(); 192 } 193 194 public Color getColumnColor() { 195 return columnColor; 196 } 197 198 public void setLineColor(Color c) { 199 lineColor = c; 200 chartPanel.repaint(); 201 } 202 203 public Color getLineColor() { 204 return lineColor; 205 } 206 207 public void setDrawShadow(boolean d) { 208 drawShadow = d; 209 chartPanel.repaint(); 210 } 211 212 public boolean getDrawShadow() { 213 return drawShadow; 214 } 215 216 class ChartPanel extends JComponent { 217 int xMargin = 5; 218 219 int yMargin = 5; 220 221 int pieGap = 10; 222 223 int m_x; 224 225 int m_y; 226 227 int m_w; 228 229 int m_h; 230 231 ChartPanel() { 232 enableEvents(ComponentEvent.COMPONENT_RESIZED); 233 } 234 235 protected void processComponentEvent(ComponentEvent e) { 236 calcDimensions(); 237 } 238 239 public void calcDimensions() { 240 Dimension d = getSize(); 241 m_x = xMargin; 242 m_y = yMargin; 243 m_w = d.width - 2 * xMargin; 244 m_h = d.height - 2 * yMargin; 245 if (m_chartType == ColumnChart) { 246 m_x += columnWidth / 2; 247 m_w -= columnWidth; 248 } 249 } 250 251 public int xChartToScreen(int x) { 252 return m_x + (x - xMin) * m_w / (xMax - xMin); 253 } 254 255 public int yChartToScreen(int y) { 256 return m_y + (yMax - y) * m_h / (yMax - yMin); 257 } 258 259 public void paintComponent(Graphics g) { 260 int x0 = 0; 261 int y0 = 0; 262 if (m_chartType != PieChart) { 263 g.setColor(Color.black); 264 x0 = xChartToScreen(0); 265 g.drawLine(x0, m_y, x0, m_y + m_h); 266 y0 = yChartToScreen(0); 267 g.drawLine(m_x, y0, m_x + m_w, y0); 268 } 269 270 Graphics2D g2 = (Graphics2D ) g; 271 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 272 RenderingHints.VALUE_ANTIALIAS_ON); 273 g2.setRenderingHint(RenderingHints.KEY_RENDERING, 274 RenderingHints.VALUE_RENDER_QUALITY); 275 276 if (stroke != null) 277 g2.setStroke(stroke); 278 279 GeneralPath path = new GeneralPath (); 280 switch (m_chartType) { 281 case LineChart: 282 g2.setColor(lineColor); 283 path.moveTo(xChartToScreen(xData[0]), 284 yChartToScreen(yData[0])); 285 for (int k = 1; k < dataLength; k++) 286 path.lineTo(xChartToScreen(xData[k]), 287 yChartToScreen(yData[k])); 288 g2.draw(path); 289 break; 290 291 case ColumnChart: 292 for (int k = 0; k < dataLength; k++) { 293 xMax++; int x = xChartToScreen(xData[k]); 294 int w = columnWidth; 295 int y1 = yChartToScreen(yData[k]); 296 int y = Math.min(y0, y1); 297 int h = Math.abs(y1 - y0); 298 Shape rc = new Rectangle2D.Double (x, y, w, h); 299 path.append(rc, false); 300 xMax--; 301 } 302 303 if (drawShadow) { 304 AffineTransform s0 = new AffineTransform (1.0, 0.0, 0.0, 305 -1.0, x0, y0); 306 s0.concatenate(AffineTransform.getScaleInstance(1.0, 0.5)); 307 s0.concatenate(AffineTransform.getShearInstance(0.5, 0.0)); 308 s0.concatenate(new AffineTransform (1.0, 0.0, 0.0, -1.0, 309 -x0, y0)); 310 g2.setColor(Color.gray); 311 Shape shadow = s0.createTransformedShape(path); 312 g2.fill(shadow); 313 } 314 315 if (m_effectIndex == Gradientffect && gradient != null) { 316 g2.setPaint(gradient); 317 g2.fill(path); 318 } else if (m_effectIndex == ImageEffect 319 && foregroundImage != null) 320 fillByImage(g2, path, 0); 321 else { 322 g2.setColor(columnColor); 323 g2.fill(path); 324 } 325 g2.setColor(lineColor); 326 g2.draw(path); 327 break; 328 329 case PieChart: 330 double start = 0.0; 331 double finish = 0.0; 332 int ww = m_w - 2 * pieGap; 333 int hh = m_h - 2 * pieGap; 334 if (drawShadow) { 335 ww -= pieGap; 336 hh -= pieGap; 337 } 338 339 for (int i = 0; i < dataLength; i++) { 340 finish = start + pieData[i]; 341 double f1 = Math.min(90 - start, 90 - finish); 342 double f2 = Math.max(90 - start, 90 - finish); 343 Shape shp = new Arc2D.Double (m_x, m_y, ww, hh, f1, f2 - f1, 344 Arc2D.PIE); 345 double f = (f1 + f2) / 2 * Math.PI / 180; 346 AffineTransform s1 = AffineTransform.getTranslateInstance( 347 pieGap * Math.cos(f), -pieGap * Math.sin(f)); 348 s1.translate(pieGap, pieGap); 349 Shape piece = s1.createTransformedShape(shp); 350 path.append(piece, false); 351 start = finish; 352 } 353 354 if (drawShadow) { 355 AffineTransform s0 = AffineTransform.getTranslateInstance( 356 pieGap, pieGap); 357 g2.setColor(Color.gray); 358 Shape shadow = s0.createTransformedShape(path); 359 g2.fill(shadow); 360 } 361 362 if (m_effectIndex == Gradientffect && gradient != null) { 363 g2.setPaint(gradient); 364 g2.fill(path); 365 } else if (m_effectIndex == ImageEffect 366 && foregroundImage != null) 367 fillByImage(g2, path, 0); 368 else { 369 g2.setColor(columnColor); 370 g2.fill(path); 371 } 372 373 g2.setColor(lineColor); 374 g2.draw(path); 375 break; 376 } 377 } 378 379 protected void fillByImage(Graphics2D g2, Shape shape, int xOffset) { 380 if (foregroundImage == null) 381 return; 382 int wImg = foregroundImage.getWidth(this); 383 int hImg = foregroundImage.getHeight(this); 384 if (wImg <= 0 || hImg <= 0) 385 return; 386 g2.setClip(shape); 387 Rectangle bounds = shape.getBounds(); 388 for (int i = bounds.x + xOffset; i < bounds.x + bounds.width; i += wImg) 389 for (int j = bounds.y; j < bounds.y + bounds.height; j += hImg) 390 g2.drawImage(foregroundImage, i, j, this); 391 } 392 } 393 } 394 | Popular Tags |