/*******************************************************************************
* 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.util.ArrayList;
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.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.swtchart.Chart;
import org.swtchart.IAxis.Position;
import org.swtchart.internal.ChartLayoutData;
/**
* Axis tick marks.
*/
public class AxisTickMarks implements PaintListener
{
/** the chart */
private Chart chart;
/** the axis */
private Axis axis;
/** the foreground color */
private Color foreground;
/** the width hint of tick marks area */
private int widthHint;
/** the height hint of tick marks area */
private int heightHint;
/** the bounds of tick marks area */
private Rectangle bounds;
/** the line width */
protected static final int LINE_WIDTH = 1;
/** the tick length */
public static final int TICK_LENGTH = 5;
/** the default foreground */
private static final int DEFAULT_FOREGROUND = SWT.COLOR_BLUE;
/**
* Constructor.
*
* @param chart
* the chart
* @param axis
* the axis
*/
public AxisTickMarks ( Chart chart, Axis axis )
{
this.chart = chart;
this.axis = axis;
foreground = Display.getDefault ().getSystemColor ( DEFAULT_FOREGROUND );
chart.addPaintListener ( this );
}
/**
* 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;
}
/**
* Gets the associated axis.
*
* @return the axis
*/
public Axis getAxis ()
{
return axis;
}
/**
* 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 + TICK_LENGTH;
}
else
{
widthHint = TICK_LENGTH + Axis.MARGIN;
}
}
}
/**
* 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 );
}
}
/*
* @see PaintListener#paintControl(PaintEvent)
*/
public void paintControl ( PaintEvent e )
{
ArrayList<Integer> tickLabelPositions = axis.getTick ().getAxisTickLabels ().getTickLabelPositions ();
e.gc.setBackground ( chart.getBackground () );
e.gc.setForeground ( getForeground () );
Rectangle oldClipping = e.gc.getClipping ();
e.gc.setClipping ( bounds );
if ( axis.isHorizontalAxis () )
{
drawXTickMarks ( e.gc, tickLabelPositions, axis.getPosition () );
}
else
{
drawYTickMarks ( e.gc, tickLabelPositions, axis.getPosition () );
}
e.gc.setClipping ( oldClipping );
}
/**
* Draw the X tick marks.
*
* @param tickLabelPositions
* the tick label positions
* @param position
* the axis position
* @param gc
* the graphics context
*/
private void drawXTickMarks ( GC gc, ArrayList<Integer> tickLabelPositions, Position position )
{
// draw tick marks
gc.setLineStyle ( SWT.LINE_SOLID );
if ( axis.isValidCategoryAxis () )
{
if ( tickLabelPositions.size () > 1 )
{
int step = tickLabelPositions.get ( 1 ).intValue () - tickLabelPositions.get ( 0 ).intValue ();
int x = (int) ( tickLabelPositions.get ( 0 ).intValue () - step / 2d );
for ( int i = 0; i < tickLabelPositions.size () + 1; i++ )
{
int y = 0;
if ( position == Position.Secondary )
{
y = bounds.height - 1 - LINE_WIDTH - TICK_LENGTH;
}
gc.drawLine ( bounds.x + x, bounds.y + y, bounds.x + x, bounds.y + y + TICK_LENGTH );
x += step;
}
}
}
else
{
for ( int i = 0; i < tickLabelPositions.size (); i++ )
{
int x = tickLabelPositions.get ( i );
int y = 0;
if ( position == Position.Secondary )
{
y = bounds.height - 1 - LINE_WIDTH - TICK_LENGTH;
}
gc.drawLine ( bounds.x + x, bounds.y + y, bounds.x + x, bounds.y + y + TICK_LENGTH );
}
}
// draw axis line
if ( position == Position.Primary )
{
gc.drawLine ( bounds.x, bounds.y, bounds.x + bounds.width - 1, bounds.y );
}
else
{
gc
.drawLine ( bounds.x, bounds.y + bounds.height - 1, bounds.x + bounds.width - 1, bounds.y + bounds.height - 1 );
}
}
/**
* Draw the Y tick marks.
*
* @param tickLabelPositions
* the tick label positions
* @param position
* the axis position
* @param gc
* the graphics context
*/
private void drawYTickMarks ( GC gc, ArrayList<Integer> tickLabelPositions, Position position )
{
// draw tick marks
gc.setLineStyle ( SWT.LINE_SOLID );
if ( axis.isValidCategoryAxis () )
{
if ( tickLabelPositions.size () > 1 )
{
int step = tickLabelPositions.get ( 1 ).intValue () - tickLabelPositions.get ( 0 ).intValue ();
int y = (int) ( tickLabelPositions.get ( 0 ).intValue () - step / 2d );
for ( int i = 0; i < tickLabelPositions.size () + 1; i++ )
{
int x = 0;
if ( position == Position.Primary )
{
x = bounds.width - 1 - LINE_WIDTH - TICK_LENGTH;
}
else
{
x = LINE_WIDTH;
}
gc.drawLine ( bounds.x + x, bounds.y + y, bounds.x + x + TICK_LENGTH, bounds.y + y );
y += step;
}
}
}
else
{
int y = 0;
for ( int i = 0; i < tickLabelPositions.size (); i++ )
{
int x = 0;
if ( position == Position.Primary )
{
x = bounds.width - 1 - LINE_WIDTH - TICK_LENGTH;
}
else
{
x = LINE_WIDTH;
}
y = bounds.height - 1 - tickLabelPositions.get ( i );
gc.drawLine ( bounds.x + x, bounds.y + y, bounds.x + x + TICK_LENGTH, bounds.y + y );
}
}
// draw axis line
if ( position == Position.Primary )
{
gc
.drawLine ( bounds.x + bounds.width - 1, bounds.y, bounds.x + bounds.width - 1, bounds.y + bounds.height - 1 );
}
else
{
gc.drawLine ( bounds.x, bounds.y, bounds.x, bounds.y + bounds.height - 1 );
}
}
}