/*******************************************************************************
* Copyright (c) 2013 Luigi Sgro. All rights reserved. This
* program and the accompanying materials are made available under the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Luigi Sgro - initial API and implementation
******************************************************************************/
package com.quantcomponents.chart.series;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Display;
import com.quantcomponents.chart.HorizontalLabelContainer;
import com.quantcomponents.chart.IAxis;
import com.quantcomponents.chart.IChartMetrics;
import com.quantcomponents.chart.IDrawable;
import com.quantcomponents.chart.IMark;
/**
* Horizontal chart ruler for double charts indexed by {@link java.util.Date}
*
*/
public class TimeRulerX implements IDrawable<Date, Double> {
private static final Color DEFAULT_COLOR = Display.getDefault().getSystemColor(SWT.COLOR_YELLOW);
private static final Color DEFAULT_GRID_COLOR = Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY);
private static final Color DEFAULT_EMPH_GRID_COLOR = Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
private static final int DEFAULT_GRID_STYLE = SWT.LINE_SOLID;
private static final int DEFAULT_PRIMARY_MARK_LENGTH = 5;
private static final int DEFAULT_SECONDARY_MARK_LENGTH = 8;
private final DateFormat hourMinuteFormat = new SimpleDateFormat("HH:mm");
private final DateFormat dateFormat = new SimpleDateFormat("dd");
private final DateFormat dayMonthFormat = new SimpleDateFormat("dd/MM");
private final DateFormat monthYearFormat = new SimpleDateFormat("MMM yyyy");
private final DateFormat yearFormat = new SimpleDateFormat("yyyy");
private Color color = DEFAULT_COLOR;
private Color gridColor = DEFAULT_GRID_COLOR;
private Color emphGridColor = DEFAULT_EMPH_GRID_COLOR;
private int gridStyle = DEFAULT_GRID_STYLE;
private volatile int primaryMarkLength = DEFAULT_PRIMARY_MARK_LENGTH;
private volatile int secondaryMarkLength = DEFAULT_SECONDARY_MARK_LENGTH;
public void setTimeZone(TimeZone timeZone) {
hourMinuteFormat.setTimeZone(timeZone);
dateFormat.setTimeZone(timeZone);
dayMonthFormat.setTimeZone(timeZone);
monthYearFormat.setTimeZone(timeZone);
yearFormat.setTimeZone(timeZone);
}
public void setPrimaryMarkLength(int primaryMarkLength) {
this.primaryMarkLength = primaryMarkLength;
}
public void setSecondaryMarkLength(int secondaryMarkLength) {
this.secondaryMarkLength = secondaryMarkLength;
}
@Override
public void draw(IChartMetrics<Date, Double> metrics, GC gc) {
IAxis<Date> xAxis = metrics.xAxis();
int yPixelHigh = metrics.yAxis().getPixelHigh();
int yPixelLow = metrics.yAxis().getPixelLow();
int xPixelLow = xAxis.getPixelLow();
int xPixelHigh = xAxis.getPixelHigh();
int avgCharWidth = gc.getFontMetrics().getAverageCharWidth();
HorizontalLabelContainer<Date> xLabelContainer = new HorizontalLabelContainer<Date>();
addMarks(xLabelContainer, xAxis, xAxis.baseMarks(), avgCharWidth);
addMarks(xLabelContainer, xAxis, xAxis.parentMarks(), avgCharWidth);
for (HorizontalLabelContainer.LabelInfo<Date> labelInfo : xLabelContainer) {
gc.setForeground(color);
gc.drawString(labelInfo.label, labelInfo.leftPixel, yPixelHigh);
int markLength;
if (labelInfo.markScale.equals(xAxis.baseMarkScale())) {
markLength = primaryMarkLength;
gc.setForeground(gridColor);
} else {
markLength = secondaryMarkLength;
gc.setForeground(emphGridColor);
}
gc.setLineStyle(gridStyle);
gc.drawLine(labelInfo.centerPixel, yPixelHigh, labelInfo.centerPixel, yPixelLow);
gc.setLineStyle(SWT.LINE_SOLID);
gc.drawLine(labelInfo.centerPixel, yPixelHigh, labelInfo.centerPixel, yPixelHigh - markLength);
}
gc.setLineStyle(gridStyle);
gc.drawLine(xPixelLow, yPixelHigh, xPixelHigh, yPixelHigh);
}
private void addMarks(HorizontalLabelContainer<Date> container, IAxis<Date> axis, List<IMark<Date>> markList, int avgCharWidth) {
for (IMark<Date> mark : markList) {
Date date = mark.getValue();
String label = generateLabel(date, ((TimeScale) mark.getScale()).getCalendarUnit(), true);
int x = axis.calculatePixel(date);
int leftPixel = x - label.length() * avgCharWidth / 2;
int rightPixel = leftPixel + label.length() * avgCharWidth;
container.addLabel(date, label, leftPixel, x, rightPixel, mark.getScale());
}
}
private String generateLabel(Date date, int uom, boolean parentScale) {
String label;
switch (uom) {
case Calendar.MINUTE:
case Calendar.HOUR_OF_DAY:
label = hourMinuteFormat.format(date);
break;
case Calendar.DATE:
if (parentScale) {
label = dayMonthFormat.format(date);
} else {
label = dateFormat.format(date);
}
break;
case Calendar.WEEK_OF_YEAR:
label = dayMonthFormat.format(date);
break;
case Calendar.MONTH:
label = monthYearFormat.format(date);
break;
case Calendar.YEAR:
label = yearFormat.format(date);
break;
default:
label = date.toString();
}
return label;
}
}