/*********************************************************************************************** * Copyright 2002 (C) Nathaniel G. Auvil. All Rights Reserved. * * Redistribution and use of this software and associated documentation ("Software"), with or * without modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain copyright statements and notices. * Redistributions must also contain a copy of this document. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. The name "jCharts" or "Nathaniel G. Auvil" must not be used to endorse or promote * products derived from this Software without prior written permission of Nathaniel G. * Auvil. For written permission, please contact nathaniel_auvil@users.sourceforge.net * * 4. Products derived from this Software may not be called "jCharts" nor may "jCharts" appear * in their names without prior written permission of Nathaniel G. Auvil. jCharts is a * registered trademark of Nathaniel G. Auvil. * * 5. Due credit should be given to the jCharts Project (http://jcharts.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY Nathaniel G. Auvil AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * jCharts OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE ************************************************************************************************/ package org.krysalis.jcharts.axisChart.axis; import org.krysalis.jcharts.axisChart.AxisChart; import org.krysalis.jcharts.properties.*; import org.krysalis.jcharts.properties.util.ChartFont; import org.krysalis.jcharts.test.HTMLGenerator; import org.krysalis.jcharts.test.HTMLTestable; import com.google.code.appengine.awt.*; import com.google.code.appengine.awt.geom.Line2D; import java.lang.reflect.Field; /************************************************************************************* * * @author Nathaniel Auvil, John Thomson * @version $Id: YAxis.java,v 1.5 2004/05/31 16:29:47 nathaniel_auvil Exp $ ************************************************************************************/ public class YAxis extends Axis implements HTMLTestable { private float lastTickY; /************************************************************************************************** * Constructor * * @param axisChart ***************************************************************************************************/ public YAxis( AxisChart axisChart, int numberOfScaleItems ) { super( axisChart, numberOfScaleItems ); } /************************************************************************************ * Need this value as horizontal plots start from the top of the axis and go down * * @return float ************************************************************************************/ public float getLastTickY() { return lastTickY; } /************************************************************************************************* * Computes the minimum pixel width required for the Y-Axis. * Includes space, if needed, for: axis title + padding, axis values + tick padding, and tick marks. * **************************************************************************************************/ public void computeMinimumWidthNeeded( String yAxisTitle ) { AxisTypeProperties axisTypeProperties= super.getAxisChart().getAxisProperties().getYAxisProperties(); float widthNeeded = 0; //---if we are displaying axis scale labels, add width of widest label if( axisTypeProperties.showAxisLabels() ) { // Dual Y axis changes integrated CMC 25Aug03 //widthNeeded+= super.getAxisLabelsGroup().getWidestLabel(); if ( axisTypeProperties.getShowRightAxis() ) { if ( super.getAxisLabelsGroupRight().getWidestLabel()>super.getAxisLabelsGroup().getWidestLabel()) { widthNeeded+= super.getAxisLabelsGroupRight().getWidestLabel(); } else { widthNeeded+= super.getAxisLabelsGroup().getWidestLabel(); } } else { widthNeeded+= super.getAxisLabelsGroup().getWidestLabel(); } } if( axisTypeProperties.getShowTicks() != AxisTypeProperties.TICKS_NONE ) { //---add the padding between scale labels and tick marks widthNeeded += axisTypeProperties.getPaddingBetweenLabelsAndTicks(); //---add width of tick marks widthNeeded += axisTypeProperties.getAxisTickMarkPixelLength(); } else { //---else, if we are not showing any ticks, add padding between labels and axis, if we are displaying labels if( axisTypeProperties.showAxisLabels() ) { widthNeeded += axisTypeProperties.getPaddingBetweenAxisAndLabels(); } } //---include axis title height if needed. Remember it is vertical for y-axis //if( super.getAxisChart().getAxisProperties().getShowAxisTitle( AxisProperties.Y_AXIS ) ) if( yAxisTitle != null ) { super.computeAxisTitleDimensions( yAxisTitle, axisTypeProperties.getTitleChartFont() ); widthNeeded += super.getTitleHeight(); widthNeeded += axisTypeProperties.getPaddingBetweenAxisTitleAndLabels(); } super.setMinimumWidthNeeded( widthNeeded ); } /**************************************************************************************************** * * @param axisTitle * @param graphics2D * @param axisTypeProperties ***************************************************************************************************/ private void renderAxisTitle( String axisTitle, Graphics2D graphics2D, AxisTypeProperties axisTypeProperties ) { if( axisTitle != null ) { float titleY; // = super.getAxisChart().getChartProperties().getEdgePadding(); float titleX = super.getAxisChart().getXAxis().getOrigin() - super.getMinimumWidthNeeded() + super.getTitleHeight(); //---if YAxis title is larger than the YAxis itself, center it on image. if( super.getTitleWidth() > super.getPixelLength() ) { //titleY= super.getTitleWidth(); titleY= super.getAxisChart().getImageHeight() - ( ( super.getAxisChart().getImageHeight() - super.getTitleWidth() ) / 2 ); } //---else, center on YAxis. else { titleY = this.getOrigin() - ( ( super.getPixelLength() - super.getTitleWidth() ) / 2 ); } //TODO this should use a TextTag graphics2D.setFont( axisTypeProperties.getAxisTitleChartFont().getFont().deriveFont( ChartFont.VERTICAL_ROTATION ) ); graphics2D.setPaint( axisTypeProperties.getAxisTitleChartFont().getPaint() ); graphics2D.drawString( axisTitle, titleX, titleY ); } } /********************************************************************************************* * Renders the YAxis on the passes Graphics2D object * * @param graphics2D * @param axisProperties * @param yAxisTitle **********************************************************************************************/ public void render( Graphics2D graphics2D, AxisProperties axisProperties, String yAxisTitle ) { AxisTypeProperties axisTypeProperties = axisProperties.getYAxisProperties(); //---AXIS TITLE this.renderAxisTitle( yAxisTitle, graphics2D, axisProperties.getYAxisProperties() ); Line2D.Float line2D; float stringY= 0; if( axisTypeProperties instanceof DataAxisProperties ) { //---start at the axis line2D = new Line2D.Float( 0.0f, super.getOrigin(), 0.0f, super.getOrigin() ); if( axisTypeProperties.showAxisLabels() ) { stringY = super.getOrigin() + ( super.getAxisLabelsGroup().getTallestLabel() / 4 ); } } else { //--start at half a axis item width float y = super.getOrigin() - ( super.getScalePixelWidth() / 2 ); line2D = new Line2D.Float( 0.0f, y, 0.0f, y ); if( axisTypeProperties.showAxisLabels() ) { stringY = y + ( super.getAxisLabelsGroup().getTallestLabel() / 4 ); //---horizontal plots start at top of axis and go down super.getAxisLabelsGroup().reverse(); } } float tickX1 = super.getAxisChart().getXAxis().getOrigin() - axisTypeProperties.getAxisTickMarkPixelLength(); float tickX2 = super.getAxisChart().getXAxis().getOrigin(); float gridLineX1 = super.getAxisChart().getXAxis().getOrigin() + 1; float gridLineX2 = super.getAxisChart().getXAxis().getOrigin() + super.getAxisChart().getXAxis().getPixelLength(); float stringX = super.getAxisChart().getXAxis().getOrigin() - axisTypeProperties.getAxisTickMarkPixelLength(); if( axisTypeProperties.showAxisLabels() ) { stringX-= axisTypeProperties.getPaddingBetweenLabelsAndTicks(); } for( int i = 0; i < super.getNumberOfScaleItems(); i++ ) { //---GRID LINES if( axisTypeProperties.getShowGridLines() != AxisTypeProperties.GRID_LINES_NONE ) { //---we do not want to draw a grid line over the axis as data axis first value is on the axis if( i > 0 || ( i == 0 && !( axisTypeProperties instanceof DataAxisProperties ) ) ) { line2D.x1 = gridLineX1; line2D.x2 = gridLineX2; //TODO what is this doing???? How could i ever equal the size? if( i < super.getAxisLabelsGroup().size() || ( i == super.getAxisLabelsGroup().size() && !axisTypeProperties.getShowEndBorder() ) ) // if( i == super.getNumberOfScaleItems() - 1 && !axisTypeProperties.getShowEndBorder() ) { axisTypeProperties.getGridLineChartStroke().draw( graphics2D, line2D ); } else { //---draw top border with the same ChartStroke as the X-Axis axisProperties.getXAxisProperties().getAxisStroke().draw( graphics2D, line2D ); } } } //---TICK MARKS if( axisTypeProperties.getShowTicks() != AxisTypeProperties.TICKS_NONE ) { line2D.x1 = tickX1; line2D.x2 = tickX2; axisTypeProperties.getTickChartStroke().draw( graphics2D, line2D ); } //---need this value as horizontal plots start from the top of the axis and go down //---must set this no matter if no ticks are present as horizontal plots start their rendering based on this screen coordinate. this.lastTickY= line2D.y1; line2D.y1 -= super.getScalePixelWidth(); line2D.y2 = line2D.y1; //---AXIS LABEL if( axisTypeProperties.showAxisLabels() ) { super.getAxisLabelsGroup().render( i, graphics2D, stringX - super.getAxisLabelsGroup().getTextTag( i ).getWidth(), stringY ); //graphics2D.setPaint( axisProperties.getScaleFontColor() ); //graphics2D.drawString( this.formattedLabels[ i ], stringX - this.labelWidths[ i ], stringY ); } stringY -= super.getScalePixelWidth(); } //---AXIS---------------------------------------------------------------------- line2D.x1 = super.getAxisChart().getXAxis().getOrigin(); line2D.x2 = line2D.x1; line2D.y1 = super.getOrigin() - super.getPixelLength(); line2D.y2 = super.getOrigin(); axisTypeProperties.getAxisStroke().draw( graphics2D, line2D ); //---TOP BORDER---------------------------------------------------------------- if( axisTypeProperties.getShowEndBorder() ) { line2D.x1 = super.getAxisChart().getXAxis().getOrigin(); line2D.x2 = super.getAxisChart().getXAxis().getOrigin() + super.getAxisChart().getXAxis().getPixelLength(); line2D.y1 = super.getOrigin() - super.getPixelLength(); line2D.y2 = line2D.y1; axisProperties.getXAxisProperties().getAxisStroke().draw( graphics2D, line2D ); } //---ZERO LINE----------------------------------------------------------------- if( axisTypeProperties instanceof DataAxisProperties ) { DataAxisProperties dataAxisProperties = ( DataAxisProperties ) axisTypeProperties; if( dataAxisProperties.showZeroLine() && super.getScaleCalculator().getMinValue() < 0.0d && super.getScaleCalculator().getMaxValue() > 0.0d ) { line2D.y1 = super.getZeroLineCoordinate(); line2D.y2 = line2D.y1; line2D.x1 = super.getAxisChart().getXAxis().getOrigin(); line2D.x2 = super.getAxisChart().getXAxis().getOrigin() + super.getAxisChart().getXAxis().getPixelLength(); dataAxisProperties.getZeroLineChartStroke().draw( graphics2D, line2D ); } } // Dual Y axis changes integrated CMC 25Aug03 //---if AXIS at the right---------------------------------------------------------------------- if (axisTypeProperties.getShowRightAxis()) { line2D.x1 = super.getAxisChart().getXAxis().getOrigin() + super.getAxisChart().getXAxis().getPixelLength(); line2D.x2 = line2D.x1; line2D.y1 = super.getOrigin() - super.getPixelLength() - 10 ; line2D.y2 = super.getOrigin(); axisTypeProperties.getAxisStroke().draw( graphics2D, line2D ); float tickRightX1 = super.getAxisChart().getXAxis().getOrigin() + super.getAxisChart().getXAxis().getPixelLength(); float tickRightX2 = tickRightX1 + axisTypeProperties.getAxisTickMarkPixelLength(); line2D.y1 = super.getOrigin(); line2D.y2 = line2D.y1; stringY = super.getOrigin() + ( super.getAxisLabelsGroupRight().getTallestLabel() / 4 ); stringX = super.getAxisChart().getXAxis().getOrigin() + axisTypeProperties.getAxisTickMarkPixelLength() + super.getAxisChart().getXAxis().getPixelLength(); stringX+= axisTypeProperties.getPaddingBetweenLabelsAndTicks(); for( int i = 0; i < super.getNumberOfScaleItems(); i++ ) { //---TICK MARKS at the right if( axisTypeProperties.getShowTicks() != AxisTypeProperties.TICKS_NONE ) { line2D.x1 = tickRightX1; line2D.x2 = tickRightX2; axisTypeProperties.getTickChartStroke().draw( graphics2D, line2D ); } line2D.y1 -= super.getScalePixelWidth(); line2D.y2 = line2D.y1; //---AXIS LABEL at the right if( axisTypeProperties.showAxisLabels() ) { // Font and Paint set in TextTagGroup object in 1.0 it seems CMC 25Aug03 //graphics2D.setFont( axisTypeProperties.getScaleChartFontRight().getFont()); //graphics2D.setPaint( axisTypeProperties.getScaleChartFontRight().getPaint() ); super.getAxisLabelsGroupRight().render( i, graphics2D, stringX , stringY ); } stringY -= super.getScalePixelWidth(); } } } /************************************************************************************************* * Takes a value and determines the screen coordinate it should be drawn at. THe only difference * between this and the x-axis is we subtract to the origin versus subtract from it. * * @param origin * @param value * @param axisMinValue the minimum value on the axis * @return float the screen pixel coordinate **************************************************************************************************/ public float computeAxisCoordinate( float origin, double value, double axisMinValue ) { double returnValue = origin - ( value - axisMinValue ) * this.getOneUnitPixelSize(); return ( float ) returnValue; } /********************************************************************************************* * Enables the testing routines to display the contents of this Object. * * @param htmlGenerator **********************************************************************************************/ //todo is this method needed? public void toHTML( HTMLGenerator htmlGenerator ) { htmlGenerator.propertiesTableStart( this.getClass().getName() ); super.toHTML( htmlGenerator ); Field[] fields = this.getClass().getDeclaredFields(); for( int i = 0; i < fields.length; i++ ) { try { htmlGenerator.addField( fields[ i ].getName(), fields[ i ].get( this ) ); } catch( IllegalAccessException illegalAccessException ) { illegalAccessException.printStackTrace(); } } htmlGenerator.propertiesTableEnd(); } }