/******************************************************************************* * 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; } }