/*******************************************************************************
* Copyright (c) 2008-2009 SWTChart project. All rights reserved.
*
* This code is distributed under the terms of the Eclipse Public License v1.0
* which is available at http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.swtchart.internal.axis;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.swtchart.Chart;
import org.swtchart.internal.ChartLayoutData;
import org.swtchart.internal.Util;
/**
* Axis tick labels.
*/
public class AxisTickLabels implements PaintListener
{
/** the chart */
private Chart chart;
/** the axis */
private Axis axis;
/** the foreground color */
private Color foreground;
/** the width hint of tick labels area */
private int widthHint;
/** the height hint of tick labels area */
private int heightHint;
/** the bounds of tick labels area */
private Rectangle bounds;
/** the array of tick label vales */
private ArrayList<Double> tickLabelValues;
/** the array of tick label */
private ArrayList<String> tickLabels;
/** the array of tick label position in pixels */
private ArrayList<Integer> tickLabelPositions;
/** the array of visibility state of tick label */
private ArrayList<Boolean> tickVisibilities;
/** the maximum length of tick labels */
private int tickLabelMaxLength;
/** the format for tick labels */
private Format format;
/** the default foreground */
private static final int DEFAULT_FOREGROUND = SWT.COLOR_BLUE;
/** the default font */
private static final Font DEFAULT_FONT = Display.getDefault ().getSystemFont ();
/** the default label format */
private static final String DEFAULT_DECIMAL_FORMAT = "#.###########";
/** the possible tick steps */
private Map<Integer, Integer[]> possibleTickSteps;
/** the time unit for tick step */
private int timeUnit;
/** the font */
private Font font;
/**
* Constructor.
*
* @param chart
* the chart
* @param axis
* the axis
*/
protected AxisTickLabels ( Chart chart, Axis axis )
{
this.chart = chart;
this.axis = axis;
tickLabelValues = new ArrayList<Double> ();
tickLabels = new ArrayList<String> ();
tickLabelPositions = new ArrayList<Integer> ();
tickVisibilities = new ArrayList<Boolean> ();
initializePossibleTickSteps ();
font = DEFAULT_FONT;
foreground = Display.getDefault ().getSystemColor ( DEFAULT_FOREGROUND );
chart.addPaintListener ( this );
}
/**
* Initialized the possible tick steps.
*/
private void initializePossibleTickSteps ()
{
final Integer[] milliseconds = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 999 };
final Integer[] seconds = { 1, 2, 5, 10, 15, 20, 30, 59 };
final Integer[] minutes = { 1, 2, 3, 5, 10, 15, 20, 30, 59 };
final Integer[] hours = { 1, 2, 3, 4, 6, 12, 22 };
final Integer[] dates = { 1, 7, 14, 28 };
final Integer[] months = { 1, 2, 3, 4, 6, 11 };
final Integer[] years = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 };
possibleTickSteps = new HashMap<Integer, Integer[]> ();
possibleTickSteps.put ( Calendar.MILLISECOND, milliseconds );
possibleTickSteps.put ( Calendar.SECOND, seconds );
possibleTickSteps.put ( Calendar.MINUTE, minutes );
possibleTickSteps.put ( Calendar.HOUR_OF_DAY, hours );
possibleTickSteps.put ( Calendar.DATE, dates );
possibleTickSteps.put ( Calendar.MONTH, months );
possibleTickSteps.put ( Calendar.YEAR, years );
}
/**
* Sets the foreground color.
*
* @param color
* the foreground color
*/
public void setForeground ( Color color )
{
if ( color == null )
{
foreground = Display.getDefault ().getSystemColor ( DEFAULT_FOREGROUND );
}
else
{
foreground = color;
}
}
/**
* Gets the foreground color.
*
* @return the foreground color
*/
protected Color getForeground ()
{
if ( foreground.isDisposed () )
{
foreground = Display.getDefault ().getSystemColor ( DEFAULT_FOREGROUND );
}
return foreground;
}
/**
* Updates the tick labels.
*
* @param length
* the axis length
*/
protected void update ( int length )
{
tickLabelValues.clear ();
tickLabels.clear ();
tickLabelPositions.clear ();
if ( axis.isValidCategoryAxis () )
{
updateTickLabelForCategoryAxis ( length );
}
else if ( axis.isLogScaleEnabled () )
{
updateTickLabelForLogScale ( length );
}
else if ( axis.isDateEnabled () )
{
updateTickLabelForDateAxis ( length );
}
else
{
updateTickLabelForLinearScale ( length );
}
updateTickVisibility ();
updateTickLabelMaxLength ();
}
/**
* Updates tick label for date axis.
*
* @param length
* the length of axis
*/
private void updateTickLabelForDateAxis ( int length )
{
double min = axis.getRange ().lower;
double max = axis.getRange ().upper;
double gridStepHint = Math.abs ( max - min ) / length * axis.getTick ().getTickMarkStepHint ();
timeUnit = getTimeUnit ( gridStepHint );
if ( timeUnit == Calendar.MILLISECOND || timeUnit == Calendar.SECOND || timeUnit == Calendar.MINUTE || timeUnit == Calendar.HOUR_OF_DAY || timeUnit == Calendar.DATE )
{
Integer[] steps = possibleTickSteps.get ( timeUnit );
for ( int i = 0; i < steps.length - 1; i++ )
{
if ( gridStepHint < ( getPeriodInMillis ( timeUnit, steps[i] ) + getPeriodInMillis ( timeUnit, steps[i + 1] ) ) / 2d )
{
BigDecimal gridStep = new BigDecimal ( Long
.valueOf ( getPeriodInMillis ( timeUnit, steps[i] ) )
.toString () );
updateTickLabelForLinearScale ( length, gridStep );
break;
}
}
}
else if ( timeUnit == Calendar.MONTH || timeUnit == Calendar.YEAR )
{
updateTickLabelForMonthOrYear ( length, gridStepHint, timeUnit );
}
}
/**
* Updates the tick label for month or year. The month and year are handled
* differently from other units of time, since 1 month and 1 year can be
* different depending on which time to start counting.
*
* @param length
* the length of axis
* @param gridStepHint
* the grid step hint
* @param tickStepUnit
* the tick step unit of time
*/
private void updateTickLabelForMonthOrYear ( int length, double gridStepHint, int tickStepUnit )
{
double min = axis.getRange ().lower;
double max = axis.getRange ().upper;
// get initial position
Calendar cal = Calendar.getInstance ();
cal.setTime ( new Date ( (long)min ) );
int month = cal.get ( Calendar.MONTH );
int year = cal.get ( Calendar.YEAR );
if ( tickStepUnit == Calendar.MONTH )
{
if ( month == Calendar.DECEMBER )
{
year++;
month = Calendar.JANUARY;
}
else
{
month++;
}
}
else if ( tickStepUnit == Calendar.YEAR )
{
month = Calendar.JANUARY;
year++;
}
// get tick step
Integer[] steps = possibleTickSteps.get ( tickStepUnit );
int step = steps[steps.length - 1];
for ( int i = 0; i < steps.length - 1; i++ )
{
if ( gridStepHint < ( getPeriodInMillis ( tickStepUnit, steps[i] ) + getPeriodInMillis ( tickStepUnit, steps[i + 1] ) ) / 2d )
{
step = steps[i];
break;
}
}
// set tick labels
cal.clear ();
cal.set ( year, month, 1 );
while ( cal.getTimeInMillis () < max )
{
tickLabelValues.add ( Double.valueOf ( cal.getTimeInMillis () ) );
tickLabels.add ( format ( cal.getTimeInMillis () ) );
int tickLabelPosition = (int) ( ( cal.getTimeInMillis () - min ) / ( max - min ) * length );
tickLabelPositions.add ( tickLabelPosition );
if ( tickStepUnit == Calendar.MONTH )
{
month += step;
if ( month + step > Calendar.DECEMBER )
{
year++;
month -= Calendar.DECEMBER + 1;
}
}
else if ( tickStepUnit == Calendar.YEAR )
{
year += step;
}
cal.clear ();
cal.set ( year, month, 1 );
}
}
/**
* Updates tick label for category axis.
*
* @param length
* the length of axis
*/
private void updateTickLabelForCategoryAxis ( int length )
{
String[] series = axis.getCategorySeries ();
if ( series == null )
{
return;
}
int min = (int)axis.getRange ().lower;
int max = (int)axis.getRange ().upper;
int sizeOfTickLabels = ( series.length < max - min + 1 ) ? series.length : max - min + 1;
int initialIndex = ( min < 0 ) ? 0 : min;
for ( int i = 0; i < sizeOfTickLabels; i++ )
{
tickLabels.add ( series[i + initialIndex] );
int tickLabelPosition = (int) ( length * ( i + 0.5 ) / sizeOfTickLabels );
tickLabelPositions.add ( tickLabelPosition );
}
}
/**
* Updates tick label for log scale.
*
* @param length
* the length of axis
*/
private void updateTickLabelForLogScale ( int length )
{
double min = axis.getRange ().lower;
double max = axis.getRange ().upper;
int digitMin = (int)Math.ceil ( Math.log10 ( min ) );
int digitMax = (int)Math.ceil ( Math.log10 ( max ) );
final BigDecimal MIN = new BigDecimal ( new Double ( min ).toString () );
BigDecimal tickStep = pow ( 10, digitMin - 1 );
BigDecimal firstPosition;
if ( MIN.remainder ( tickStep ).doubleValue () <= 0 )
{
firstPosition = MIN.subtract ( MIN.remainder ( tickStep ) );
}
else
{
firstPosition = MIN.subtract ( MIN.remainder ( tickStep ) ).add ( tickStep );
}
for ( int i = digitMin; i <= digitMax; i++ )
{
for ( BigDecimal j = firstPosition; j.doubleValue () <= pow ( 10, i ).doubleValue (); j = j.add ( tickStep ) )
{
if ( j.doubleValue () > max )
{
break;
}
if ( axis.isDateEnabled () )
{
Date date = new Date ( (long)j.doubleValue () );
tickLabels.add ( format ( date ) );
}
else
{
tickLabels.add ( format ( j.doubleValue () ) );
}
tickLabelValues.add ( j.doubleValue () );
int tickLabelPosition = (int) ( ( Math.log10 ( j.doubleValue () ) - Math.log10 ( min ) ) / ( Math
.log10 ( max ) - Math.log10 ( min ) ) * length );
tickLabelPositions.add ( tickLabelPosition );
}
tickStep = tickStep.multiply ( pow ( 10, 1 ) );
firstPosition = tickStep.add ( pow ( 10, i ) );
}
}
/**
* Updates tick label for normal scale.
*
* @param length
* axis length (>0)
*/
private void updateTickLabelForLinearScale ( int length )
{
double min = axis.getRange ().lower;
double max = axis.getRange ().upper;
updateTickLabelForLinearScale ( length, getGridStep ( length, min, max ) );
}
/**
* Updates tick label for normal scale.
*
* @param length
* axis length (>0)
* @param tickStep
* the tick step
*/
private void updateTickLabelForLinearScale ( int length, BigDecimal tickStep )
{
double min = axis.getRange ().lower;
double max = axis.getRange ().upper;
final BigDecimal MIN = new BigDecimal ( new Double ( min ).toString () );
BigDecimal firstPosition;
/* if (min % tickStep <= 0) */
if ( MIN.remainder ( tickStep ).doubleValue () <= 0 )
{
/* firstPosition = min - min % tickStep */
firstPosition = MIN.subtract ( MIN.remainder ( tickStep ) );
}
else
{
/* firstPosition = min - min % tickStep + tickStep */
firstPosition = MIN.subtract ( MIN.remainder ( tickStep ) ).add ( tickStep );
}
// the unit time starts from 1:00
if ( axis.isDateEnabled () )
{
BigDecimal zeroOclock = firstPosition.subtract ( new BigDecimal ( new Double ( 3600000 ).toString () ) );
if ( MIN.compareTo ( zeroOclock ) == -1 )
{
firstPosition = zeroOclock;
}
}
for ( BigDecimal b = firstPosition; b.doubleValue () <= max; b = b.add ( tickStep ) )
{
if ( axis.isDateEnabled () )
{
Date date = new Date ( (long)b.doubleValue () );
tickLabels.add ( format ( date ) );
}
else
{
tickLabels.add ( format ( b.doubleValue () ) );
}
tickLabelValues.add ( b.doubleValue () );
int tickLabelPosition = (int) ( ( b.doubleValue () - min ) / ( max - min ) * length );
tickLabelPositions.add ( tickLabelPosition );
}
}
/**
* Updates the visibility of tick labels.
*/
private void updateTickVisibility ()
{
// initialize the array of tick label visibility state
tickVisibilities.clear ();
for ( int i = 0; i < tickLabelPositions.size (); i++ )
{
tickVisibilities.add ( Boolean.TRUE );
}
if ( tickLabelPositions.size () == 0 )
{
return;
}
// set the tick label visibility
int previousPosition = 0;
for ( int i = 0; i < tickLabelPositions.size (); i++ )
{
// check if there is enough space to draw tick label
boolean hasSpaceToDraw = true;
if ( i != 0 )
{
hasSpaceToDraw = hasSpaceToDraw ( previousPosition, tickLabelPositions.get ( i ), tickLabels.get ( i ) );
}
// check if the tick label value is major
boolean isMajorTick = true;
if ( !axis.isValidCategoryAxis () && axis.isLogScaleEnabled () )
{
isMajorTick = isMajorTick ( tickLabelValues.get ( i ) );
}
// check if the same tick label is repeated
String currentLabel = tickLabels.get ( i );
try
{
double value = Double.parseDouble ( currentLabel );
if ( value != tickLabelValues.get ( i ) )
{
isMajorTick = false;
}
}
catch ( NumberFormatException e )
{
// label is not decimal value but string
}
if ( hasSpaceToDraw && isMajorTick )
{
previousPosition = tickLabelPositions.get ( i );
}
else
{
tickVisibilities.set ( i, Boolean.FALSE );
}
}
}
/**
* Gets the tick step unit.
*
* @param gridStepHint
* the grid step hint
* @return the tick step unit.
*/
private int getTimeUnit ( double gridStepHint )
{
final Integer[] units = { Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.DATE, Calendar.MONTH, Calendar.YEAR };
for ( Integer unit : units )
{
Integer[] steps = possibleTickSteps.get ( unit );
if ( gridStepHint < ( getPeriodInMillis ( unit, steps[steps.length - 2] ) + getPeriodInMillis ( unit, steps[steps.length - 1] ) ) / 2d )
{
return unit;
}
}
return Calendar.YEAR;
}
/**
* Gets the period in milliseconds of given unit of date and amount. The
* period is calculated based on UTC of January 1, 1970.
*
* @param unit
* the unit of time like <tt>Calendar.YEAR<tt>.
* @param amount
* the amount of period.
* @return the period in milliseconds
*/
private long getPeriodInMillis ( int unit, int amount )
{
Calendar cal = Calendar.getInstance ();
cal.setTimeInMillis ( 0 );
cal.roll ( unit, amount );
return cal.getTimeInMillis ();
}
/**
* Formats the given object.
*
* @param obj
* the object
* @return the formatted string
*/
private String format ( Object obj )
{
if ( format == null )
{
if ( axis.isDateEnabled () )
{
String dateFormat = "yyyyy.MMMMM.dd";
if ( timeUnit == Calendar.MILLISECOND )
{
dateFormat = "HH:mm:ss.SSS";
}
else if ( timeUnit == Calendar.SECOND )
{
dateFormat = "HH:mm:ss";
}
else if ( timeUnit == Calendar.MINUTE )
{
dateFormat = "HH:mm";
}
else if ( timeUnit == Calendar.HOUR_OF_DAY )
{
dateFormat = "dd HH:mm";
}
else if ( timeUnit == Calendar.DATE )
{
dateFormat = "MMMMM d";
}
else if ( timeUnit == Calendar.MONTH )
{
dateFormat = "yyyy MMMMM";
}
else if ( timeUnit == Calendar.YEAR )
{
dateFormat = "yyyy";
}
return new SimpleDateFormat ( dateFormat ).format ( obj );
}
return new DecimalFormat ( DEFAULT_DECIMAL_FORMAT ).format ( obj );
}
return format.format ( obj );
}
/**
* Checks if the tick label is major (...,0.01,0.1,1,10,100,...).
*
* @param tickValue
* the tick label value
* @return true if the tick label is major
*/
private boolean isMajorTick ( double tickValue )
{
if ( !axis.isLogScaleEnabled () )
{
return true;
}
if ( Math.log10 ( tickValue ) % 1 == 0 )
{
return true;
}
return false;
}
/**
* Returns the state indicating if there is a space to draw tick label.
*
* @param previousPosition
* the previously drawn tick label position.
* @param tickLabelPosition
* the tick label position.
* @param tickLabel
* the tick label text
* @return true if there is a space to draw tick label
*/
private boolean hasSpaceToDraw ( int previousPosition, int tickLabelPosition, String tickLabel )
{
Point p = Util.getExtentInGC ( axis.getTick ().getFont (), tickLabel );
int interval = tickLabelPosition - previousPosition;
int textLength = axis.isHorizontalAxis () ? p.x : p.y;
return interval > textLength;
}
/**
* Gets max length of tick label.
*/
private void updateTickLabelMaxLength ()
{
int maxLength = 0;
for ( int i = 0; i < tickLabels.size (); i++ )
{
if ( tickVisibilities.size () > i && tickVisibilities.get ( i ) == true )
{
Point p = Util.getExtentInGC ( axis.getTick ().getFont (), tickLabels.get ( i ) );
if ( p.x > maxLength )
{
maxLength = p.x;
}
}
}
tickLabelMaxLength = maxLength;
}
/**
* Calculates the value of the first argument raised to the power of the
* second argument.
*
* @param base
* the base
* @param expornent
* the exponent
* @return the value <tt>a<sup>b</sup></tt> in <tt>BigDecimal</tt>
*/
private BigDecimal pow ( double base, int expornent )
{
BigDecimal value;
if ( expornent > 0 )
{
value = new BigDecimal ( new Double ( base ).toString () ).pow ( expornent );
}
else
{
value = BigDecimal.ONE.divide ( new BigDecimal ( new Double ( base ).toString () ).pow ( -expornent ) );
}
return value;
}
/**
* Gets the grid step.
*
* @param lengthInPixels
* axis length in pixels
* @param min
* minimum value
* @param max
* maximum value
* @return rounded value.
*/
private BigDecimal getGridStep ( int lengthInPixels, double min, double max )
{
if ( lengthInPixels <= 0 )
{
throw new IllegalArgumentException ( "lengthInPixels must be positive value." );
}
if ( min >= max )
{
throw new IllegalArgumentException ( "min must be less than max." );
}
double length = Math.abs ( max - min );
double gridStepHint = length / lengthInPixels * axis.getTick ().getTickMarkStepHint ();
// gridStepHint --> mantissa * 10 ** exponent
// e.g. 724.1 --> 7.241 * 10 ** 2
double mantissa = gridStepHint;
int exponent = 0;
if ( mantissa < 1 )
{
while ( mantissa < 1 )
{
mantissa *= 10.0;
exponent--;
}
}
else
{
while ( mantissa >= 10 )
{
mantissa /= 10.0;
exponent++;
}
}
// calculate the grid step with hint.
BigDecimal gridStep;
if ( mantissa > 7.5 )
{
// gridStep = 10.0 * 10 ** exponent
gridStep = BigDecimal.TEN.multiply ( pow ( 10, exponent ) );
}
else if ( mantissa > 3.5 )
{
// gridStep = 5.0 * 10 ** exponent
gridStep = new BigDecimal ( new Double ( 5 ).toString () ).multiply ( pow ( 10, exponent ) );
}
else if ( mantissa > 1.5 )
{
// gridStep = 2.0 * 10 ** exponent
gridStep = new BigDecimal ( new Double ( 2 ).toString () ).multiply ( pow ( 10, exponent ) );
}
else
{
// gridStep = 1.0 * 10 ** exponent
gridStep = pow ( 10, exponent );
}
return gridStep;
}
/**
* Gets the tick label positions.
*
* @return the tick label positions
*/
public ArrayList<Integer> getTickLabelPositions ()
{
return tickLabelPositions;
}
/**
* Sets the font.
*
* @param font
* the font
*/
protected void setFont ( Font font )
{
if ( font == null )
{
this.font = DEFAULT_FONT;
}
else
{
this.font = font;
}
}
/**
* Gets the font.
*
* @return the font
*/
protected Font getFont ()
{
if ( font.isDisposed () )
{
font = DEFAULT_FONT;
}
return font;
}
/**
* Gets the layout data.
*
* @return the layout data
*/
public ChartLayoutData getLayoutData ()
{
return new ChartLayoutData ( widthHint, heightHint );
}
/**
* Sets the bounds on chart panel.
*
* @param x
* the x coordinate
* @param y
* the y coordinate
* @param width
* the width
* @param height
* the height
*/
public void setBounds ( int x, int y, int width, int height )
{
bounds = new Rectangle ( x, y, width, height );
}
/**
* Gets the bounds on chart panel.
*
* @return the bounds on chart panel
*/
protected Rectangle getBounds ()
{
return bounds;
}
/**
* Disposes the resources.
*/
protected void dispose ()
{
if ( !chart.isDisposed () )
{
chart.removePaintListener ( this );
}
}
/**
* Updates title layout.
*/
protected void updateLayoutData ()
{
widthHint = SWT.DEFAULT;
heightHint = SWT.DEFAULT;
if ( !axis.getTick ().isVisible () )
{
widthHint = 0;
heightHint = 0;
}
else
{
if ( axis.isHorizontalAxis () )
{
heightHint = Axis.MARGIN + Util.getExtentInGC ( getFont (), "dummy" ).y;
}
else
{
widthHint = tickLabelMaxLength + Axis.MARGIN;
}
}
}
/*
* @see PaintListener#paintControl(PaintEvent)
*/
public void paintControl ( PaintEvent e )
{
if ( !axis.getTick ().isVisible () )
{
return;
}
e.gc.setBackground ( chart.getBackground () );
e.gc.setForeground ( getForeground () );
if ( axis.isHorizontalAxis () )
{
drawXTick ( e.gc );
}
else
{
drawYTick ( e.gc );
}
}
/**
* Draw the X tick.
*
* @param gc
* the graphics context
*/
private void drawXTick ( GC gc )
{
int offset = axis.getTick ().getAxisTickMarks ().getBounds ().x;
// draw tick labels
gc.setFont ( axis.getTick ().getFont () );
for ( int i = 0; i < tickLabelPositions.size (); i++ )
{
if ( axis.isValidCategoryAxis () || tickVisibilities.get ( i ) == true )
{
String text = tickLabels.get ( i );
int fontWidth = gc.textExtent ( text ).x;
int x = (int) ( tickLabelPositions.get ( i ) - fontWidth / 2.0 + offset );
gc.drawText ( text, bounds.x + x, bounds.y );
}
}
}
/**
* Draw the Y tick.
*
* @param gc
* the graphics context
*/
private void drawYTick ( GC gc )
{
int margin = Axis.MARGIN + AxisTickMarks.TICK_LENGTH;
// draw tick labels
gc.setFont ( axis.getTick ().getFont () );
int figureHeight = gc.textExtent ( "dummy" ).y;
for ( int i = 0; i < tickLabelPositions.size (); i++ )
{
if ( tickVisibilities.size () == 0 || tickLabels.size () == 0 )
{
break;
}
if ( tickVisibilities.get ( i ) == true )
{
String text = tickLabels.get ( i );
int x = 0;
if ( tickLabels.get ( 0 ).startsWith ( "-" ) && !text.startsWith ( "-" ) )
{
x += gc.textExtent ( "-" ).x;
}
int y = (int) ( bounds.height - 1 - tickLabelPositions.get ( i ) - figureHeight / 2.0 - margin );
gc.drawText ( text, bounds.x + x, bounds.y + y );
}
}
}
/**
* Sets the format for axis tick label. <tt>DecimalFormat</tt> and
* <tt>DateFormat</tt> should be used for <tt>double[]</tt> series and
* <tt>Data[]</tt> series respectively.
* <p>
* If <tt>null</tt> is set, default format will be used.
*
* @param format
* the format
*/
protected void setFormat ( Format format )
{
this.format = format;
}
/**
* Gets the format for axis tick label.
*
* @return the format
*/
protected Format getFormat ()
{
return format;
}
}