/*******************************************************************************
* Copyright (c) 2008-2011 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 tick marks 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();
for (int i = 0; i < tickLabelPositions.size() + 1; i++) {
int x;
if (i < tickLabelPositions.size()) {
x = (int) (tickLabelPositions.get(i).intValue() - step / 2d);
} else {
x = (int) (tickLabelPositions.get(i - 1).intValue() + step / 2d);
}
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);
}
}
} 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();
for (int i = 0; i < tickLabelPositions.size() + 1; i++) {
int x = 0;
int y;
if (i < tickLabelPositions.size()) {
y = (int) (tickLabelPositions.get(i).intValue() - step / 2d);
} else {
y = (int) (tickLabelPositions.get(i - 1).intValue() + step / 2d);
}
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);
}
}
} 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);
}
}
}