/*******************************************************************************
* 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 java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import org.eclipse.swt.SWT;
import org.swtchart.Chart;
import org.swtchart.IAxis;
import org.swtchart.IAxisSet;
import org.swtchart.ISeries;
import org.swtchart.IAxis.Direction;
import org.swtchart.internal.ChartLayout;
import org.swtchart.internal.ChartLayoutData;
import org.swtchart.internal.Legend;
import org.swtchart.internal.Title;
import org.swtchart.internal.series.SeriesSet;
/**
* An axis container. By default, axis set has X Axis and Y axis with axis id 0.
*/
public class AxisSet implements IAxisSet {
/** the set of X axes */
private HashMap<Integer, Axis> xAxisMap;
/** the set of Y axes */
private HashMap<Integer, Axis> yAxisMap;
/** the chart */
private Chart chart;
/**
* Constructor.
*
* @param chart
* the chart
*/
public AxisSet(Chart chart) {
this.chart = chart;
xAxisMap = new HashMap<Integer, Axis>();
yAxisMap = new HashMap<Integer, Axis>();
// add default axes
Axis xAxis = new Axis(0, Direction.X, chart);
Axis yAxis = new Axis(0, Direction.Y, chart);
xAxisMap.put(0, xAxis);
yAxisMap.put(0, yAxis);
}
/**
* Gets the axis map for given direction.
*
* @param direction
* the direction
* @return the axis map
*/
private HashMap<Integer, Axis> getAxisMap(Direction direction) {
if (direction == Direction.X) {
return xAxisMap;
}
return yAxisMap;
}
/*
* @see IAxisSet#createXAxis()
*/
public int createXAxis() {
return createAxis(Direction.X);
}
/*
* @see IAxisSet#createYAxis()
*/
public int createYAxis() {
return createAxis(Direction.Y);
}
/**
* Creates the axis for given direction.
*
* @param direction
* the direction of axis
* @return the created axis id
*/
private int createAxis(Direction direction) {
int id = getUniqueId(direction);
Axis axis = new Axis(id, direction, chart);
getAxisMap(direction).put(id, axis);
chart.updateLayout();
SeriesSet series = (SeriesSet) chart.getSeriesSet();
if (series != null) {
series.compressAllSeries();
}
return id;
}
/**
* Gets a unique axis id.
*
* @param direction
* the axis direction
* @return a unique axis id
*/
private int getUniqueId(Direction direction) {
Set<Integer> keySet = getAxisMap(direction).keySet();
int i = 0;
while (keySet.contains(i)) {
i++;
}
return i;
}
/*
* @see IAxisSet#getXAxis(int)
*/
public IAxis getXAxis(int id) {
return getAxis(id, Direction.X);
}
/*
* @see IAxisSet#getYAxis(int)
*/
public IAxis getYAxis(int id) {
return getAxis(id, Direction.Y);
}
/**
* Gets the axis with axis id for given direction.
*
* @param id
* the axis id
* @param direction
* the direction
* @return the axis
*/
private IAxis getAxis(int id, Direction direction) {
return getAxisMap(direction).get(id);
}
/*
* @see IAxisSet#getXAxes()
*/
public IAxis[] getXAxes() {
return xAxisMap.values().toArray(new IAxis[0]);
}
/*
* @see IAxisSet#getYAxes()
*/
public IAxis[] getYAxes() {
return yAxisMap.values().toArray(new IAxis[0]);
}
/*
* @see IAxisSet#getAxes()
*/
public IAxis[] getAxes() {
Collection<Axis> axes = new ArrayList<Axis>();
axes.addAll(xAxisMap.values());
axes.addAll(yAxisMap.values());
return axes.toArray(new Axis[0]);
}
/*
* @see IAxisSet#getXAxisIds()
*/
public int[] getXAxisIds() {
return getAxisIds(Direction.X);
}
/*
* @see IAxisSet#getYAxisIds()
*/
public int[] getYAxisIds() {
return getAxisIds(Direction.Y);
}
/**
* Gets the axis ids for given direction.
*
* @param direction
* the direction
* @return the axis ids
*/
private int[] getAxisIds(Direction direction) {
Integer[] array = getAxisMap(direction).keySet()
.toArray(new Integer[0]);
int[] ids = new int[array.length];
for (int i = 0; i < ids.length; i++) {
ids[i] = array[i];
}
Arrays.sort(ids);
return ids;
}
/*
* @see IAxisSet#deleteXAxis(int)
*/
public void deleteXAxis(int id) {
deleteAxis(id, Direction.X);
}
/*
* @see IAxisSet#deleteYAxis(int)
*/
public void deleteYAxis(int id) {
deleteAxis(id, Direction.Y);
}
/**
* Deletes the axis with the axis id for given direction.
*
* @param id
* the axis id
* @param direction
* the direction
*/
private void deleteAxis(int id, Direction direction) {
if (id == 0) {
SWT.error(SWT.ERROR_CANNOT_BE_ZERO);
}
if (getAxisMap(direction).get(id) == null) {
throw new IllegalArgumentException("Given axis id doesn't exist");
}
((Axis) getAxis(id, direction)).dispose();
getAxisMap(direction).remove(id);
for (ISeries series : chart.getSeriesSet().getSeries()) {
if (direction == Direction.X) {
if (series.getXAxisId() == id) {
series.setXAxisId(0);
}
} else {
if (series.getYAxisId() == id) {
series.setYAxisId(0);
}
}
}
chart.updateLayout();
}
/*
* @see IAxisSet#adjustRange()
*/
public void adjustRange() {
for (IAxis axis : getAxes()) {
((Axis) axis).adjustRange(false);
}
chart.updateLayout();
}
/*
* @see IAxisSet#zoomIn()
*/
public void zoomIn() {
for (IAxis axis : getAxes()) {
axis.zoomIn();
}
}
/*
* @see IAxisSet#zoomOut()
*/
public void zoomOut() {
for (IAxis axis : getAxes()) {
axis.zoomOut();
}
}
/**
* Updates the layout data.
*/
public void updateLayoutData() {
IAxis[] horizontalAxes;
IAxis[] verticalAxes;
if (chart.getOrientation() == SWT.HORIZONTAL) {
horizontalAxes = getXAxes();
verticalAxes = getYAxes();
} else {
horizontalAxes = getYAxes();
verticalAxes = getXAxes();
}
updateAxesLayoutData(horizontalAxes);
updateVerticalTick(horizontalAxes, verticalAxes);
updateAxesLayoutData(verticalAxes);
updateHorizontalTick(horizontalAxes, verticalAxes);
}
/**
* Updates the layout data
*
* @param axes
* The axes
*/
private void updateAxesLayoutData(IAxis[] axes) {
for (IAxis axis : axes) {
((Axis) axis).updateLayoutData();
}
}
/**
* Updates the horizontal tick.
*
* @param horizontalAxes
* the horizontal axes
* @param verticalAxes
* the vertical axes
*/
private void updateHorizontalTick(IAxis[] horizontalAxes,
IAxis[] verticalAxes) {
int legendPosition = ((Legend) chart.getLegend()).getPosition();
int legendWidth = ((ChartLayoutData) ((Legend) chart.getLegend())
.getLayoutData()).widthHint;
int axesWidth = 0;
for (IAxis axis : verticalAxes) {
axesWidth += ((ChartLayoutData) ((Title) ((Axis) axis).getTitle())
.getLayoutData()).widthHint
+ ((Axis) axis).getTick().getAxisTickLabels()
.getLayoutData().widthHint
+ ((Axis) axis).getTick().getAxisTickMarks()
.getLayoutData().widthHint;
}
int axisWidth = chart.getSize().x
- axesWidth
- ChartLayout.MARGIN
* 2
- (legendPosition == SWT.LEFT || legendPosition == SWT.RIGHT ? legendWidth
+ (legendWidth == 0 ? 0 : ChartLayout.PADDING)
: 0);
for (IAxis axis : horizontalAxes) {
((Axis) axis).getTick().updateTick(axisWidth);
}
}
/**
* Updates the vertical tick.
*
* @param horizontalAxes
* the horizontal axes
* @param verticalAxes
* the vertical axes
*/
private void updateVerticalTick(IAxis[] horizontalAxes, IAxis[] verticalAxes) {
int legendPosition = ((Legend) chart.getLegend()).getPosition();
int legendHeight = ((ChartLayoutData) ((Legend) chart.getLegend())
.getLayoutData()).heightHint;
int titleHeight = ((ChartLayoutData) ((Title) chart.getTitle())
.getLayoutData()).heightHint;
int axesHeight = 0;
for (IAxis axis : horizontalAxes) {
axesHeight += ((ChartLayoutData) ((Title) ((Axis) axis).getTitle())
.getLayoutData()).heightHint
+ ((Axis) axis).getTick().getAxisTickLabels()
.getLayoutData().heightHint
+ ((Axis) axis).getTick().getAxisTickMarks()
.getLayoutData().heightHint;
}
int axisHeight = chart.getSize().y
- titleHeight
- axesHeight
- ChartLayout.MARGIN
* 2
- (titleHeight == 0 ? 0 : ChartLayout.PADDING)
- ((legendPosition == SWT.TOP || legendPosition == SWT.BOTTOM) ? legendHeight
+ (legendHeight == 0 ? 0 : ChartLayout.PADDING)
: 0);
for (IAxis axis : verticalAxes) {
((Axis) axis).getTick().updateTick(axisHeight);
}
}
/**
* Refreshes the cache.
*/
public void refresh() {
for (IAxis axis : getAxes()) {
((Axis) axis).refresh();
}
}
/**
* Disposes the resources.
*/
public void dispose() {
for (IAxis axis : getAxes()) {
((Axis) axis).dispose();
}
}
}