From: Nathaniel G. A. <nat...@us...> - 2004-10-20 13:35:02
|
Update of /cvsroot/jcharts/krysalis-jcharts/src/java/org/krysalis/jcharts In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30339/src/java/org/krysalis/jcharts Modified Files: Legend.java Log Message: partial fix for null shapes on lines Index: Legend.java =================================================================== RCS file: /cvsroot/jcharts/krysalis-jcharts/src/java/org/krysalis/jcharts/Legend.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** Legend.java 1 Jul 2004 00:06:17 -0000 1.12 --- Legend.java 20 Oct 2004 13:34:50 -0000 1.13 *************** *** 33,37 **** ************************************************************************************************/ - package org.krysalis.jcharts; --- 33,36 ---- *************** *** 64,72 **** ! /************************************************************************************* ! * * @author Nathaniel Auvil, Sandor Dornbush, Sundar Balasubramanian * @version $Id$ ! ************************************************************************************/ final public class Legend implements HTMLTestable, Serializable { --- 63,71 ---- ! /***************************************************************************************** ! * * @author Nathaniel Auvil, Sandor Dornbush, Sundar Balasubramanian * @version $Id$ ! ****************************************************************************************/ final public class Legend implements HTMLTestable, Serializable { *************** *** 76,80 **** private float iconSide; - //---derived values private float widestLabelAndColumnPadding; --- 75,78 ---- *************** *** 82,86 **** private int numRows; - private TextProcessor textProcessor; --- 80,83 ---- *************** *** 89,95 **** private float width = 0; private float height = 0; ! // for Bar chart legend shape - size is automatically calculated later on ! private Rectangle2D barShape = new Rectangle2D.Double(0, 0, 0, 0); private Stroke barStroke = new BasicStroke(); --- 86,92 ---- private float width = 0; private float height = 0; ! // for Bar chart legend shape - size is automatically calculated later on ! private Rectangle2D barShape = new Rectangle2D.Double( 0, 0, 0, 0 ); private Stroke barStroke = new BasicStroke(); *************** *** 106,114 **** ! /********************************************************************************************* ! * * @param chart * @deprecated ! **********************************************************************************************/ public Legend( Chart chart ) { --- 103,111 ---- ! /*************************************************************************************** ! * * @param chart * @deprecated ! **************************************************************************************/ public Legend( Chart chart ) { *************** *** 117,125 **** ! /********************************************************************************************* ! * * @param chart * @param legendProperties ! **********************************************************************************************/ public Legend( Chart chart, LegendProperties legendProperties ) { --- 114,122 ---- ! /*************************************************************************************** ! * * @param chart * @param legendProperties ! **************************************************************************************/ public Legend( Chart chart, LegendProperties legendProperties ) { *************** *** 141,149 **** ! /***************************************************************************************** ! * * @param iAxisDataSeries * @param chartTitleHeight ! ****************************************************************************************/ public void computeLegendXY( IAxisDataSeries iAxisDataSeries, float chartTitleHeight ) { --- 138,146 ---- ! /*************************************************************************************** ! * * @param iAxisDataSeries * @param chartTitleHeight ! **************************************************************************************/ public void computeLegendXY( IAxisDataSeries iAxisDataSeries, float chartTitleHeight ) { *************** *** 152,156 **** if( (this.getLegendProperties().getPlacement() == LegendAreaProperties.RIGHT) ! || (this.getLegendProperties().getPlacement() == LegendAreaProperties.LEFT) ) { if( this.getHeight() > this.chart.getImageHeight() - this.chart.getChartProperties().getEdgePadding() * 2 ) --- 149,153 ---- if( (this.getLegendProperties().getPlacement() == LegendAreaProperties.RIGHT) ! || (this.getLegendProperties().getPlacement() == LegendAreaProperties.LEFT) ) { if( this.getHeight() > this.chart.getImageHeight() - this.chart.getChartProperties().getEdgePadding() * 2 ) *************** *** 167,176 **** this.setX( this.chart.getImageWidth() - this.getWidth() - this.chart.getChartProperties().getEdgePadding() ); } ! else //---else, LegendAreaProperties.LEFT { this.setX( this.chart.getChartProperties().getEdgePadding() ); } } ! else //---LegendAreaProperties.BOTTOM, OR LegendAreaProperties.TOP { if( this.getWidth() + this.chart.getChartProperties().getEdgePadding() * 2 > this.chart.getImageWidth() ) --- 164,175 ---- this.setX( this.chart.getImageWidth() - this.getWidth() - this.chart.getChartProperties().getEdgePadding() ); } ! else ! //---else, LegendAreaProperties.LEFT { this.setX( this.chart.getChartProperties().getEdgePadding() ); } } ! else ! //---LegendAreaProperties.BOTTOM, OR LegendAreaProperties.TOP { if( this.getWidth() + this.chart.getChartProperties().getEdgePadding() * 2 > this.chart.getImageWidth() ) *************** *** 187,191 **** this.setY( this.chart.getImageHeight() - this.getHeight() - this.chart.getChartProperties().getEdgePadding() ); } ! else //---else, LegendAreaProperties.TOP { this.setY( this.chart.getChartProperties().getEdgePadding() + chartTitleHeight ); --- 186,191 ---- this.setY( this.chart.getImageHeight() - this.getHeight() - this.chart.getChartProperties().getEdgePadding() ); } ! else ! //---else, LegendAreaProperties.TOP { this.setY( this.chart.getChartProperties().getEdgePadding() + chartTitleHeight ); *************** *** 195,205 **** ! /********************************************************************************************** ! * Central method for processing data; try to minimize looping. ! * 1) calculate the maximum height of labels ! * 2) find the maximum label width ! * * @param iAxisDataSeries ! **********************************************************************************************/ private void processData( IAxisDataSeries iAxisDataSeries ) { --- 195,204 ---- ! /*************************************************************************************** ! * Central method for processing data; try to minimize looping. 1) calculate the maximum ! * height of labels 2) find the maximum label width ! * * @param iAxisDataSeries ! **************************************************************************************/ private void processData( IAxisDataSeries iAxisDataSeries ) { *************** *** 216,226 **** ! /********************************************************************************************** ! * Central method for processing data; try to minimize looping. ! * 1) calculate the maximum height of labels ! * 2) find the maximum label width ! * * @param iPieChartDataSet ! **********************************************************************************************/ private void processData( IPieChartDataSet iPieChartDataSet ) { --- 215,224 ---- ! /*************************************************************************************** ! * Central method for processing data; try to minimize looping. 1) calculate the maximum ! * height of labels 2) find the maximum label width ! * * @param iPieChartDataSet ! **************************************************************************************/ private void processData( IPieChartDataSet iPieChartDataSet ) { *************** *** 230,241 **** ! /********************************************************************************************** ! * Method for processing data for AxisPlot datasets; try to minimize ! * looping. ! * 1) calculate the maximum height of labels ! * 2) find the maximum label width ! * * @param iAxisPlotDataSet ! * *********************************************************************************************/ private void processLegendLabels( IAxisPlotDataSet iAxisPlotDataSet ) { --- 228,237 ---- ! /*************************************************************************************** ! * Method for processing data for AxisPlot datasets; try to minimize looping. 1) ! * calculate the maximum height of labels 2) find the maximum label width ! * * @param iAxisPlotDataSet ! **************************************************************************************/ private void processLegendLabels( IAxisPlotDataSet iAxisPlotDataSet ) { *************** *** 245,249 **** if( iAxisPlotDataSet.getLegendLabel( i ) != null ) { ! this.textProcessor.addLabel( iAxisPlotDataSet.getLegendLabel( i ), this.legendProperties.getChartFont().getFont(), this.chart.getGraphics2D().getFontRenderContext() ); //---pair labels with paints to get around ugly piechart vs axischart data structure mess --- 241,247 ---- if( iAxisPlotDataSet.getLegendLabel( i ) != null ) { ! this.textProcessor.addLabel( iAxisPlotDataSet.getLegendLabel( i ), ! this.legendProperties.getChartFont().getFont(), ! this.chart.getGraphics2D().getFontRenderContext() ); //---pair labels with paints to get around ugly piechart vs axischart data structure mess *************** *** 259,267 **** this.pointOutlinePaints.add( pointChartProperties.getPointOutlinePaints( i ) ); } ! if( iAxisPlotDataSet.getChartType().equals( ChartType.LINE ) ) { this.chartType = ChartType.LINE; this.lineChartProperties = (LineChartProperties) iAxisPlotDataSet.getChartTypeProperties(); ! this.strokes.add( lineChartProperties.getLineStrokes()[ i ] ); if( lineChartProperties.getShapes() != null ) { --- 257,265 ---- this.pointOutlinePaints.add( pointChartProperties.getPointOutlinePaints( i ) ); } ! else if( iAxisPlotDataSet.getChartType().equals( ChartType.LINE ) ) { this.chartType = ChartType.LINE; this.lineChartProperties = (LineChartProperties) iAxisPlotDataSet.getChartTypeProperties(); ! this.strokes.add( lineChartProperties.getLineStrokes()[i] ); if( lineChartProperties.getShapes() != null ) { *************** *** 269,279 **** } } ! else { // just put place holder shape in as well as stroke so that order is maintained ! // for combo bar and line charts. If we allow point/line/bar combos then we'll // also have to add fillPointsFlags and Paints ! this.shapes.add(barShape); ! this.strokes.add(barStroke); } } --- 267,277 ---- } } ! else { // just put place holder shape in as well as stroke so that order is maintained ! // for combo bar and line charts. If we allow point/line/bar combos then we'll // also have to add fillPointsFlags and Paints ! this.shapes.add( barShape ); ! this.strokes.add( barStroke ); } } *************** *** 282,291 **** ! /********************************************************************************************** ! * Method for processing data for PieCharts; try to minimize looping. ! * 1) calculate the maximum height of labels ! * 2) find the maximum label width * @param iPieChartDataSet ! * ********************************************************************************************/ private void processLegendLabels( IPieChartDataSet iPieChartDataSet ) { --- 280,289 ---- ! /*************************************************************************************** ! * Method for processing data for PieCharts; try to minimize looping. 1) calculate the ! * maximum height of labels 2) find the maximum label width ! * * @param iPieChartDataSet ! **************************************************************************************/ private void processLegendLabels( IPieChartDataSet iPieChartDataSet ) { *************** *** 295,301 **** if( iPieChartDataSet.getLegendLabel( i ) != null ) { ! this.textProcessor.addLabel( iPieChartDataSet.getLegendLabel( i ), this.legendProperties.getChartFont().getFont(), this.chart.getGraphics2D().getFontRenderContext() ); ! //---pair labels with paints to get around ugly piechart vs axischart data structure mess this.labels.add( iPieChartDataSet.getLegendLabel( i ) ); this.paints.add( iPieChartDataSet.getPaint( i ) ); --- 293,302 ---- if( iPieChartDataSet.getLegendLabel( i ) != null ) { ! this.textProcessor.addLabel( iPieChartDataSet.getLegendLabel( i ), ! this.legendProperties.getChartFont().getFont(), ! this.chart.getGraphics2D().getFontRenderContext() ); ! //---pair labels with paints to get around ugly piechart vs axischart data ! // structure mess this.labels.add( iPieChartDataSet.getLegendLabel( i ) ); this.paints.add( iPieChartDataSet.getPaint( i ) ); *************** *** 305,311 **** ! /************************************************************************************************ ! * ! *************************************************************************************************/ public LegendProperties getLegendProperties() { --- 306,312 ---- ! /*************************************************************************************** ! * ! **************************************************************************************/ public LegendProperties getLegendProperties() { *************** *** 314,323 **** ! /************************************************************************************************ ! * Calculates the width and height needed to display the Legend. Use the getWidth() and ! * getHeight() methods to extract this information. ! * * @param iData can pass either the IPieChartDataSet or the IChartDataSeries to this. ! ************************************************************************************************/ public void calculateDrawingValues( IData iData ) { --- 315,324 ---- ! /*************************************************************************************** ! * Calculates the width and height needed to display the Legend. Use the getWidth() and ! * getHeight() methods to extract this information. ! * * @param iData can pass either the IPieChartDataSet or the IChartDataSeries to this. ! **************************************************************************************/ public void calculateDrawingValues( IData iData ) { *************** *** 326,330 **** this.paints = new ArrayList(); - if( iData instanceof IAxisDataSeries ) { --- 327,330 ---- *************** *** 340,344 **** } - //---make the icon proportional to the Font being used. this.iconSide = (float) .50 * this.textProcessor.getTallestLabel(); --- 340,343 ---- *************** *** 349,367 **** for( int i = 0; i < this.shapes.size(); i++ ) { //---get the bounds of the shape ! try ! { ! Double shapeWidthDouble = new Double( ( ( (Shape) this.shapes.get( i ) ).getBounds2D().getWidth() ) ); ! float shapeWidth = shapeWidthDouble.floatValue(); ! this.iconSide = Math.max(this.iconSide, shapeWidth); ! } ! catch (NullPointerException npe) ! { ! // Looks like in 0.74 it was quite acceptable to make shape = null ! // we should probably catch all these and render a "null" shape to the legend ! System.err.println("Warning: legend shape is null"); ! npe.printStackTrace(); ! } ! } } --- 348,377 ---- for( int i = 0; i < this.shapes.size(); i++ ) { + Double shapeWidthDouble; + Shape shape; + //---get the bounds of the shape ! if( this.shapes.get( i ) != null ) ! { ! shape = (Shape) this.shapes.get( i ); ! } ! else ! { ! shape = PointChartProperties.SHAPE_SQUARE; ! } ! ! shapeWidthDouble = new Double( shape.getBounds2D().getWidth() ); ! float shapeWidth = shapeWidthDouble.floatValue(); ! this.iconSide = Math.max( this.iconSide, shapeWidth ); ! ! /* ! * //---get the bounds of the shape try { Double shapeWidthDouble = new Double( ( ( ! * (Shape) this.shapes.get( i ) ).getBounds2D().getWidth() ) ); float shapeWidth = ! * shapeWidthDouble.floatValue(); this.iconSide = Math.max(this.iconSide, ! * shapeWidth); } catch (NullPointerException npe) { // Looks like in 0.74 it was ! * quite acceptable to make shape = null // we should probably catch all these and ! * render a "null" shape to the legend System.err.println("Warning: legend shape ! * is null"); npe.printStackTrace(); } ! */} } *************** *** 370,376 **** ! /******************************************************************************************** ! * ! ********************************************************************************************/ public float getWidth() { --- 380,386 ---- ! /*************************************************************************************** ! * ! **************************************************************************************/ public float getWidth() { *************** *** 379,396 **** ! /******************************************************************************************** ! * ! ********************************************************************************************/ public int getHeight() { ! //why not return a float here? return ((int) Math.ceil( this.height )); } ! /********************************************************************************************** * Determines the dimensions needed for the Legend and creates the image for it. ! * ! **********************************************************************************************/ private void determineWidthAndHeight( int numberOfLabels ) { --- 389,406 ---- ! /*************************************************************************************** ! * ! **************************************************************************************/ public int getHeight() { ! //why not return a float here? return ((int) Math.ceil( this.height )); } ! /*************************************************************************************** * Determines the dimensions needed for the Legend and creates the image for it. ! * ! **************************************************************************************/ private void determineWidthAndHeight( int numberOfLabels ) { *************** *** 399,406 **** height = width; - //---if don't care how many columns or the number of labels is less than num columns specified, all in one row. if( this.legendProperties.getNumColumns() == LegendAreaProperties.COLUMNS_AS_MANY_AS_NEEDED ! || this.legendProperties.getNumColumns() >= numberOfLabels ) { this.numColumns = numberOfLabels; --- 409,415 ---- height = width; //---if don't care how many columns or the number of labels is less than num columns specified, all in one row. if( this.legendProperties.getNumColumns() == LegendAreaProperties.COLUMNS_AS_MANY_AS_NEEDED ! || this.legendProperties.getNumColumns() >= numberOfLabels ) { this.numColumns = numberOfLabels; *************** *** 420,428 **** float actualWidth = legendProperties.getSize().width; ! float widestLabelColumnAndIcon = ! widestLabelAndColumnPadding + ! iconSide + ! legendProperties.getIconPadding() + ! legendProperties.getColumnPadding(); numColumns = (int) (actualWidth / widestLabelColumnAndIcon); --- 429,434 ---- float actualWidth = legendProperties.getSize().width; ! float widestLabelColumnAndIcon = widestLabelAndColumnPadding + iconSide + legendProperties.getIconPadding() ! + legendProperties.getColumnPadding(); numColumns = (int) (actualWidth / widestLabelColumnAndIcon); *************** *** 439,443 **** } - //---account for icons width += (this.iconSide + this.legendProperties.getIconPadding()) * this.numColumns; --- 445,448 ---- *************** *** 447,451 **** //---account for lineStrokes for LINE charts ! if( chartType == ChartType.LINE) { width += this.legendProperties.getIconLineStrokeLength() * 2 * this.numColumns; --- 452,456 ---- //---account for lineStrokes for LINE charts ! if( chartType == ChartType.LINE ) { width += this.legendProperties.getIconLineStrokeLength() * 2 * this.numColumns; *************** *** 460,467 **** ! /********************************************************************************************** * Renders the legend. ! * ! **********************************************************************************************/ public void render() { --- 465,472 ---- ! /*************************************************************************************** * Renders the legend. ! * ! **************************************************************************************/ public void render() { *************** *** 485,489 **** //---dont think we want this so text will be clean but leave commented out. ! //g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF ); //---set the font and text color. --- 490,495 ---- //---dont think we want this so text will be clean but leave commented out. ! //g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, ! // RenderingHints.VALUE_ANTIALIAS_OFF ); //---set the font and text color. *************** *** 495,503 **** rectangle.height = this.iconSide; - float posX = this.x + this.legendProperties.getEdgePadding(); float fontY = rectangle.y + rectangle.height; - //---pre calculate utility values float yIncrement = this.textProcessor.getTallestLabel() + this.legendProperties.getRowPadding(); --- 501,507 ---- *************** *** 506,509 **** --- 510,515 ---- int labelIndex = 0; + Shape shape = (Shape) this.shapes.get( labelIndex ); + //LOOP for( int j = 0; j < this.numRows; j++ ) *************** *** 513,528 **** { rectangle.x = posX; ! //---display icon g2d.setPaint( (Paint) this.paints.get( labelIndex ) ); ! // only Point and Line Charts will have shapes drawn ! ! if( this.shapes.size() > 0 && this.shapes.size() > labelIndex && ! !((Shape)this.shapes.get( labelIndex)).equals(barShape)) ! { - //Shape shape = (Shape)this.shapes.get( labelIndex); - //---get the original transform so can reset it AffineTransform affineTransform = g2d.getTransform(); --- 519,533 ---- { rectangle.x = posX; ! shape = (Shape) this.shapes.get( labelIndex ); ! //---display icon g2d.setPaint( (Paint) this.paints.get( labelIndex ) ); ! if( shape != null ) ! { ! //TODO what about scatter plots? ! //TODO what about NULL shapes on a Line Chart? ! if( this.shapes.size() > 0 && this.shapes.size() > labelIndex && !shape.equals( barShape ) ) { //---get the original transform so can reset it AffineTransform affineTransform = g2d.getTransform(); *************** *** 535,539 **** if( ((Boolean) this.fillPointsFlags.get( labelIndex )).booleanValue() ) { ! g2d.fill( (Shape) this.shapes.get( labelIndex ) ); //---if we are filling the points, see if we should outline the Shape --- 540,544 ---- if( ((Boolean) this.fillPointsFlags.get( labelIndex )).booleanValue() ) { ! g2d.fill( shape ); //---if we are filling the points, see if we should outline the Shape *************** *** 542,546 **** { g2d.setPaint( (Paint) this.pointOutlinePaints.get( labelIndex ) ); ! g2d.draw( (Shape) this.shapes.get( labelIndex ) ); } } --- 547,551 ---- { g2d.setPaint( (Paint) this.pointOutlinePaints.get( labelIndex ) ); ! g2d.draw( shape ); } } *************** *** 549,579 **** { // for Point Charts, only draw shape ! if( chartType == ChartType.POINT) { ! g2d.draw( (Shape) this.shapes.get( labelIndex ) ); ! } else // chartType == ChartType.LINE // for Line Charts, fill the shape { //---get the bounds of the shape ! Rectangle2D shapeBounds = ( (Shape) this.shapes.get( labelIndex ) ).getBounds2D(); ! double XOffset = shapeBounds.getWidth() / 2; ! double YOffset = shapeBounds.getHeight() / 2; ! ! // g2d.setStroke(this.lineChartProperties.getLineStrokes()[ labelIndex]); ! g2d.setStroke((Stroke)this.strokes.get( labelIndex )); ! ! Line2D.Double line = new Line2D.Double(0, YOffset, this.legendProperties.getIconLineStrokeLength(), YOffset); g2d.draw( line ); ! // move posX to account for the lineStroke before the shape. for example, ---o posX += this.legendProperties.getIconLineStrokeLength(); //---translate the Shape to adjust for the IconLineStrokeLength ! g2d.translate( this.legendProperties.getIconLineStrokeLength() - XOffset , 0 ); ! ! line.x1 = XOffset; g2d.draw( line ); - g2d.fill( (Shape) this.shapes.get( labelIndex ) ); --- 554,583 ---- { // for Point Charts, only draw shape ! if( chartType == ChartType.POINT ) { ! g2d.draw( shape ); ! } ! else // chartType == ChartType.LINE // for Line Charts, fill the shape { //---get the bounds of the shape ! Rectangle2D shapeBounds = shape.getBounds2D(); ! double xOffset = shapeBounds.getWidth() / 2; ! double yOffset = shapeBounds.getHeight() / 2; ! g2d.setStroke( (Stroke) this.strokes.get( labelIndex ) ); ! Line2D.Double line = new Line2D.Double( 0, ! yOffset, ! this.legendProperties.getIconLineStrokeLength(), ! yOffset ); g2d.draw( line ); ! // move posX to account for the lineStroke before the shape. for example: ---o posX += this.legendProperties.getIconLineStrokeLength(); //---translate the Shape to adjust for the IconLineStrokeLength ! g2d.translate( this.legendProperties.getIconLineStrokeLength() - xOffset, 0 ); ! line.x1 = xOffset; g2d.draw( line ); g2d.fill( (Shape) this.shapes.get( labelIndex ) ); *************** *** 581,593 **** if( this.legendProperties.getIconBorderStroke() != null && this.pointOutlinePaints.size() != 0 ) { ! if( this.pointOutlinePaints != null ) { g2d.setStroke( this.legendProperties.getIconBorderStroke() ); g2d.setPaint( (Paint) this.pointOutlinePaints.get( labelIndex ) ); ! g2d.draw( (Shape) this.shapes.get( labelIndex ) ); } } ! ! // move posX to account for the lineStroke after the shape. for example, o--- posX += this.legendProperties.getIconLineStrokeLength(); } --- 585,597 ---- if( this.legendProperties.getIconBorderStroke() != null && this.pointOutlinePaints.size() != 0 ) { ! if( this.pointOutlinePaints != null ) ! { g2d.setStroke( this.legendProperties.getIconBorderStroke() ); g2d.setPaint( (Paint) this.pointOutlinePaints.get( labelIndex ) ); ! g2d.draw( shape ); } } ! //---move posX to account for the lineStroke after the shape. for example: o--- posX += this.legendProperties.getIconLineStrokeLength(); } *************** *** 609,612 **** --- 613,617 ---- } } + } *************** *** 616,622 **** g2d.drawString( (String) this.labels.get( labelIndex ), posX, fontY ); - if( this.legendProperties.getNumColumns() == LegendAreaProperties.COLUMNS_AS_MANY_AS_NEEDED ! || this.legendProperties.getNumColumns() >= this.labels.size() ) { //---each column is as wide as it needs to be --- 621,626 ---- g2d.drawString( (String) this.labels.get( labelIndex ), posX, fontY ); if( this.legendProperties.getNumColumns() == LegendAreaProperties.COLUMNS_AS_MANY_AS_NEEDED ! || this.legendProperties.getNumColumns() >= this.labels.size() ) { //---each column is as wide as it needs to be *************** *** 642,650 **** ! /********************************************************************************************* * Enables the testing routines to display the contents of this Object. ! * * @param htmlGenerator ! **********************************************************************************************/ public void toHTML( HTMLGenerator htmlGenerator ) { --- 646,654 ---- ! /*************************************************************************************** * Enables the testing routines to display the contents of this Object. ! * * @param htmlGenerator ! **************************************************************************************/ public void toHTML( HTMLGenerator htmlGenerator ) { *************** *** 662,664 **** } ! } --- 666,668 ---- } ! } \ No newline at end of file |