| 1 34 35 36 package org.krysalis.jcharts.axisChart; 37 38 39 import org.krysalis.jcharts.Chart; 40 import org.krysalis.jcharts.axisChart.axis.Axis; 41 import org.krysalis.jcharts.axisChart.axis.XAxis; 42 import org.krysalis.jcharts.axisChart.axis.YAxis; 43 import org.krysalis.jcharts.axisChart.axis.scale.AutomaticScaleCalculator; 44 import org.krysalis.jcharts.axisChart.axis.scale.ScaleCalculator; 45 import org.krysalis.jcharts.axisChart.axis.scale.UserDefinedScaleCalculator; 46 import org.krysalis.jcharts.chartData.ChartDataException; 47 import org.krysalis.jcharts.chartData.interfaces.IAxisChartDataSet; 48 import org.krysalis.jcharts.chartData.interfaces.IAxisDataSeries; 49 import org.krysalis.jcharts.chartData.interfaces.IAxisPlotDataSet; 50 import org.krysalis.jcharts.chartData.interfaces.IDataSeries; 51 import org.krysalis.jcharts.chartData.interfaces.IStockChartDataSet; 52 import org.krysalis.jcharts.chartData.processors.AxisChartDataProcessor; 53 import org.krysalis.jcharts.chartText.NumericTagGroup; 54 import org.krysalis.jcharts.chartText.TextTagGroup; 55 import org.krysalis.jcharts.imageMap.ImageMap; 56 import org.krysalis.jcharts.properties.AxisProperties; 57 import org.krysalis.jcharts.properties.AxisTypeProperties; 58 import org.krysalis.jcharts.properties.ChartProperties; 59 import org.krysalis.jcharts.properties.DataAxisProperties; 60 import org.krysalis.jcharts.properties.LegendAreaProperties; 61 import org.krysalis.jcharts.properties.LegendProperties; 62 import org.krysalis.jcharts.properties.PropertyException; 63 import org.krysalis.jcharts.test.HTMLChartTestable; 64 import org.krysalis.jcharts.test.HTMLGenerator; 65 import org.krysalis.jcharts.test.HTMLTestable; 66 import org.krysalis.jcharts.types.ChartType; 67 68 import java.awt.*; 69 import java.awt.font.FontRenderContext ; 70 import java.awt.geom.Rectangle2D ; 71 72 76 77 78 85 public class AxisChart extends Chart implements HTMLChartTestable 86 { 87 protected XAxis xAxis; 88 protected YAxis yAxis; 89 protected AxisProperties axisProperties; 90 91 private IAxisDataSeries iAxisDataSeries; 92 93 94 104 public AxisChart( IAxisDataSeries iAxisDataSeries, 105 ChartProperties chartProperties, 106 AxisProperties axisProperties, 107 LegendProperties legendProperties, 108 int pixelWidth, 109 int pixelHeight ) 110 { 111 super( legendProperties, chartProperties, pixelWidth, pixelHeight ); 112 this.axisProperties = axisProperties; 113 this.iAxisDataSeries = iAxisDataSeries; 114 } 115 116 117 121 public IAxisDataSeries getIAxisDataSeries() 122 { 123 return this.iAxisDataSeries; 124 } 125 126 127 133 public AxisChartDataProcessor createAxisChartDataProcessor() 134 { 135 return new AxisChartDataProcessor(); 136 } 137 138 147 protected NumericTagGroup setupDataAxisProperties( Axis axis, 148 DataAxisProperties dataAxisProperties, 149 AxisChartDataProcessor axisChartDataProcessor, 150 FontRenderContext fontRenderContext ) 151 { 152 if( dataAxisProperties.getScaleCalculator() == null ) 153 { 154 ScaleCalculator s; 155 156 if( dataAxisProperties.hasUserDefinedScale() ) 157 { 158 s = new UserDefinedScaleCalculator( dataAxisProperties.getUserDefinedMinimumValue(), dataAxisProperties.getUserDefinedIncrement() ); 159 } 160 else 161 { 162 s = new AutomaticScaleCalculator(); 163 if (this.axisProperties.getYAxisProperties().getMaxRightAxis()>0) 167 { 168 s.setMaxValue( this.axisProperties.getYAxisProperties().getMaxRightAxis() ); 169 } 170 else 171 { 172 s.setMaxValue( axisChartDataProcessor.getMaxValue() ); 173 } 174 175 if (this.axisProperties.getYAxisProperties().getMinRightAxis()<0) 176 { 177 s.setMinValue( this.axisProperties.getYAxisProperties().getMinRightAxis() ); 178 } 179 else 180 { 181 s.setMinValue( axisChartDataProcessor.getMinValue() ); 182 } 183 } 184 axis.setScaleCalculator( s ); 185 } 186 else 187 { 188 axis.setScaleCalculator( dataAxisProperties.getScaleCalculator() ); 189 193 if (this.axisProperties.getYAxisProperties().getMaxRightAxis()>0) 194 { 195 axis.getScaleCalculator().setMaxValue( this.axisProperties.getYAxisProperties().getMaxRightAxis() ); 196 } 197 else 198 { 199 axis.getScaleCalculator().setMaxValue( axisChartDataProcessor.getMaxValue() ); 200 } 201 202 if (this.axisProperties.getYAxisProperties().getMinRightAxis()<0) 203 { 204 axis.getScaleCalculator().setMinValue( this.axisProperties.getYAxisProperties().getMinRightAxis() ); 205 } 206 else 207 { 208 axis.getScaleCalculator().setMinValue( axisChartDataProcessor.getMinValue() ); 209 } 210 } 211 212 axis.getScaleCalculator().setRoundingPowerOfTen( dataAxisProperties.getRoundToNearest() ); 213 axis.getScaleCalculator().setNumberOfScaleItems( dataAxisProperties.getNumItems() ); 214 axis.getScaleCalculator().computeScaleValues(); 215 216 217 { 219 NumericTagGroup numericTagGroup = new NumericTagGroup( dataAxisProperties.getScaleChartFont(), 222 fontRenderContext, 223 dataAxisProperties.useDollarSigns(), 224 dataAxisProperties.usePercentSigns(), 225 dataAxisProperties.useCommas(), 226 dataAxisProperties.getRoundToNearest() ); 227 228 numericTagGroup.createAxisScaleLabels( axis.getScaleCalculator() ); 229 return numericTagGroup; 230 } 231 237 } 238 239 240 246 protected void setupAxis( AxisChartDataProcessor axisChartDataProcessor, FontRenderContext fontRenderContext ) throws ChartDataException 247 { 248 IDataSeries iDataSeries= (IDataSeries) this.getIAxisDataSeries(); 249 250 if( this.axisProperties.isPlotHorizontal() ) 251 { 252 DataAxisProperties dataAxisProperties = (DataAxisProperties) this.getAxisProperties().getXAxisProperties(); 254 this.xAxis = new XAxis( this, dataAxisProperties.getNumItems() ); 255 256 NumericTagGroup numericTagGroup= setupDataAxisProperties( this.xAxis, dataAxisProperties, axisChartDataProcessor, fontRenderContext ); 257 this.xAxis.setAxisLabelsGroup( numericTagGroup ); 258 259 260 AxisTypeProperties axisTypeProperties = this.getAxisProperties().getYAxisProperties(); 262 this.yAxis = new YAxis( this, axisChartDataProcessor.getNumberOfElementsInADataSet() ); 263 if( axisTypeProperties.showAxisLabels() ) 264 { 265 TextTagGroup textTagGroup = new TextTagGroup( axisTypeProperties.getScaleChartFont(), fontRenderContext ); 266 267 for( int i = 0; i < iDataSeries.getNumberOfAxisLabels(); i++ ) 269 { 270 if( iDataSeries.getAxisLabel( i ) == null ) 271 { 272 throw new ChartDataException( "None of the axis labels can be NULL." ); 273 } 274 textTagGroup.addLabel( iDataSeries.getAxisLabel( i ) ); 275 } 276 277 this.yAxis.setAxisLabelsGroup( textTagGroup ); 278 } 279 } 280 else 281 { 282 AxisTypeProperties axisTypeProperties = this.getAxisProperties().getXAxisProperties(); 284 this.xAxis = new XAxis( this, axisChartDataProcessor.getNumberOfElementsInADataSet() ); 285 if( axisTypeProperties.showAxisLabels() ) 286 { 287 TextTagGroup textTagGroup = new TextTagGroup( axisTypeProperties.getScaleChartFont(), fontRenderContext ); 288 289 for( int i = 0; i < iDataSeries.getNumberOfAxisLabels(); i++ ) 291 { 292 if( iDataSeries.getAxisLabel( i ) == null ) 293 { 294 throw new ChartDataException( "None of the axis labels can be NULL." ); 295 } 296 textTagGroup.addLabel( iDataSeries.getAxisLabel( i ) ); 297 } 298 299 this.xAxis.setAxisLabelsGroup( textTagGroup ); 300 } 301 302 DataAxisProperties dataAxisProperties = ( DataAxisProperties ) this.getAxisProperties().getYAxisProperties(); 304 this.yAxis = new YAxis( this, dataAxisProperties.getNumItems() ); 305 NumericTagGroup numericTagGroup= setupDataAxisProperties( this.yAxis, dataAxisProperties, axisChartDataProcessor, fontRenderContext ); 306 this.yAxis.setAxisLabelsGroup( numericTagGroup ); 307 if ( this.axisProperties.getYAxisProperties().getSecondScaleRight()!=1 ) 310 { 311 NumericTagGroup numericTagGroup2 = new NumericTagGroup( dataAxisProperties.getScaleChartFontRight(), 312 fontRenderContext, 313 dataAxisProperties.useDollarSigns(), 314 dataAxisProperties.usePercentSigns(), 315 dataAxisProperties.useCommas(), 316 dataAxisProperties.getRoundToNearest() ); 317 int j=0; 318 while (j<this.getYAxis().getNumberOfScaleItems()) 319 { 320 Float myFloat = new Float (this.yAxis.getAxisLabelsGroup().getTextTag(j).getText()); 321 float temp = myFloat.floatValue(); 322 String myString = new String (String.valueOf(Math.round(temp / this.axisProperties.getYAxisProperties().getSecondScaleRight())) ); 327 numericTagGroup2.addLabel(myString); 328 j++; 329 } 330 this.yAxis.setAxisLabelsGroupRight(numericTagGroup2); 331 } 332 } 333 334 335 this.yAxis.computeMinimumWidthNeeded( iDataSeries.getYAxisTitle() ); 337 this.xAxis.computeMinimumHeightNeeded( iDataSeries.getXAxisTitle() ); 338 } 339 340 341 348 private void sizeAndPositionAxis( float xAxisWidth, float yAxisHeight, float chartTitleHeight ) 349 { 350 if (this.axisProperties.getYAxisProperties().getShowRightAxis()) 354 xAxisWidth -= 2*this.yAxis.getMinimumWidthNeeded(); 355 else 356 xAxisWidth -= this.yAxis.getMinimumWidthNeeded(); 357 358 yAxisHeight -= this.xAxis.getMinimumHeightNeeded(); 359 360 this.xAxis.setPixelLength( xAxisWidth ); 362 363 if( axisProperties.getYAxisProperties().showAxisLabels() ) 364 { 365 this.yAxis.setPixelLength( yAxisHeight - this.yAxis.getAxisLabelsGroup().getTallestLabel() / 2 ); 366 } 367 else 368 { 369 this.yAxis.setPixelLength( yAxisHeight ); 370 } 371 372 if( this.getLegend() != null ) 373 { 374 if( ( this.getLegend().getLegendProperties().getPlacement() == LegendAreaProperties.RIGHT ) 376 || ( this.getLegend().getLegendProperties().getPlacement() == LegendAreaProperties.BOTTOM ) ) 377 { 378 this.xAxis.setOrigin( this.yAxis.getMinimumWidthNeeded() + super.getChartProperties().getEdgePadding() ); 379 this.yAxis.setOrigin( yAxisHeight + super.getChartProperties().getEdgePadding() + chartTitleHeight ); 380 } 381 else if( this.getLegend().getLegendProperties().getPlacement() == LegendAreaProperties.LEFT ) 382 { 384 this.xAxis.setOrigin( super.getImageWidth() - xAxisWidth - super.getChartProperties().getEdgePadding() ); 385 this.yAxis.setOrigin( yAxisHeight + super.getChartProperties().getEdgePadding() + chartTitleHeight ); 386 } 387 else if( this.getLegend().getLegendProperties().getPlacement() == LegendAreaProperties.TOP ) 388 { 389 this.xAxis.setOrigin( this.yAxis.getMinimumWidthNeeded() + super.getChartProperties().getEdgePadding() ); 390 this.yAxis.setOrigin( super.getImageHeight() - super.getChartProperties().getEdgePadding() - this.xAxis.getMinimumHeightNeeded() ); 391 } 392 } 393 else 394 { 395 this.xAxis.setOrigin( this.yAxis.getMinimumWidthNeeded() + super.getChartProperties().getEdgePadding() ); 396 this.yAxis.setOrigin( yAxisHeight + super.getChartProperties().getEdgePadding() + chartTitleHeight ); 397 } 398 } 399 400 401 404 protected void deriveAxisValues() 405 { 406 this.xAxis.computeLabelFilter(); 407 this.xAxis.computeShouldTickStartAtYAxis( this.iAxisDataSeries, this.axisProperties.getXAxisProperties() ); 408 409 if( this.axisProperties.isPlotHorizontal() ) 410 { 411 414 416 this.xAxis.computeScalePixelWidthDataAxis( this.axisProperties.getXAxisProperties() ); 417 418 this.yAxis.computeScalePixelWidth( this.axisProperties.getYAxisProperties() ); 419 this.xAxis.computeOneUnitPixelSize( this.xAxis.getScalePixelWidth(), this.xAxis.getScaleCalculator().getIncrement() ); 420 421 422 float zeroLineCoordinate = ( float ) ( this.xAxis.getOrigin() + ( this.xAxis.getScalePixelWidth() * ( -this.xAxis.getScaleCalculator().getMinValue() ) ) / this.xAxis.getScaleCalculator().getIncrement() ); 424 this.xAxis.setZeroLineCoordinate( zeroLineCoordinate ); 425 } 426 else 427 { 428 430 this.xAxis.computeScalePixelWidth( this.axisProperties.getXAxisProperties() ); 431 this.yAxis.computeScalePixelWidthDataAxis( this.axisProperties.getYAxisProperties() ); 432 this.yAxis.computeOneUnitPixelSize( this.yAxis.getScalePixelWidth(), this.yAxis.getScaleCalculator().getIncrement() ); 433 434 float zeroLineCoordinate = ( float ) ( this.yAxis.getOrigin() - ( this.yAxis.getScalePixelWidth() * ( -this.yAxis.getScaleCalculator().getMinValue() ) ) / this.yAxis.getScaleCalculator().getIncrement() ); 436 this.yAxis.setZeroLineCoordinate( zeroLineCoordinate ); 437 } 438 439 this.xAxis.computeTickStart(); 440 } 441 442 443 450 protected void renderChart() throws ChartDataException, PropertyException 451 { 452 if( super.getChartProperties().validate() ) 453 { 454 this.iAxisDataSeries.validate(); 455 } 456 457 this.validateHorizontalPlot(); 459 460 461 Graphics2D g2d = super.getGraphics2D(); 462 463 464 FontRenderContext fontRenderContext = g2d.getFontRenderContext(); 465 466 467 float edgePaddingTimesTwo = super.getChartProperties().getEdgePadding() * 2; 469 470 471 float xAxisWidth = super.getImageWidth() - edgePaddingTimesTwo; 473 float yAxisHeight = super.getImageHeight() - edgePaddingTimesTwo; 474 475 476 float chartTitleHeight = super.renderChartTitle( this.getIAxisDataSeries().getChartTitle(), fontRenderContext ); 478 yAxisHeight -= chartTitleHeight; 479 480 481 if( super.getLegend() != null ) 483 { 484 super.getLegend().computeLegendXY( this.iAxisDataSeries, chartTitleHeight ); 486 487 if( ( super.getLegend().getLegendProperties().getPlacement() == LegendAreaProperties.RIGHT ) 488 || ( super.getLegend().getLegendProperties().getPlacement() == LegendAreaProperties.LEFT ) ) 489 { 490 xAxisWidth -= super.getLegend().getLegendProperties().getChartPadding(); 491 xAxisWidth -= super.getLegend().getWidth(); 492 } 493 else { 495 yAxisHeight -= this.getLegend().getLegendProperties().getChartPadding(); 496 yAxisHeight -= this.getLegend().getHeight(); 497 } 498 499 super.getLegend().render(); 500 } 501 502 503 AxisChartDataProcessor axisChartDataProcessor = this.createAxisChartDataProcessor(); 504 axisChartDataProcessor.processData( this, fontRenderContext ); 505 506 507 this.setupAxis( axisChartDataProcessor, fontRenderContext ); 508 this.sizeAndPositionAxis( xAxisWidth, yAxisHeight, chartTitleHeight ); 509 this.deriveAxisValues(); 510 511 512 513 if( this.getAxisProperties().getBackgroundPaint() != null ) 515 { 516 Rectangle2D.Float rectangle = new Rectangle2D.Float ( this.xAxis.getOrigin() + 1, 517 this.yAxis.getOrigin() - this.yAxis.getPixelLength(), 518 this.xAxis.getPixelLength(), 519 this.yAxis.getPixelLength() ); 520 g2d.setPaint( this.axisProperties.getBackgroundPaint() ); 521 g2d.fill( rectangle ); 522 } 523 524 525 this.yAxis.render( g2d, this.getAxisProperties(), iAxisDataSeries.getYAxisTitle() ); 526 this.xAxis.render( g2d, this.getAxisProperties(), iAxisDataSeries.getXAxisTitle() ); 527 528 529 Rectangle2D.Float rectangle = new Rectangle2D.Float ( this.getXAxis().getOrigin(), 532 this.getYAxis().getOrigin() - this.getYAxis().getPixelLength() + 1, 533 this.xAxis.getPixelLength() + 1, 534 this.yAxis.getPixelLength() - 2 ); 535 g2d.setClip( rectangle ); 536 537 538 if( super.getGenerateImageMapFlag() ) 542 { 543 ImageMap imageMap = new ImageMap( iAxisDataSeries.size() * iAxisDataSeries.getTotalNumberOfDataSets() ); 545 super.setImageMap( imageMap ); 546 } 547 548 549 overlayCharts(); 551 } 552 553 554 560 protected void overlayCharts() throws PropertyException, ChartDataException 561 { 562 IAxisPlotDataSet iAxisPlotDataSet; 563 564 iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.AREA_STACKED ); 565 if( iAxisPlotDataSet != null ) 566 { 567 StackedAreaChart.render( this, ( IAxisChartDataSet ) iAxisPlotDataSet ); 568 } 569 iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.AREA ); 570 if( iAxisPlotDataSet != null ) 571 { 572 AreaChart.render( this, ( IAxisChartDataSet ) iAxisPlotDataSet ); 573 } 574 575 576 iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.BAR ); 577 if( iAxisPlotDataSet != null ) 578 { 579 BarChart.render( this, ( IAxisChartDataSet ) iAxisPlotDataSet ); 580 } 581 iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.BAR_STACKED ); 582 if( iAxisPlotDataSet != null ) 583 { 584 StackedBarChart.render( this, ( IAxisChartDataSet ) iAxisPlotDataSet ); 585 } 586 iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.BAR_CLUSTERED ); 587 if( iAxisPlotDataSet != null ) 588 { 589 ClusteredBarChart.render( this, ( IAxisChartDataSet ) iAxisPlotDataSet ); 590 } 591 592 593 iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.STOCK ); 594 if( iAxisPlotDataSet != null ) 595 { 596 StockChart.render( this, ( IStockChartDataSet ) iAxisPlotDataSet ); 597 } 598 599 600 iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.LINE ); 601 if( iAxisPlotDataSet != null ) 602 { 603 LineChart.render( this, ( IAxisChartDataSet ) iAxisPlotDataSet ); 604 } 605 606 iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.POINT ); 607 if( iAxisPlotDataSet != null ) 608 { 609 PointChart.render( this, ( IAxisChartDataSet ) iAxisPlotDataSet ); 610 } 611 } 612 613 614 620 private void validateHorizontalPlot() throws PropertyException 621 { 622 if( axisProperties.isPlotHorizontal() ) 623 { 624 if( this.iAxisDataSeries.size() > 1 ) 626 { 627 throw new PropertyException( "You can not have a combo chart on a horizontal plot." ); 628 } 629 630 if( !this.allowHorizontalPlot() ) 631 { 632 throw new PropertyException( "Horizontal plots are only supported in the Bar, Stacked Bar, and Clustered Bar Chart Types." ); 633 } 634 } 635 } 636 637 638 643 private boolean allowHorizontalPlot() 644 { 645 if( this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.BAR ) != null ) 646 { 647 return true; 648 } 649 650 if( this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.BAR_STACKED ) != null ) 651 { 652 return true; 653 } 654 655 if( this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.BAR_CLUSTERED ) != null ) 656 { 657 return true; 658 } 659 660 return false; 661 } 662 663 664 667 public AxisProperties getAxisProperties() 668 { 669 return this.axisProperties; 670 } 671 672 673 676 public XAxis getXAxis() 677 { 678 return this.xAxis; 679 } 680 681 682 685 public YAxis getYAxis() 686 { 687 return this.yAxis; 688 } 689 690 691 699 public void toHTML( HTMLGenerator htmlGenerator, String imageFileName, ImageMap imageMap ) 700 { 701 htmlGenerator.chartTableStart( this.getClass().getName(), imageFileName, imageMap ); 702 703 if( this.iAxisDataSeries instanceof HTMLTestable ) 704 { 705 ( ( HTMLTestable ) this.iAxisDataSeries ).toHTML( htmlGenerator ); 706 } 707 708 htmlGenerator.chartTableRowStart(); 710 this.axisProperties.toHTML( htmlGenerator ); 711 htmlGenerator.chartTableRowEnd(); 712 713 714 htmlGenerator.chartTableRowStart(); 716 this.xAxis.toHTML( htmlGenerator ); 717 htmlGenerator.chartTableRowEnd(); 718 719 htmlGenerator.chartTableRowStart(); 721 this.yAxis.toHTML( htmlGenerator ); 722 htmlGenerator.chartTableRowEnd(); 723 724 725 htmlGenerator.chartTableRowStart(); 727 super.getChartProperties().toHTML( htmlGenerator ); 728 htmlGenerator.chartTableRowEnd(); 729 730 731 if( super.getLegend() != null ) 732 { 733 htmlGenerator.chartTableRowStart(); 734 this.getLegend().toHTML( htmlGenerator ); 735 htmlGenerator.chartTableRowEnd(); 736 } 737 738 htmlGenerator.chartTableEnd(); 739 } 740 741 } 742 | Popular Tags |