001: /***********************************************************************************************
002: * Copyright 2002 (C) Nathaniel G. Auvil. All Rights Reserved.
003: *
004: * Redistribution and use of this software and associated documentation ("Software"), with or
005: * without modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain copyright statements and notices.
008: * Redistributions must also contain a copy of this document.
009: *
010: * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
011: * conditions and the following disclaimer in the documentation and/or other materials
012: * provided with the distribution.
013: *
014: * 3. The name "jCharts" or "Nathaniel G. Auvil" must not be used to endorse or promote
015: * products derived from this Software without prior written permission of Nathaniel G.
016: * Auvil. For written permission, please contact nathaniel_auvil@users.sourceforge.net
017: *
018: * 4. Products derived from this Software may not be called "jCharts" nor may "jCharts" appear
019: * in their names without prior written permission of Nathaniel G. Auvil. jCharts is a
020: * registered trademark of Nathaniel G. Auvil.
021: *
022: * 5. Due credit should be given to the jCharts Project (http://jcharts.sourceforge.net/).
023: *
024: * THIS SOFTWARE IS PROVIDED BY Nathaniel G. Auvil AND CONTRIBUTORS ``AS IS'' AND ANY
025: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
026: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
027: * jCharts OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
028: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
029: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
030: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,STRICT LIABILITY, OR TORT
031: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
032: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
033: ************************************************************************************************/package org.krysalis.jcharts.axisChart.axis;
034:
035: import org.krysalis.jcharts.axisChart.AxisChart;
036: import org.krysalis.jcharts.properties.*;
037: import org.krysalis.jcharts.properties.util.ChartFont;
038: import org.krysalis.jcharts.test.HTMLGenerator;
039: import org.krysalis.jcharts.test.HTMLTestable;
040:
041: import java.awt.*;
042: import java.awt.geom.Line2D;
043: import java.lang.reflect.Field;
044:
045: /*************************************************************************************
046: *
047: * @author Nathaniel Auvil, John Thomson
048: * @version $Id: YAxis.java,v 1.5 2004/05/31 16:29:47 nathaniel_auvil Exp $
049: ************************************************************************************/
050: public class YAxis extends Axis implements HTMLTestable {
051:
052: private float lastTickY;
053:
054: /**************************************************************************************************
055: * Constructor
056: *
057: * @param axisChart
058: ***************************************************************************************************/
059: public YAxis(AxisChart axisChart, int numberOfScaleItems) {
060: super (axisChart, numberOfScaleItems);
061: }
062:
063: /************************************************************************************
064: * Need this value as horizontal plots start from the top of the axis and go down
065: *
066: * @return float
067: ************************************************************************************/
068: public float getLastTickY() {
069: return lastTickY;
070: }
071:
072: /*************************************************************************************************
073: * Computes the minimum pixel width required for the Y-Axis.
074: * Includes space, if needed, for: axis title + padding, axis values + tick padding, and tick marks.
075: *
076: **************************************************************************************************/
077: public void computeMinimumWidthNeeded(String yAxisTitle) {
078: AxisTypeProperties axisTypeProperties = super .getAxisChart()
079: .getAxisProperties().getYAxisProperties();
080:
081: float widthNeeded = 0;
082:
083: //---if we are displaying axis scale labels, add width of widest label
084: if (axisTypeProperties.showAxisLabels()) {
085: // Dual Y axis changes integrated CMC 25Aug03
086: //widthNeeded+= super.getAxisLabelsGroup().getWidestLabel();
087: if (axisTypeProperties.getShowRightAxis()) {
088: if (super .getAxisLabelsGroupRight().getWidestLabel() > super
089: .getAxisLabelsGroup().getWidestLabel()) {
090: widthNeeded += super .getAxisLabelsGroupRight()
091: .getWidestLabel();
092: } else {
093: widthNeeded += super .getAxisLabelsGroup()
094: .getWidestLabel();
095: }
096: } else {
097: widthNeeded += super .getAxisLabelsGroup()
098: .getWidestLabel();
099: }
100: }
101:
102: if (axisTypeProperties.getShowTicks() != AxisTypeProperties.TICKS_NONE) {
103: //---add the padding between scale labels and tick marks
104: widthNeeded += axisTypeProperties
105: .getPaddingBetweenLabelsAndTicks();
106:
107: //---add width of tick marks
108: widthNeeded += axisTypeProperties
109: .getAxisTickMarkPixelLength();
110: } else {
111: //---else, if we are not showing any ticks, add padding between labels and axis, if we are displaying labels
112: if (axisTypeProperties.showAxisLabels()) {
113: widthNeeded += axisTypeProperties
114: .getPaddingBetweenAxisAndLabels();
115: }
116: }
117:
118: //---include axis title height if needed. Remember it is vertical for y-axis
119: //if( super.getAxisChart().getAxisProperties().getShowAxisTitle( AxisProperties.Y_AXIS ) )
120: if (yAxisTitle != null) {
121: super .computeAxisTitleDimensions(yAxisTitle,
122: axisTypeProperties.getTitleChartFont());
123: widthNeeded += super .getTitleHeight();
124: widthNeeded += axisTypeProperties
125: .getPaddingBetweenAxisTitleAndLabels();
126: }
127:
128: super .setMinimumWidthNeeded(widthNeeded);
129: }
130:
131: /****************************************************************************************************
132: *
133: * @param axisTitle
134: * @param graphics2D
135: * @param axisTypeProperties
136: ***************************************************************************************************/
137: private void renderAxisTitle(String axisTitle,
138: Graphics2D graphics2D, AxisTypeProperties axisTypeProperties) {
139: if (axisTitle != null) {
140: float titleY; // = super.getAxisChart().getChartProperties().getEdgePadding();
141: float titleX = super .getAxisChart().getXAxis().getOrigin()
142: - super .getMinimumWidthNeeded()
143: + super .getTitleHeight();
144:
145: //---if YAxis title is larger than the YAxis itself, center it on image.
146: if (super .getTitleWidth() > super .getPixelLength()) {
147: //titleY= super.getTitleWidth();
148: titleY = super .getAxisChart().getImageHeight()
149: - ((super .getAxisChart().getImageHeight() - super
150: .getTitleWidth()) / 2);
151: }
152: //---else, center on YAxis.
153: else {
154: titleY = this .getOrigin()
155: - ((super .getPixelLength() - super
156: .getTitleWidth()) / 2);
157: }
158:
159: //TODO this should use a TextTag
160: graphics2D.setFont(axisTypeProperties
161: .getAxisTitleChartFont().getFont().deriveFont(
162: ChartFont.VERTICAL_ROTATION));
163: graphics2D.setPaint(axisTypeProperties
164: .getAxisTitleChartFont().getPaint());
165: graphics2D.drawString(axisTitle, titleX, titleY);
166: }
167: }
168:
169: /*********************************************************************************************
170: * Renders the YAxis on the passes Graphics2D object
171: *
172: * @param graphics2D
173: * @param axisProperties
174: * @param yAxisTitle
175: **********************************************************************************************/
176: public void render(Graphics2D graphics2D,
177: AxisProperties axisProperties, String yAxisTitle) {
178: AxisTypeProperties axisTypeProperties = axisProperties
179: .getYAxisProperties();
180:
181: //---AXIS TITLE
182: this .renderAxisTitle(yAxisTitle, graphics2D, axisProperties
183: .getYAxisProperties());
184:
185: Line2D.Float line2D;
186: float stringY = 0;
187:
188: if (axisTypeProperties instanceof DataAxisProperties) {
189: //---start at the axis
190: line2D = new Line2D.Float(0.0f, super .getOrigin(), 0.0f,
191: super .getOrigin());
192:
193: if (axisTypeProperties.showAxisLabels()) {
194: stringY = super .getOrigin()
195: + (super .getAxisLabelsGroup().getTallestLabel() / 4);
196: }
197: } else {
198: //--start at half a axis item width
199: float y = super .getOrigin()
200: - (super .getScalePixelWidth() / 2);
201: line2D = new Line2D.Float(0.0f, y, 0.0f, y);
202:
203: if (axisTypeProperties.showAxisLabels()) {
204: stringY = y
205: + (super .getAxisLabelsGroup().getTallestLabel() / 4);
206:
207: //---horizontal plots start at top of axis and go down
208: super .getAxisLabelsGroup().reverse();
209: }
210: }
211:
212: float tickX1 = super .getAxisChart().getXAxis().getOrigin()
213: - axisTypeProperties.getAxisTickMarkPixelLength();
214: float tickX2 = super .getAxisChart().getXAxis().getOrigin();
215: float gridLineX1 = super .getAxisChart().getXAxis().getOrigin() + 1;
216: float gridLineX2 = super .getAxisChart().getXAxis().getOrigin()
217: + super .getAxisChart().getXAxis().getPixelLength();
218:
219: float stringX = super .getAxisChart().getXAxis().getOrigin()
220: - axisTypeProperties.getAxisTickMarkPixelLength();
221:
222: if (axisTypeProperties.showAxisLabels()) {
223: stringX -= axisTypeProperties
224: .getPaddingBetweenLabelsAndTicks();
225: }
226:
227: for (int i = 0; i < super .getNumberOfScaleItems(); i++) {
228: //---GRID LINES
229: if (axisTypeProperties.getShowGridLines() != AxisTypeProperties.GRID_LINES_NONE) {
230: //---we do not want to draw a grid line over the axis as data axis first value is on the axis
231: if (i > 0
232: || (i == 0 && !(axisTypeProperties instanceof DataAxisProperties))) {
233: line2D.x1 = gridLineX1;
234: line2D.x2 = gridLineX2;
235:
236: //TODO what is this doing???? How could i ever equal the size?
237:
238: if (i < super .getAxisLabelsGroup().size()
239: || (i == super .getAxisLabelsGroup().size() && !axisTypeProperties
240: .getShowEndBorder()))
241:
242: // if( i == super.getNumberOfScaleItems() - 1 && !axisTypeProperties.getShowEndBorder() )
243: {
244: axisTypeProperties.getGridLineChartStroke()
245: .draw(graphics2D, line2D);
246: } else {
247: //---draw top border with the same ChartStroke as the X-Axis
248: axisProperties.getXAxisProperties()
249: .getAxisStroke().draw(graphics2D,
250: line2D);
251: }
252: }
253: }
254:
255: //---TICK MARKS
256: if (axisTypeProperties.getShowTicks() != AxisTypeProperties.TICKS_NONE) {
257: line2D.x1 = tickX1;
258: line2D.x2 = tickX2;
259: axisTypeProperties.getTickChartStroke().draw(
260: graphics2D, line2D);
261: }
262:
263: //---need this value as horizontal plots start from the top of the axis and go down
264: //---must set this no matter if no ticks are present as horizontal plots start their rendering based on this screen coordinate.
265: this .lastTickY = line2D.y1;
266:
267: line2D.y1 -= super .getScalePixelWidth();
268: line2D.y2 = line2D.y1;
269:
270: //---AXIS LABEL
271: if (axisTypeProperties.showAxisLabels()) {
272: super .getAxisLabelsGroup().render(
273: i,
274: graphics2D,
275: stringX
276: - super .getAxisLabelsGroup()
277: .getTextTag(i).getWidth(),
278: stringY);
279: //graphics2D.setPaint( axisProperties.getScaleFontColor() );
280: //graphics2D.drawString( this.formattedLabels[ i ], stringX - this.labelWidths[ i ], stringY );
281: }
282:
283: stringY -= super .getScalePixelWidth();
284: }
285:
286: //---AXIS----------------------------------------------------------------------
287: line2D.x1 = super .getAxisChart().getXAxis().getOrigin();
288: line2D.x2 = line2D.x1;
289: line2D.y1 = super .getOrigin() - super .getPixelLength();
290: line2D.y2 = super .getOrigin();
291: axisTypeProperties.getAxisStroke().draw(graphics2D, line2D);
292:
293: //---TOP BORDER----------------------------------------------------------------
294: if (axisTypeProperties.getShowEndBorder()) {
295: line2D.x1 = super .getAxisChart().getXAxis().getOrigin();
296: line2D.x2 = super .getAxisChart().getXAxis().getOrigin()
297: + super .getAxisChart().getXAxis().getPixelLength();
298: line2D.y1 = super .getOrigin() - super .getPixelLength();
299: line2D.y2 = line2D.y1;
300: axisProperties.getXAxisProperties().getAxisStroke().draw(
301: graphics2D, line2D);
302: }
303:
304: //---ZERO LINE-----------------------------------------------------------------
305: if (axisTypeProperties instanceof DataAxisProperties) {
306: DataAxisProperties dataAxisProperties = (DataAxisProperties) axisTypeProperties;
307:
308: if (dataAxisProperties.showZeroLine()
309: && super .getScaleCalculator().getMinValue() < 0.0d
310: && super .getScaleCalculator().getMaxValue() > 0.0d) {
311: line2D.y1 = super .getZeroLineCoordinate();
312: line2D.y2 = line2D.y1;
313: line2D.x1 = super .getAxisChart().getXAxis().getOrigin();
314: line2D.x2 = super .getAxisChart().getXAxis().getOrigin()
315: + super .getAxisChart().getXAxis()
316: .getPixelLength();
317: dataAxisProperties.getZeroLineChartStroke().draw(
318: graphics2D, line2D);
319: }
320: }
321:
322: // Dual Y axis changes integrated CMC 25Aug03
323: //---if AXIS at the right----------------------------------------------------------------------
324:
325: if (axisTypeProperties.getShowRightAxis()) {
326:
327: line2D.x1 = super .getAxisChart().getXAxis().getOrigin()
328: + super .getAxisChart().getXAxis().getPixelLength();
329: line2D.x2 = line2D.x1;
330: line2D.y1 = super .getOrigin() - super .getPixelLength() - 10;
331: line2D.y2 = super .getOrigin();
332: axisTypeProperties.getAxisStroke().draw(graphics2D, line2D);
333:
334: float tickRightX1 = super .getAxisChart().getXAxis()
335: .getOrigin()
336: + super .getAxisChart().getXAxis().getPixelLength();
337: float tickRightX2 = tickRightX1
338: + axisTypeProperties.getAxisTickMarkPixelLength();
339: line2D.y1 = super .getOrigin();
340: line2D.y2 = line2D.y1;
341:
342: stringY = super .getOrigin()
343: + (super .getAxisLabelsGroupRight()
344: .getTallestLabel() / 4);
345: stringX = super .getAxisChart().getXAxis().getOrigin()
346: + axisTypeProperties.getAxisTickMarkPixelLength()
347: + super .getAxisChart().getXAxis().getPixelLength();
348:
349: stringX += axisTypeProperties
350: .getPaddingBetweenLabelsAndTicks();
351:
352: for (int i = 0; i < super .getNumberOfScaleItems(); i++) {
353: //---TICK MARKS at the right
354: if (axisTypeProperties.getShowTicks() != AxisTypeProperties.TICKS_NONE) {
355: line2D.x1 = tickRightX1;
356: line2D.x2 = tickRightX2;
357: axisTypeProperties.getTickChartStroke().draw(
358: graphics2D, line2D);
359: }
360:
361: line2D.y1 -= super .getScalePixelWidth();
362: line2D.y2 = line2D.y1;
363:
364: //---AXIS LABEL at the right
365: if (axisTypeProperties.showAxisLabels()) {
366:
367: // Font and Paint set in TextTagGroup object in 1.0 it seems CMC 25Aug03
368: //graphics2D.setFont( axisTypeProperties.getScaleChartFontRight().getFont());
369: //graphics2D.setPaint( axisTypeProperties.getScaleChartFontRight().getPaint() );
370: super .getAxisLabelsGroupRight().render(i,
371: graphics2D, stringX, stringY);
372: }
373: stringY -= super .getScalePixelWidth();
374: }
375: }
376: }
377:
378: /*************************************************************************************************
379: * Takes a value and determines the screen coordinate it should be drawn at. THe only difference
380: * between this and the x-axis is we subtract to the origin versus subtract from it.
381:
382: *
383: * @param origin
384: * @param value
385: * @param axisMinValue the minimum value on the axis
386: * @return float the screen pixel coordinate
387: **************************************************************************************************/
388: public float computeAxisCoordinate(float origin, double value,
389: double axisMinValue) {
390: double returnValue = origin - (value - axisMinValue)
391: * this .getOneUnitPixelSize();
392: return (float) returnValue;
393: }
394:
395: /*********************************************************************************************
396: * Enables the testing routines to display the contents of this Object.
397: *
398: * @param htmlGenerator
399: **********************************************************************************************/
400: //todo is this method needed?
401: public void toHTML(HTMLGenerator htmlGenerator) {
402: htmlGenerator.propertiesTableStart(this .getClass().getName());
403:
404: super .toHTML(htmlGenerator);
405:
406: Field[] fields = this .getClass().getDeclaredFields();
407: for (int i = 0; i < fields.length; i++) {
408: try {
409: htmlGenerator.addField(fields[i].getName(), fields[i]
410: .get(this ));
411: } catch (IllegalAccessException illegalAccessException) {
412: illegalAccessException.printStackTrace();
413: }
414: }
415:
416: htmlGenerator.propertiesTableEnd();
417: }
418:
419: }
|