/** Fetches the latest legend items. */ protected void fetchLegendItems() { this.items.clear(); RectangleEdge p = getPosition(); if (RectangleEdge.isTopOrBottom(p)) { this.items.setArrangement(this.hLayout); } else { this.items.setArrangement(this.vLayout); } if (this.sortOrder.equals(SortOrder.ASCENDING)) { for (int s = 0; s < this.sources.length; s++) { LegendItemCollection legendItems = this.sources[s].getLegendItems(); if (legendItems != null) { for (int i = 0; i < legendItems.getItemCount(); i++) { addItemBlock(legendItems.get(i)); } } } } else { for (int s = this.sources.length - 1; s >= 0; s--) { LegendItemCollection legendItems = this.sources[s].getLegendItems(); if (legendItems != null) { for (int i = legendItems.getItemCount() - 1; i >= 0; i--) { addItemBlock(legendItems.get(i)); } } } } }
/** * Converts a data value to a coordinate in Java2D space, assuming that the axis runs along one * edge of the specified plotArea. Note that it is possible for the coordinate to fall outside the * plotArea. * * @param value the data value. * @param plotArea the area for plotting the data. * @param edge the axis location. * @return The Java2D coordinate. */ @Override public double valueToJava2D(double value, Rectangle2D plotArea, RectangleEdge edge) { Range range = getRange(); double axisMin = switchedLog10(range.getLowerBound()); double axisMax = switchedLog10(range.getUpperBound()); double min = 0.0; double max = 0.0; if (RectangleEdge.isTopOrBottom(edge)) { min = plotArea.getMinX(); max = plotArea.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { min = plotArea.getMaxY(); max = plotArea.getMinY(); } value = switchedLog10(value); if (isInverted()) { return max - (((value - axisMin) / (axisMax - axisMin)) * (max - min)); } else { return min + (((value - axisMin) / (axisMax - axisMin)) * (max - min)); } }
/** * Reserve some space on each axis side because we draw a centered label at each extremity. * * @param g2 the graphics device. * @param plot the plot. * @param plotArea the plot area. * @param edge the edge. * @param space the space already reserved. * @return The reserved space. */ public AxisSpace reserveSpace( Graphics2D g2, Plot plot, Rectangle2D plotArea, RectangleEdge edge, AxisSpace space) { this.internalMarkerCycleBoundTick = null; AxisSpace ret = super.reserveSpace(g2, plot, plotArea, edge, space); if (this.internalMarkerCycleBoundTick == null) { return ret; } FontMetrics fm = g2.getFontMetrics(getTickLabelFont()); Rectangle2D r = TextUtilities.getTextBounds(this.internalMarkerCycleBoundTick.getText(), g2, fm); if (RectangleEdge.isTopOrBottom(edge)) { if (isVerticalTickLabels()) { space.add(r.getHeight() / 2, RectangleEdge.RIGHT); } else { space.add(r.getWidth() / 2, RectangleEdge.RIGHT); } } else if (RectangleEdge.isLeftOrRight(edge)) { if (isVerticalTickLabels()) { space.add(r.getWidth() / 2, RectangleEdge.TOP); } else { space.add(r.getHeight() / 2, RectangleEdge.TOP); } } return ret; }
/** * Converts a coordinate in Java2D space to the corresponding data value, assuming that the axis * runs along one edge of the specified plotArea. * * @param java2DValue the coordinate in Java2D space. * @param plotArea the area in which the data is plotted. * @param edge the axis location. * @return The data value. */ @Override public double java2DToValue(double java2DValue, Rectangle2D plotArea, RectangleEdge edge) { Range range = getRange(); double axisMin = switchedLog10(range.getLowerBound()); double axisMax = switchedLog10(range.getUpperBound()); double plotMin = 0.0; double plotMax = 0.0; if (RectangleEdge.isTopOrBottom(edge)) { plotMin = plotArea.getX(); plotMax = plotArea.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { plotMin = plotArea.getMaxY(); plotMax = plotArea.getMinY(); } if (isInverted()) { return switchedPow10( axisMax - ((java2DValue - plotMin) / (plotMax - plotMin)) * (axisMax - axisMin)); } else { return switchedPow10( axisMin + ((java2DValue - plotMin) / (plotMax - plotMin)) * (axisMax - axisMin)); } }
/** * Converts a coordinate from Java 2D space to data space. * * @param java2DValue the coordinate in Java2D space. * @param dataArea the data area. * @param edge the edge. * @return The data value. */ public double java2DToValue(double java2DValue, Rectangle2D dataArea, RectangleEdge edge) { Range range = getRange(); double vmax = range.getUpperBound(); double vp = getCycleBound(); double jmin = 0.0; double jmax = 0.0; if (RectangleEdge.isTopOrBottom(edge)) { jmin = dataArea.getMinX(); jmax = dataArea.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { jmin = dataArea.getMaxY(); jmax = dataArea.getMinY(); } if (isInverted()) { double jbreak = jmax - (vmax - vp) * (jmax - jmin) / this.period; if (java2DValue >= jbreak) { return vp + (jmax - java2DValue) * this.period / (jmax - jmin); } else { return vp - (java2DValue - jmin) * this.period / (jmax - jmin); } } else { double jbreak = (vmax - vp) * (jmax - jmin) / this.period + jmin; if (java2DValue <= jbreak) { return vp + (java2DValue - jmin) * this.period / (jmax - jmin); } else { return vp - (jmax - java2DValue) * this.period / (jmax - jmin); } } }
/** * Selects an appropriate tick value for the axis. The strategy is to display as many ticks as * possible (selected from an array of 'standard' tick units) without the labels overlapping. * * @param g2 the graphics device. * @param dataArea the area defined by the axes. * @param edge the axis location. * @since 1.0.7 */ protected void selectAutoTickUnit(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) { if (RectangleEdge.isTopOrBottom(edge)) { selectHorizontalAutoTickUnit(g2, dataArea, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { selectVerticalAutoTickUnit(g2, dataArea, edge); } }
/** * Draws the tick marks for the axis. * * @param g2 the graphics device. * @param state the axis state. * @param dataArea the data area. * @param edge the edge. */ protected void drawTickMarks( Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) { if (RectangleEdge.isTopOrBottom(edge)) { drawTickMarksHorizontal(g2, state, dataArea, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { drawTickMarksVertical(g2, state, dataArea, edge); } }
/** * Calculates the positions of the tick labels for the axis, storing the results in the tick label * list (ready for drawing). * * @param g2 the graphics device. * @param state the axis state. * @param dataArea the area in which the plot should be drawn. * @param edge the location of the axis. * @return A list of ticks. */ @Override public List refreshTicks( Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) { List result = new java.util.ArrayList(); if (RectangleEdge.isTopOrBottom(edge)) { result = refreshTicksHorizontal(g2, dataArea, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { result = refreshTicksVertical(g2, dataArea, edge); } return result; }
/** * Estimates the space (height or width) required to draw the axis. * * @param g2 the graphics device. * @param plot the plot that the axis belongs to. * @param plotArea the area within which the plot (including axes) should be drawn. * @param edge the axis location. * @param space space already reserved. * @return The space required to draw the axis (including pre-reserved space). */ public AxisSpace reserveSpace( Graphics2D g2, Plot plot, Rectangle2D plotArea, RectangleEdge edge, AxisSpace space) { // create a new space object if one wasn't supplied... if (space == null) { space = new AxisSpace(); } // if the axis is not visible, no additional space is required... if (!isVisible()) { return space; } // if the axis has a fixed dimension, return it... double dimension = getFixedDimension(); if (dimension > 0.0) { space.ensureAtLeast(dimension, edge); } // get the axis label size and update the space object... Rectangle2D labelEnclosure = getLabelEnclosure(g2, edge); double labelHeight = 0.0; double labelWidth = 0.0; double tickLabelBandsDimension = 0.0; for (int i = 0; i < this.labelInfo.length; i++) { PeriodAxisLabelInfo info = this.labelInfo[i]; FontMetrics fm = g2.getFontMetrics(info.getLabelFont()); tickLabelBandsDimension += info.getPadding().extendHeight(fm.getHeight()); } if (RectangleEdge.isTopOrBottom(edge)) { labelHeight = labelEnclosure.getHeight(); space.add(labelHeight + tickLabelBandsDimension, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { labelWidth = labelEnclosure.getWidth(); space.add(labelWidth + tickLabelBandsDimension, edge); } // add space for the outer tick labels, if any... double tickMarkSpace = 0.0; if (isTickMarksVisible()) { tickMarkSpace = getTickMarkOutsideLength(); } if (this.minorTickMarksVisible) { tickMarkSpace = Math.max(tickMarkSpace, this.minorTickMarkOutsideLength); } space.add(tickMarkSpace, edge); return space; }
public double java2DToValue(double java2DValue, Rectangle2D area, RectangleEdge edge) { Range range = getRange(); double axisMin = range.getLowerBound(); double axisMax = range.getUpperBound(); double min = 0.0d; double max = 0.0d; if (RectangleEdge.isTopOrBottom(edge)) { min = area.getX(); max = area.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { min = area.getMaxY(); max = area.getY(); } if (isInverted()) { return axisMax - (((java2DValue - min) / (max - min)) * (axisMax - axisMin)); } return (((java2DValue - min) / (max - min)) * (axisMax - axisMin)) + axisMin; }
/** * Converts a coordinate in Java2D space to the corresponding data value, assuming that the axis * runs along one edge of the specified dataArea. * * @param java2DValue the coordinate in Java2D space. * @param area the area in which the data is plotted. * @param edge the edge along which the axis lies. * @return The data value. */ public double java2DToValue(double java2DValue, Rectangle2D area, RectangleEdge edge) { double result = Double.NaN; double min = 0.0; double max = 0.0; double axisMin = this.first.getFirstMillisecond(); double axisMax = this.last.getLastMillisecond(); if (RectangleEdge.isTopOrBottom(edge)) { min = area.getX(); max = area.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { min = area.getMaxY(); max = area.getY(); } if (isInverted()) { result = axisMax - ((java2DValue - min) / (max - min) * (axisMax - axisMin)); } else { result = axisMin + ((java2DValue - min) / (max - min) * (axisMax - axisMin)); } return result; }
/** * Draws the plot on a Java 2D graphics device (such as the screen or a printer). * * @param g2 the graphics device. * @param colorBarArea the area within which the axis should be drawn. * @param edge the location. */ public void drawColorBar(Graphics2D g2, Rectangle2D colorBarArea, RectangleEdge edge) { Object antiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); // setTickValues was missing from ColorPalette v. 0.96 // colorPalette.setTickValues(this.axis.getTicks()); Stroke strokeSaved = g2.getStroke(); g2.setStroke(new BasicStroke(1.0f)); if (RectangleEdge.isTopOrBottom(edge)) { double y1 = colorBarArea.getY(); double y2 = colorBarArea.getMaxY(); double xx = colorBarArea.getX(); Line2D line = new Line2D.Double(); while (xx <= colorBarArea.getMaxX()) { double value = this.axis.java2DToValue(xx, colorBarArea, edge); line.setLine(xx, y1, xx, y2); g2.setPaint(getPaint(value)); g2.draw(line); xx += 1; } } else { double y1 = colorBarArea.getX(); double y2 = colorBarArea.getMaxX(); double xx = colorBarArea.getY(); Line2D line = new Line2D.Double(); while (xx <= colorBarArea.getMaxY()) { double value = this.axis.java2DToValue(xx, colorBarArea, edge); line.setLine(y1, xx, y2, xx); g2.setPaint(getPaint(value)); g2.draw(line); xx += 1; } } g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias); g2.setStroke(strokeSaved); }
/** * Estimates the space required for the axis, given a specific drawing area. * * @param g2 the graphics device (used to obtain font information). * @param plot the plot that the axis belongs to. * @param plotArea the area within which the axis should be drawn. * @param edge the axis location (top or bottom). * @param space the space already reserved. * @return The space required to draw the axis. */ public AxisSpace reserveSpace( Graphics2D g2, Plot plot, Rectangle2D plotArea, RectangleEdge edge, AxisSpace space) { // create a new space object if one wasn't supplied... if (space == null) { space = new AxisSpace(); } // if the axis is not visible, no additional space is required... if (!isVisible()) { return space; } space = super.reserveSpace(g2, plot, plotArea, edge, space); double maxdim = getMaxDim(g2, edge); if (RectangleEdge.isTopOrBottom(edge)) { space.add(maxdim, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { space.add(maxdim, edge); } return space; }
/** * Translates a value from data space to Java 2D space. * * @param value the data value. * @param dataArea the data area. * @param edge the edge. * @return The Java 2D value. */ public double valueToJava2D(double value, Rectangle2D dataArea, RectangleEdge edge) { Range range = getRange(); double vmin = range.getLowerBound(); double vmax = range.getUpperBound(); double vp = getCycleBound(); if ((value < vmin) || (value > vmax)) { return Double.NaN; } double jmin = 0.0; double jmax = 0.0; if (RectangleEdge.isTopOrBottom(edge)) { jmin = dataArea.getMinX(); jmax = dataArea.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { jmax = dataArea.getMinY(); jmin = dataArea.getMaxY(); } if (isInverted()) { if (value == vp) { return this.boundMappedToLastCycle ? jmin : jmax; } else if (value > vp) { return jmax - (value - vp) * (jmax - jmin) / this.period; } else { return jmin + (vp - value) * (jmax - jmin) / this.period; } } else { if (value == vp) { return this.boundMappedToLastCycle ? jmax : jmin; } else if (value >= vp) { return jmin + (value - vp) * (jmax - jmin) / this.period; } else { return jmax - (vp - value) * (jmax - jmin) / this.period; } } }
/** * Converts a data value to a coordinate in Java2D space, assuming that the axis runs along one * edge of the specified dataArea. * * <p>Note that it is possible for the coordinate to fall outside the area. * * @param value the data value. * @param area the area for plotting the data. * @param edge the edge along which the axis lies. * @return The Java2D coordinate. */ public double valueToJava2D(double value, Rectangle2D area, RectangleEdge edge) { double result = Double.NaN; double axisMin = this.first.getFirstMillisecond(); double axisMax = this.last.getLastMillisecond(); if (RectangleEdge.isTopOrBottom(edge)) { double minX = area.getX(); double maxX = area.getMaxX(); if (isInverted()) { result = maxX + ((value - axisMin) / (axisMax - axisMin)) * (minX - maxX); } else { result = minX + ((value - axisMin) / (axisMax - axisMin)) * (maxX - minX); } } else if (RectangleEdge.isLeftOrRight(edge)) { double minY = area.getMinY(); double maxY = area.getMaxY(); if (isInverted()) { result = minY + (((value - axisMin) / (axisMax - axisMin)) * (maxY - minY)); } else { result = maxY - (((value - axisMin) / (axisMax - axisMin)) * (maxY - minY)); } } return result; }
/** * Draws the legend within the specified area. * * @param g2 the graphics target (<code>null</code> not permitted). * @param area the drawing area (<code>null</code> not permitted). * @param params drawing parameters (ignored here). * @return <code>null</code>. */ public Object draw(Graphics2D g2, Rectangle2D area, Object params) { Rectangle2D target = (Rectangle2D) area.clone(); target = trimMargin(target); if (this.backgroundPaint != null) { g2.setPaint(this.backgroundPaint); g2.fill(target); } getFrame().draw(g2, target); getFrame().getInsets().trim(target); target = trimPadding(target); double base = this.axis.getLowerBound(); double increment = this.axis.getRange().getLength() / this.subdivisions; Rectangle2D r = new Rectangle2D.Double(); if (RectangleEdge.isTopOrBottom(getPosition())) { RectangleEdge axisEdge = Plot.resolveRangeAxisLocation(this.axisLocation, PlotOrientation.HORIZONTAL); if (axisEdge == RectangleEdge.TOP) { for (int i = 0; i < this.subdivisions; i++) { double v = base + (i * increment); Paint p = this.scale.getPaint(v); double vv0 = this.axis.valueToJava2D(v, target, RectangleEdge.TOP); double vv1 = this.axis.valueToJava2D(v + increment, target, RectangleEdge.TOP); double ww = Math.abs(vv1 - vv0) + 1.0; r.setRect(Math.min(vv0, vv1), target.getMaxY() - this.stripWidth, ww, this.stripWidth); g2.setPaint(p); g2.fill(r); } if (isStripOutlineVisible()) { g2.setPaint(this.stripOutlinePaint); g2.setStroke(this.stripOutlineStroke); g2.draw( new Rectangle2D.Double( target.getMinX(), target.getMaxY() - this.stripWidth, target.getWidth(), this.stripWidth)); } this.axis.draw( g2, target.getMaxY() - this.stripWidth - this.axisOffset, target, target, RectangleEdge.TOP, null); } else if (axisEdge == RectangleEdge.BOTTOM) { for (int i = 0; i < this.subdivisions; i++) { double v = base + (i * increment); Paint p = this.scale.getPaint(v); double vv0 = this.axis.valueToJava2D(v, target, RectangleEdge.BOTTOM); double vv1 = this.axis.valueToJava2D(v + increment, target, RectangleEdge.BOTTOM); double ww = Math.abs(vv1 - vv0) + 1.0; r.setRect(Math.min(vv0, vv1), target.getMinY(), ww, this.stripWidth); g2.setPaint(p); g2.fill(r); } if (isStripOutlineVisible()) { g2.setPaint(this.stripOutlinePaint); g2.setStroke(this.stripOutlineStroke); g2.draw( new Rectangle2D.Double( target.getMinX(), target.getMinY(), target.getWidth(), this.stripWidth)); } this.axis.draw( g2, target.getMinY() + this.stripWidth + this.axisOffset, target, target, RectangleEdge.BOTTOM, null); } } else { RectangleEdge axisEdge = Plot.resolveRangeAxisLocation(this.axisLocation, PlotOrientation.VERTICAL); if (axisEdge == RectangleEdge.LEFT) { for (int i = 0; i < this.subdivisions; i++) { double v = base + (i * increment); Paint p = this.scale.getPaint(v); double vv0 = this.axis.valueToJava2D(v, target, RectangleEdge.LEFT); double vv1 = this.axis.valueToJava2D(v + increment, target, RectangleEdge.LEFT); double hh = Math.abs(vv1 - vv0) + 1.0; r.setRect(target.getMaxX() - this.stripWidth, Math.min(vv0, vv1), this.stripWidth, hh); g2.setPaint(p); g2.fill(r); } if (isStripOutlineVisible()) { g2.setPaint(this.stripOutlinePaint); g2.setStroke(this.stripOutlineStroke); g2.draw( new Rectangle2D.Double( target.getMaxX() - this.stripWidth, target.getMinY(), this.stripWidth, target.getHeight())); } this.axis.draw( g2, target.getMaxX() - this.stripWidth - this.axisOffset, target, target, RectangleEdge.LEFT, null); } else if (axisEdge == RectangleEdge.RIGHT) { for (int i = 0; i < this.subdivisions; i++) { double v = base + (i * increment); Paint p = this.scale.getPaint(v); double vv0 = this.axis.valueToJava2D(v, target, RectangleEdge.LEFT); double vv1 = this.axis.valueToJava2D(v + increment, target, RectangleEdge.LEFT); double hh = Math.abs(vv1 - vv0) + 1.0; r.setRect(target.getMinX(), Math.min(vv0, vv1), this.stripWidth, hh); g2.setPaint(p); g2.fill(r); } if (isStripOutlineVisible()) { g2.setPaint(this.stripOutlinePaint); g2.setStroke(this.stripOutlineStroke); g2.draw( new Rectangle2D.Double( target.getMinX(), target.getMinY(), this.stripWidth, target.getHeight())); } this.axis.draw( g2, target.getMinX() + this.stripWidth + this.axisOffset, target, target, RectangleEdge.RIGHT, null); } } return null; }
/** * Draws the category labels and returns the updated axis state. * * @param g2 the graphics device (<code>null</code> not permitted). * @param plotArea the plot area (<code>null</code> not permitted). * @param dataArea the area inside the axes (<code>null</code> not permitted). * @param edge the axis location (<code>null</code> not permitted). * @param state the axis state (<code>null</code> not permitted). * @param plotState collects information about the plot (<code>null</code> permitted). * @return The updated axis state (never <code>null</code>). */ protected AxisState drawSubCategoryLabels( Graphics2D g2, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge, AxisState state, PlotRenderingInfo plotState) { if (state == null) { throw new IllegalArgumentException("Null 'state' argument."); } g2.setFont(this.subLabelFont); g2.setPaint(this.subLabelPaint); CategoryPlot plot = (CategoryPlot) getPlot(); CategoryDataset dataset = plot.getDataset(); int categoryCount = dataset.getColumnCount(); double maxdim = getMaxDim(g2, edge); for (int categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) { double x0 = 0.0; double x1 = 0.0; double y0 = 0.0; double y1 = 0.0; if (edge == RectangleEdge.TOP) { x0 = getCategoryStart(categoryIndex, categoryCount, dataArea, edge); x1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, edge); y1 = state.getCursor(); y0 = y1 - maxdim; } else if (edge == RectangleEdge.BOTTOM) { x0 = getCategoryStart(categoryIndex, categoryCount, dataArea, edge); x1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, edge); y0 = state.getCursor(); y1 = y0 + maxdim; } else if (edge == RectangleEdge.LEFT) { y0 = getCategoryStart(categoryIndex, categoryCount, dataArea, edge); y1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, edge); x1 = state.getCursor(); x0 = x1 - maxdim; } else if (edge == RectangleEdge.RIGHT) { y0 = getCategoryStart(categoryIndex, categoryCount, dataArea, edge); y1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, edge); x0 = state.getCursor(); x1 = x0 + maxdim; } Rectangle2D area = new Rectangle2D.Double(x0, y0, (x1 - x0), (y1 - y0)); int subCategoryCount = this.subCategories.size(); float width = (float) ((x1 - x0) / subCategoryCount); float height = (float) ((y1 - y0) / subCategoryCount); float xx = 0.0f; float yy = 0.0f; for (int i = 0; i < subCategoryCount; i++) { if (RectangleEdge.isTopOrBottom(edge)) { xx = (float) (x0 + (i + 0.5) * width); yy = (float) area.getCenterY(); } else { xx = (float) area.getCenterX(); yy = (float) (y0 + (i + 0.5) * height); } String label = this.subCategories.get(i).toString(); TextUtilities.drawRotatedString( label, g2, xx, yy, TextAnchor.CENTER, 0.0, TextAnchor.CENTER); } } if (edge.equals(RectangleEdge.TOP)) { double h = maxdim; state.cursorUp(h); } else if (edge.equals(RectangleEdge.BOTTOM)) { double h = maxdim; state.cursorDown(h); } else if (edge == RectangleEdge.LEFT) { double w = maxdim; state.cursorLeft(w); } else if (edge == RectangleEdge.RIGHT) { double w = maxdim; state.cursorRight(w); } return state; }