/*******************************************************************************
* Copyright (c) 2010, 2017 Oak Ridge National Laboratory and others.
* 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
******************************************************************************/
package org.eclipse.nebula.visualization.xygraph.linearscale;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.nebula.visualization.xygraph.linearscale.AbstractScale.LabelSide;
import org.eclipse.nebula.visualization.xygraph.util.SWTConstants;
/**
* Linear scale tick marks.
*
* @author Xihui Chen
* @author Baha El-Kassaby/Peter Chang - Diamond light Source contributions
*/
public class LinearScaleTickMarks extends Figure {
/** the scale */
private LinearScale scale;
/** the line width */
public static final int LINE_WIDTH = 1;
/** the tick length */
public static final int MAJOR_TICK_LENGTH = 6;
/** the tick length */
public static final int MINOR_TICK_LENGTH = 3;
private int minorGridStepInPixel;
private int minorTicksNumber;
/**
* Constructor.
*
* @param scale
* the scale
*/
public LinearScaleTickMarks(LinearScale scale) {
this.scale = scale;
setForegroundColor(scale.getForegroundColor());
}
/**
* Gets the associated scale.
*
* @return the scale
*/
public LinearScale getAxis() {
return scale;
}
protected void paintClientArea(Graphics graphics) {
graphics.translate(bounds.x, bounds.y);
ITicksProvider ticks = scale.getTicksProvider();
int width = getSize().width;
int height = getSize().height;
try {
graphics.pushState();
graphics.setAlpha(100);
if (scale.isHorizontal()) {
drawXTickMarks(graphics, ticks.getPositions(), scale.getTickLabelSide(), width, height);
} else {
drawYTickMarks(graphics, ticks.getPositions(), scale.getTickLabelSide(), width, height);
}
} finally {
graphics.popState();
}
}
/**
* update the parameters for minor ticks
*/
private void updateMinorTickParas() {
if (scale.isDateEnabled()) {
// when range < 10 min, minor ticks is 5
if (Math.abs(scale.getRange().getUpper() - scale.getRange().getLower()) < 600000)
minorTicksNumber = 5;
else
minorTicksNumber = 6;
minorGridStepInPixel = (int) (scale.getScaleTickLabels().getGridStepInPixel() / 6.0);
return;
}
if (scale.getScaleTickLabels().getGridStepInPixel() / 5 >= scale.getMinorTickMarkStepHint()) {
minorTicksNumber = 5;
minorGridStepInPixel = (int) (scale.getScaleTickLabels().getGridStepInPixel() / 5.0);
return;
}
if (scale.getScaleTickLabels().getGridStepInPixel() / 4 >= scale.getMinorTickMarkStepHint()) {
minorTicksNumber = 4;
minorGridStepInPixel = (int) (scale.getScaleTickLabels().getGridStepInPixel() / 4.0);
return;
}
minorTicksNumber = 2;
minorGridStepInPixel = (int) (scale.getScaleTickLabels().getGridStepInPixel() / 2.0);
return;
}
/**
* Draw the X tick marks.
*
* @param tickLabelPositions
* the tick label positions
* @param tickLabelSide
* the side of tick label relative to tick marks
* @param width
* the width to draw tick marks
* @param height
* the height to draw tick marks
* @param gc
* the graphics context
*/
protected void drawXTickMarks(Graphics gc, List<Integer> tickLabelPositions, LabelSide tickLabelSide, int width,
int height) {
updateMinorTickParas();
// draw tick marks
gc.setLineStyle(SWTConstants.LINE_SOLID);
if (scale.isLogScaleEnabled()) {
ArrayList<Boolean> tickLabelVisibilities = scale.getScaleTickLabels().getTickVisibilities();
for (int i = 0; i < tickLabelPositions.size(); i++) {
int x = tickLabelPositions.get(i);
int y = 0;
int tickLength = 0;
if (tickLabelVisibilities.get(i))
tickLength = MAJOR_TICK_LENGTH;
else
tickLength = MINOR_TICK_LENGTH;
if (tickLabelSide == LabelSide.Secondary) {
y = height - 1 - LINE_WIDTH - tickLength;
}
// draw minor ticks for log scale
if (tickLabelVisibilities.get(i) || scale.isMinorTicksVisible())
gc.drawLine(x, y, x, y + tickLength);
}
} else {
for (int i = 0; i < tickLabelPositions.size(); i++) {
int x = tickLabelPositions.get(i);
int y = 0;
if (tickLabelSide == LabelSide.Secondary) {
y = height - 1 - LINE_WIDTH - MAJOR_TICK_LENGTH;
}
gc.drawLine(x, y, x, y + MAJOR_TICK_LENGTH);
// draw minor ticks for linear scale
if (scale.isMinorTicksVisible()) {
if (i > 0) {
// draw the first grid step which is start from min
// value
if (i == 1 && (tickLabelPositions.get(1) - tickLabelPositions.get(0)) < scale
.getScaleTickLabels().getGridStepInPixel()) {
x = tickLabelPositions.get(1);
while ((x - tickLabelPositions.get(0)) > minorGridStepInPixel + 3) {
x = x - minorGridStepInPixel;
drawXMinorTicks(gc, tickLabelSide, x, y);
}
} // draw the last grid step which is end to max value
else if (i == tickLabelPositions.size() - 1
&& (tickLabelPositions.get(i) - tickLabelPositions.get(i - 1)) < scale
.getScaleTickLabels().getGridStepInPixel()) {
x = tickLabelPositions.get(i - 1);
while ((tickLabelPositions.get(i) - x) > minorGridStepInPixel + 3) {
x = x + minorGridStepInPixel;
drawXMinorTicks(gc, tickLabelSide, x, y);
}
} else { // draw regular steps
for (int j = 0; j < minorTicksNumber; j++) {
x = tickLabelPositions.get(i - 1)
+ (tickLabelPositions.get(i) - tickLabelPositions.get(i - 1)) * j
/ minorTicksNumber;
drawXMinorTicks(gc, tickLabelSide, x, y);
}
}
}
}
}
}
// draw scale line
if (scale.isScaleLineVisible()) {
if (tickLabelSide == LabelSide.Primary) {
gc.drawLine(scale.getMargin(), 0, width - scale.getMargin(), 0);
} else {
gc.drawLine(scale.getMargin(), height - 1, width - scale.getMargin(), height - 1);
}
}
}
private void drawXMinorTicks(Graphics gc, LabelSide tickLabelSide, int x, int y) {
if (tickLabelSide == LabelSide.Primary)
gc.drawLine(x, y, x, y + MINOR_TICK_LENGTH);
else
gc.drawLine(x, y + MAJOR_TICK_LENGTH - MINOR_TICK_LENGTH, x, y + MAJOR_TICK_LENGTH);
}
/**
* Draw the Y tick marks.
*
* @param tickLabelPositions
* the tick label positions
* @param tickLabelSide
* the side of tick label relative to tick marks
* @param width
* the width to draw tick marks
* @param height
* the height to draw tick marks
* @param gc
* the graphics context
*/
protected void drawYTickMarks(Graphics gc, List<Integer> tickLabelPositions, LabelSide tickLabelSide, int width,
int height) {
updateMinorTickParas();
// draw tick marks
gc.setLineStyle(SWTConstants.LINE_SOLID);
int x = 0;
int y = 0;
if (scale.isLogScaleEnabled()) {
ArrayList<Boolean> tickLabelVisibilities = scale.getScaleTickLabels().getTickVisibilities();
for (int i = 0; i < tickLabelPositions.size(); i++) {
int tickLength = 0;
if (tickLabelVisibilities.get(i))
tickLength = MAJOR_TICK_LENGTH;
else
tickLength = MINOR_TICK_LENGTH;
if (tickLabelSide == LabelSide.Primary) {
x = width - 1 - LINE_WIDTH - tickLength;
} else {
x = LINE_WIDTH;
}
y = height - tickLabelPositions.get(i);
if (tickLabelVisibilities.get(i) || scale.isMinorTicksVisible())
gc.drawLine(x, y, x + tickLength, y);
}
} else {
for (int i = 0; i < tickLabelPositions.size(); i++) {
if (tickLabelSide == LabelSide.Primary) {
x = width - 1 - LINE_WIDTH - MAJOR_TICK_LENGTH;
} else {
x = LINE_WIDTH;
}
y = height - tickLabelPositions.get(i);
gc.drawLine(x, y, x + MAJOR_TICK_LENGTH, y);
// draw minor ticks for linear scale
if (scale.isMinorTicksVisible()) {
if (i > 0) {
// draw the first grid step which is start from min
// value
if (i == 1 && (tickLabelPositions.get(1) - tickLabelPositions.get(0)) < scale
.getScaleTickLabels().getGridStepInPixel()) {
y = tickLabelPositions.get(1);
while ((y - tickLabelPositions.get(0)) > minorGridStepInPixel + 3) {
y = y - minorGridStepInPixel;
drawYMinorTicks(gc, tickLabelSide, x, height - y);
}
} // draw the last grid step which is end to max value
else if (i == tickLabelPositions.size() - 1
&& (tickLabelPositions.get(i) - tickLabelPositions.get(i - 1)) < scale
.getScaleTickLabels().getGridStepInPixel()) {
y = tickLabelPositions.get(i - 1);
while ((tickLabelPositions.get(i) - y) > minorGridStepInPixel + 3) {
y = y + minorGridStepInPixel;
drawYMinorTicks(gc, tickLabelSide, x, height - y);
}
} else { // draw regular steps
for (int j = 0; j < minorTicksNumber; j++) {
y = height - tickLabelPositions.get(i - 1)
- (tickLabelPositions.get(i) - tickLabelPositions.get(i - 1)) * j
/ minorTicksNumber;
drawYMinorTicks(gc, tickLabelSide, x, y);
}
}
}
}
}
}
// draw scale line
if (scale.isScaleLineVisible()) {
if (tickLabelSide == LabelSide.Primary) {
gc.drawLine(width - 1, scale.getMargin(), width - 1, height - scale.getMargin());
} else {
gc.drawLine(0, scale.getMargin(), 0, height - scale.getMargin());
}
}
}
private void drawYMinorTicks(Graphics gc, LabelSide tickLabelSide, int x, int y) {
// there is a misillumiation
int verticalMinorTickLength = MINOR_TICK_LENGTH - 1;
if (tickLabelSide == LabelSide.Primary)
gc.drawLine(x + MAJOR_TICK_LENGTH - verticalMinorTickLength, y, x + MAJOR_TICK_LENGTH, y);
else
gc.drawLine(x, y, x + verticalMinorTickLength, y);
}
/**
*
* @return the scale
*/
public LinearScale getScaleProvider() {
return scale;
}
}