@Override public void chartMouseMoved(ChartMouseEventFX event) { Rectangle2D dataArea = this.chartViewer.getCanvas().getRenderingInfo().getPlotInfo().getDataArea(); JFreeChart chart = event.getChart(); XYPlot plot = (XYPlot) chart.getPlot(); ValueAxis xAxis = plot.getDomainAxis(); double x = xAxis.java2DToValue(event.getTrigger().getX(), dataArea, RectangleEdge.BOTTOM); // make the crosshairs disappear if the mouse is out of range if (!xAxis.getRange().contains(x)) { x = Double.NaN; } double y = DatasetUtils.findYValue(plot.getDataset(), 0, x); this.xCrosshair.setValue(x); this.yCrosshair.setValue(y); }
/** * This test is for a particular bug that arose just prior to the release * of JFreeChart 1.0.10. A BorderArrangement with LEFT, CENTRE and RIGHT * blocks that is too wide, by default, for the available space, wasn't * shrinking the centre block as expected. */ @Test public void testBugX() { RectangleConstraint constraint = new RectangleConstraint( new Range(0.0, 200.0), new Range(0.0, 100.0)); BlockContainer container = new BlockContainer(new BorderArrangement()); BufferedImage image = new BufferedImage(200, 100, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = image.createGraphics(); container.add(new EmptyBlock(10.0, 6.0), RectangleEdge.LEFT); container.add(new EmptyBlock(20.0, 6.0), RectangleEdge.RIGHT); container.add(new EmptyBlock(30.0, 6.0)); Size2D size = container.arrange(g2, constraint); assertEquals(60.0, size.width, EPSILON); assertEquals(6.0, size.height, EPSILON); container.clear(); container.add(new EmptyBlock(10.0, 6.0), RectangleEdge.LEFT); container.add(new EmptyBlock(20.0, 6.0), RectangleEdge.RIGHT); container.add(new EmptyBlock(300.0, 6.0)); size = container.arrange(g2, constraint); assertEquals(200.0, size.width, EPSILON); assertEquals(6.0, size.height, EPSILON); }
/** * Returns the middle coordinate (in Java2D space) for a series within a * category. * * @param categoryIndex the category index. * @param categoryCount the category count. * @param seriesIndex the series index. * @param seriesCount the series count. * @param itemMargin the item margin (0.0 <= itemMargin < 1.0); * @param area the area ({@code null} not permitted). * @param edge the edge ({@code null} not permitted). * * @return The coordinate in Java2D space. * * @since 1.0.13 */ public double getCategorySeriesMiddle(int categoryIndex, int categoryCount, int seriesIndex, int seriesCount, double itemMargin, Rectangle2D area, RectangleEdge edge) { double start = getCategoryStart(categoryIndex, categoryCount, area, edge); double end = getCategoryEnd(categoryIndex, categoryCount, area, edge); double width = end - start; if (seriesCount == 1) { return start + width / 2.0; } else { double gap = (width * itemMargin) / (seriesCount - 1); double ww = (width * (1 - itemMargin)) / seriesCount; return start + (seriesIndex * (ww + gap)) + ww / 2.0; } }
/** * Creates a new legend title with the specified arrangement. * * @param source the source. * @param hLayout the horizontal item arrangement ({@code null} not * permitted). * @param vLayout the vertical item arrangement ({@code null} not * permitted). */ public LegendTitle(LegendItemSource source, Arrangement hLayout, Arrangement vLayout) { this.sources = new LegendItemSource[] {source}; this.items = new BlockContainer(hLayout); this.hLayout = hLayout; this.vLayout = vLayout; this.backgroundPaint = null; this.legendItemGraphicEdge = RectangleEdge.LEFT; this.legendItemGraphicAnchor = RectangleAnchor.CENTER; this.legendItemGraphicLocation = RectangleAnchor.CENTER; this.legendItemGraphicPadding = new RectangleInsets(2.0, 2.0, 2.0, 2.0); this.itemFont = DEFAULT_ITEM_FONT; this.itemPaint = DEFAULT_ITEM_PAINT; this.itemLabelPadding = new RectangleInsets(2.0, 2.0, 2.0, 2.0); this.sortOrder = SortOrder.ASCENDING; }
/** * Creates a new title. * * @param position the position of the title ({@code null} not * permitted). * @param horizontalAlignment the horizontal alignment of the title (LEFT, * CENTER or RIGHT, {@code null} not * permitted). * @param verticalAlignment the vertical alignment of the title (TOP, * MIDDLE or BOTTOM, {@code null} not * permitted). * @param padding the amount of space to leave around the outside of the * title ({@code null} not permitted). */ protected Title(RectangleEdge position, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, RectangleInsets padding) { Args.nullNotPermitted(position, "position"); Args.nullNotPermitted(horizontalAlignment, "horizontalAlignment"); Args.nullNotPermitted(verticalAlignment, "verticalAlignment"); Args.nullNotPermitted(padding, "padding"); this.visible = true; this.position = position; this.horizontalAlignment = horizontalAlignment; this.verticalAlignment = verticalAlignment; setPadding(padding); this.listenerList = new EventListenerList(); this.notify = true; }
/** * Converts a length in data coordinates into the corresponding length in * Java2D coordinates. * * @param length the length. * @param area the plot area. * @param edge the edge along which the axis lies. * * @return The length in Java2D coordinates. */ @Override public double lengthToJava2D(double length, Rectangle2D area, RectangleEdge edge) { double axisLength = 0.0; if (this.displayEnd > this.displayStart) { axisLength = this.displayEnd - this.displayStart; } else { axisLength = (this.fixedRange.getUpperBound() - this.displayStart) + (this.displayEnd - this.fixedRange.getLowerBound()); } double areaLength; if (RectangleEdge.isLeftOrRight(edge)) { areaLength = area.getHeight(); } else { areaLength = area.getWidth(); } return (length / axisLength) * areaLength; }
/** * Paints a single bar instance. * * @param g2 the graphics target. * @param renderer the renderer. * @param row the row index. * @param column the column index. * @param bar the bar * @param base indicates which side of the rectangle is the base of the * bar. */ @Override public void paintBar(Graphics2D g2, XYBarRenderer renderer, int row, int column, RectangularShape bar, RectangleEdge base) { Paint itemPaint = renderer.getItemPaint(row, column); GradientPaintTransformer t = renderer.getGradientPaintTransformer(); if (t != null && itemPaint instanceof GradientPaint) { itemPaint = t.transform((GradientPaint) itemPaint, bar); } g2.setPaint(itemPaint); g2.fill(bar); // draw the outline... if (renderer.isDrawBarOutline()) { // && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { Stroke stroke = renderer.getItemOutlineStroke(row, column); Paint paint = renderer.getItemOutlinePaint(row, column); if (stroke != null && paint != null) { g2.setStroke(stroke); g2.setPaint(paint); g2.draw(bar); } } }
/** * Calculates the size (width or height, depending on the location of the * axis) of a category. * * @param categoryCount the number of categories. * @param area the area within which the categories will be drawn. * @param edge the axis location. * * @return The category size. */ protected double calculateCategorySize(int categoryCount, Rectangle2D area, RectangleEdge edge) { double result; double available = 0.0; if ((edge == RectangleEdge.TOP) || (edge == RectangleEdge.BOTTOM)) { available = area.getWidth(); } else if ((edge == RectangleEdge.LEFT) || (edge == RectangleEdge.RIGHT)) { available = area.getHeight(); } if (categoryCount > 1) { result = available * (1 - getLowerMargin() - getUpperMargin() - getCategoryMargin()); result = result / categoryCount; } else { result = available * (1 - getLowerMargin() - getUpperMargin()); } return result; }
/** * Returns the middle coordinate (in Java2D space) for a series within a * category. * * @param category the category ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * @param dataset the dataset ({@code null} not permitted). * @param itemMargin the item margin (0.0 <= itemMargin < 1.0); * @param area the area ({@code null} not permitted). * @param edge the edge ({@code null} not permitted). * * @return The coordinate in Java2D space. * * @since 1.0.7 */ public double getCategorySeriesMiddle(Comparable category, Comparable seriesKey, CategoryDataset dataset, double itemMargin, Rectangle2D area, RectangleEdge edge) { int categoryIndex = dataset.getColumnIndex(category); int categoryCount = dataset.getColumnCount(); int seriesIndex = dataset.getRowIndex(seriesKey); int seriesCount = dataset.getRowCount(); double start = getCategoryStart(categoryIndex, categoryCount, area, edge); double end = getCategoryEnd(categoryIndex, categoryCount, area, edge); double width = end - start; if (seriesCount == 1) { return start + width / 2.0; } else { double gap = (width * itemMargin) / (seriesCount - 1); double ww = (width * (1 - itemMargin)) / seriesCount; return start + (seriesIndex * (ww + gap)) + ww / 2.0; } }
/** * Translates a data value to a Java2D coordinate. * * @param value the value. * @param area the area. * @param edge the edge. * * @return A Java2D coordinate. */ @Override public double valueToJava2D(double value, Rectangle2D area, RectangleEdge edge) { double result; double v = mapValueToFixedRange(value); if (this.displayStart < this.displayEnd) { // regular number axis result = trans(v, area, edge); } else { // displayStart > displayEnd, need to handle split double cutoff = (this.displayStart + this.displayEnd) / 2.0; double length1 = this.fixedRange.getUpperBound() - this.displayStart; double length2 = this.displayEnd - this.fixedRange.getLowerBound(); if (v > cutoff) { result = transStart(v, area, edge, length1, length2); } else { result = transEnd(v, area, edge, length1, length2); } } return result; }
/** * Paints a single bar instance. * * @param g2 the graphics target. * @param renderer the renderer. * @param row the row index. * @param column the column index. * @param bar the bar * @param base indicates which side of the rectangle is the base of the * bar. */ @Override public void paintBar(Graphics2D g2, BarRenderer renderer, int row, int column, RectangularShape bar, RectangleEdge base) { Paint itemPaint = renderer.getItemPaint(row, column); GradientPaintTransformer t = renderer.getGradientPaintTransformer(); if (t != null && itemPaint instanceof GradientPaint) { itemPaint = t.transform((GradientPaint) itemPaint, bar); } g2.setPaint(itemPaint); g2.fill(bar); // draw the outline... if (renderer.isDrawBarOutline()) { // && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { Stroke stroke = renderer.getItemOutlineStroke(row, column); Paint paint = renderer.getItemOutlinePaint(row, column); if (stroke != null && paint != null) { g2.setStroke(stroke); g2.setPaint(paint); g2.draw(bar); } } }
/** * Paints a single bar instance. * * @param g2 the graphics target. * @param renderer the renderer. * @param row the row index. * @param column the column index. * @param bar the bar * @param base indicates which side of the rectangle is the base of the * bar. * @param pegShadow peg the shadow to the base of the bar? */ @Override public void paintBarShadow(Graphics2D g2, BarRenderer renderer, int row, int column, RectangularShape bar, RectangleEdge base, boolean pegShadow) { // handle a special case - if the bar colour has alpha == 0, it is // invisible so we shouldn't draw any shadow Paint itemPaint = renderer.getItemPaint(row, column); if (itemPaint instanceof Color) { Color c = (Color) itemPaint; if (c.getAlpha() == 0) { return; } } RectangularShape shadow = createShadow(bar, renderer.getShadowXOffset(), renderer.getShadowYOffset(), base, pegShadow); g2.setPaint(renderer.getShadowPaint()); g2.fill(shadow); }
/** * 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. */ @Override 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; }
/** * Multiplies the range on the range axis by the specified factor. * * @param factor the zoom factor. * @param info the plot rendering info. * @param source the source point (in Java2D space). * @param useAnchor use source point as zoom anchor? * * @see #zoomDomainAxes(double, PlotRenderingInfo, Point2D, boolean) * * @since 1.0.7 */ @Override public void zoomRangeAxes(double factor, PlotRenderingInfo info, Point2D source, boolean useAnchor) { // get the source coordinate - this plot has always a VERTICAL // orientation final double sourceX = source.getX(); for (int axisIdx = 0; axisIdx < getAxisCount(); axisIdx++) { final ValueAxis axis = getAxis(axisIdx); if (axis != null) { if (useAnchor) { double anchorX = axis.java2DToValue(sourceX, info.getDataArea(), RectangleEdge.BOTTOM); axis.resizeRange(factor, anchorX); } else { axis.resizeRange(factor); } } } }
/** * Utility method for drawing a horizontal line across the data area of the * plot. * * @param g2 the graphics device. * @param dataArea the data area. * @param value the coordinate, where to draw the line. * @param stroke the stroke to use. * @param paint the paint to use. */ protected void drawHorizontalLine(Graphics2D g2, Rectangle2D dataArea, double value, Stroke stroke, Paint paint) { ValueAxis axis = getRangeAxis(); if (getOrientation() == PlotOrientation.HORIZONTAL) { axis = getDomainAxis(); } if (axis.getRange().contains(value)) { double yy = axis.valueToJava2D(value, dataArea, RectangleEdge.LEFT); Line2D line = new Line2D.Double(dataArea.getMinX(), yy, dataArea.getMaxX(), yy); g2.setStroke(stroke); g2.setPaint(paint); g2.draw(line); } }
/** * Draws the gridlines for the plot, if they are visible. * * @param g2 the graphics device. * @param dataArea the data area. * @param ticks the ticks. */ protected void drawDomainGridlines(Graphics2D g2, Rectangle2D dataArea, List ticks) { if (!isDomainGridlinesVisible()) { return; } Object saved = g2.getRenderingHint(RenderingHints.KEY_STROKE_CONTROL); g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); Iterator iterator = ticks.iterator(); while (iterator.hasNext()) { ValueTick tick = (ValueTick) iterator.next(); double v = this.domainAxis.valueToJava2D(tick.getValue(), dataArea, RectangleEdge.BOTTOM); Line2D line = new Line2D.Double(v, dataArea.getMinY(), v, dataArea.getMaxY()); g2.setPaint(getDomainGridlinePaint()); g2.setStroke(getDomainGridlineStroke()); g2.draw(line); } g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, saved); }
/** * Multiplies the range on the domain axis by the specified factor. * * @param factor the zoom factor. * @param info the plot rendering info. * @param source the source point (in Java2D space). * @param useAnchor use source point as zoom anchor? * * @see #zoomRangeAxes(double, PlotRenderingInfo, Point2D, boolean) * * @since 1.0.7 */ @Override public void zoomDomainAxes(double factor, PlotRenderingInfo info, Point2D source, boolean useAnchor) { if (useAnchor) { // get the source coordinate - this plot has always a VERTICAL // orientation double sourceX = source.getX(); double anchorX = this.domainAxis.java2DToValue(sourceX, info.getDataArea(), RectangleEdge.BOTTOM); this.domainAxis.resizeRange2(factor, anchorX); } else { this.domainAxis.resizeRange(factor); } }
/** * Multiplies the range on the range axis by the specified factor. * * @param factor the zoom factor. * @param info the plot rendering info. * @param source the source point (in Java2D space). * @param useAnchor use source point as zoom anchor? * * @see #zoomDomainAxes(double, PlotRenderingInfo, Point2D, boolean) * * @since 1.0.7 */ @Override public void zoomRangeAxes(double factor, PlotRenderingInfo info, Point2D source, boolean useAnchor) { if (useAnchor) { // get the source coordinate - this plot has always a VERTICAL // orientation double sourceY = source.getY(); double anchorY = this.rangeAxis.java2DToValue(sourceY, info.getDataArea(), RectangleEdge.LEFT); this.rangeAxis.resizeRange2(factor, anchorY); } else { this.rangeAxis.resizeRange(factor); } }
/** * Test the translation of Java2D values to data values. */ @Test public void testTranslateJava2DToValue() { LogAxis axis = new LogAxis(); axis.setRange(50.0, 100.0); Rectangle2D dataArea = new Rectangle2D.Double(10.0, 50.0, 400.0, 300.0); double y1 = axis.java2DToValue(75.0, dataArea, RectangleEdge.LEFT); assertEquals(94.3874312681693, y1, EPSILON); double y2 = axis.java2DToValue(75.0, dataArea, RectangleEdge.RIGHT); assertEquals(94.3874312681693, y2, EPSILON); double x1 = axis.java2DToValue(75.0, dataArea, RectangleEdge.TOP); assertEquals(55.961246381405, x1, EPSILON); double x2 = axis.java2DToValue(75.0, dataArea, RectangleEdge.BOTTOM); assertEquals(55.961246381405, x2, EPSILON); axis.setInverted(true); double y3 = axis.java2DToValue(75.0, dataArea, RectangleEdge.LEFT); assertEquals(52.9731547179647, y3, EPSILON); double y4 = axis.java2DToValue(75.0, dataArea, RectangleEdge.RIGHT); assertEquals(52.9731547179647, y4, EPSILON); double x3 = axis.java2DToValue(75.0, dataArea, RectangleEdge.TOP); assertEquals(89.3475453695651, x3, EPSILON); double x4 = axis.java2DToValue(75.0, dataArea, RectangleEdge.BOTTOM); assertEquals(89.3475453695651, x4, EPSILON); }
/** * Creates a new plot. * * @param dataset the dataset ({@code null} permitted). */ public MultiplePiePlot(CategoryDataset dataset) { super(); setDataset(dataset); PiePlot piePlot = new PiePlot(null); piePlot.setIgnoreNullValues(true); this.pieChart = new JFreeChart(piePlot); this.pieChart.removeLegend(); this.dataExtractOrder = TableOrder.BY_COLUMN; this.pieChart.setBackgroundPaint(null); TextTitle seriesTitle = new TextTitle("Series Title", new Font("SansSerif", Font.BOLD, 12)); seriesTitle.setPosition(RectangleEdge.BOTTOM); this.pieChart.setTitle(seriesTitle); this.aggregatedItemsKey = "Other"; this.aggregatedItemsPaint = Color.lightGray; this.sectionPaints = new HashMap(); this.legendItemShape = new Ellipse2D.Double(-4.0, -4.0, 8.0, 8.0); }
/** * Handles a 'click' on the plot by updating the anchor value. * * @param x x-coordinate of the click (in Java2D space). * @param y y-coordinate of the click (in Java2D space). * @param info information about the plot's dimensions. * */ @Override public void handleClick(int x, int y, PlotRenderingInfo info) { Rectangle2D dataArea = info.getDataArea(); if (dataArea.contains(x, y)) { // set the anchor value for the range axis... double java2D = 0.0; if (this.orientation == PlotOrientation.HORIZONTAL) { java2D = x; } else if (this.orientation == PlotOrientation.VERTICAL) { java2D = y; } RectangleEdge edge = Plot.resolveRangeAxisLocation( getRangeAxisLocation(), this.orientation); double value = getRangeAxis().java2DToValue( java2D, info.getDataArea(), edge); setAnchorValue(value); setRangeCrosshairValue(value); } }
/** * Draws the domain gridlines for the plot, if they are visible. * * @param g2 the graphics device. * @param dataArea the area inside the axes. * * @see #drawRangeGridlines(Graphics2D, Rectangle2D, List) */ protected void drawDomainGridlines(Graphics2D g2, Rectangle2D dataArea) { if (!isDomainGridlinesVisible()) { return; } CategoryAnchor anchor = getDomainGridlinePosition(); RectangleEdge domainAxisEdge = getDomainAxisEdge(); CategoryDataset dataset = getDataset(); if (dataset == null) { return; } CategoryAxis axis = getDomainAxis(); if (axis != null) { int columnCount = dataset.getColumnCount(); for (int c = 0; c < columnCount; c++) { double xx = axis.getCategoryJava2DCoordinate(anchor, c, columnCount, dataArea, domainAxisEdge); CategoryItemRenderer renderer1 = getRenderer(); if (renderer1 != null) { renderer1.drawDomainGridline(g2, this, dataArea, xx); } } } }
/** * Draws a range crosshair. * * @param g2 the graphics target. * @param dataArea the data area. * @param orientation the plot orientation. * @param value the crosshair value. * @param axis the axis against which the value is measured. * @param stroke the stroke used to draw the crosshair line. * @param paint the paint used to draw the crosshair line. * * @see #drawDomainCrosshair(Graphics2D, Rectangle2D, PlotOrientation, int, * Comparable, Comparable, Stroke, Paint) * * @since 1.0.5 */ protected void drawRangeCrosshair(Graphics2D g2, Rectangle2D dataArea, PlotOrientation orientation, double value, ValueAxis axis, Stroke stroke, Paint paint) { if (!axis.getRange().contains(value)) { return; } Line2D line; if (orientation == PlotOrientation.HORIZONTAL) { double xx = axis.valueToJava2D(value, dataArea, RectangleEdge.BOTTOM); line = new Line2D.Double(xx, dataArea.getMinY(), xx, dataArea.getMaxY()); } else { double yy = axis.valueToJava2D(value, dataArea, RectangleEdge.LEFT); line = new Line2D.Double(dataArea.getMinX(), yy, dataArea.getMaxX(), yy); } g2.setStroke(stroke); g2.setPaint(paint); g2.draw(line); }
/** * Calculates the size (width or height, depending on the location of the * axis) of a category gap. * * @param categoryCount the number of categories. * @param area the area within which the categories will be drawn. * @param edge the axis location. * * @return The category gap width. */ protected double calculateCategoryGapSize(int categoryCount, Rectangle2D area, RectangleEdge edge) { double result = 0.0; double available = 0.0; if ((edge == RectangleEdge.TOP) || (edge == RectangleEdge.BOTTOM)) { available = area.getWidth(); } else if ((edge == RectangleEdge.LEFT) || (edge == RectangleEdge.RIGHT)) { available = area.getHeight(); } if (categoryCount > 1) { result = available * getCategoryMargin() / (categoryCount - 1); } return result; }
@Test public void testBug3484403() { final long[] dates = { 1304892000000L, 1304632800000L, 1304546400000L, 1304460000000L, 1304373600000L, 1304287200000L, 1320015600000L, 1309384800000L, 1319752800000L, 1319666400000L, 1319580000000L, 1319493600000L }; Arrays.sort(dates); DateAxis axis = new DateAxis("Date"); // set start and end date Date start = new Date(dates[0]); Date end = new Date(dates[dates.length-1]); axis.setMinimumDate(start); axis.setMaximumDate(end); BufferedImage image = new BufferedImage(200, 100, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = image.createGraphics(); Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, 500, 200); // if the bug is still present, this leads to an endless loop axis.refreshTicks(g2, new AxisState(), area, RectangleEdge.BOTTOM); }
/** * Selects an appropriate tick size for the axis. The strategy is to * display as many ticks as possible (selected from a collection 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. */ protected void selectHorizontalAutoTickUnit(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) { double zero = valueToJava2D(0.0, dataArea, edge); double tickLabelWidth = estimateMaximumTickLabelWidth(g2, getTickUnit()); // start with the current tick unit... TickUnitSource tickUnits = getStandardTickUnits(); TickUnit unit1 = tickUnits.getCeilingTickUnit(getTickUnit()); double x1 = valueToJava2D(unit1.getSize(), dataArea, edge); double unit1Width = Math.abs(x1 - zero); // then extrapolate... double guess = (tickLabelWidth / unit1Width) * unit1.getSize(); DateTickUnit unit2 = (DateTickUnit) tickUnits.getCeilingTickUnit(guess); double x2 = valueToJava2D(unit2.getSize(), dataArea, edge); double unit2Width = Math.abs(x2 - zero); tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit2); if (tickLabelWidth > unit2Width) { unit2 = (DateTickUnit) tickUnits.getLargerTickUnit(unit2); } setTickUnit(unit2, false, false); }
/** * Check the translation java2D to value for left, right, and center point. * * @param edge the edge. * @param plotArea the plot area. */ private void checkPointsToValue(RectangleEdge edge, Rectangle2D plotArea) { assertEquals("Right most point on the axis should be end of range.", this.axis.getUpperBound(), this.axis.java2DToValue( plotArea.getX() + plotArea.getWidth(), plotArea, edge), EPSILON); assertEquals("Left most point on the axis should be beginning of " + "range.", this.axis.getLowerBound(), this.axis.java2DToValue(plotArea.getX(), plotArea, edge), EPSILON); assertEquals("Center point on the axis should geometric mean of the " + "bounds.", Math.sqrt(this.axis.getUpperBound() * this.axis.getLowerBound()), this.axis.java2DToValue( plotArea.getX() + (plotArea.getWidth() / 2), plotArea, edge), EPSILON); }
/** * Test the translation of Java2D values to data values. */ @Test public void testJava2DToValue() { DateAxis axis = new DateAxis(); axis.setRange(50.0, 100.0); Rectangle2D dataArea = new Rectangle2D.Double(10.0, 50.0, 400.0, 300.0); double y1 = axis.java2DToValue(75.0, dataArea, RectangleEdge.LEFT); assertTrue(same(y1, 95.8333333, 1.0)); double y2 = axis.java2DToValue(75.0, dataArea, RectangleEdge.RIGHT); assertTrue(same(y2, 95.8333333, 1.0)); double x1 = axis.java2DToValue(75.0, dataArea, RectangleEdge.TOP); assertTrue(same(x1, 58.125, 1.0)); double x2 = axis.java2DToValue(75.0, dataArea, RectangleEdge.BOTTOM); assertTrue(same(x2, 58.125, 1.0)); axis.setInverted(true); double y3 = axis.java2DToValue(75.0, dataArea, RectangleEdge.LEFT); assertTrue(same(y3, 54.1666667, 1.0)); double y4 = axis.java2DToValue(75.0, dataArea, RectangleEdge.RIGHT); assertTrue(same(y4, 54.1666667, 1.0)); double x3 = axis.java2DToValue(75.0, dataArea, RectangleEdge.TOP); assertTrue(same(x3, 91.875, 1.0)); double x4 = axis.java2DToValue(75.0, dataArea, RectangleEdge.BOTTOM); assertTrue(same(x4, 91.875, 1.0)); }
/** * Test the translation of Java2D values to data values. */ @Test public void testTranslateJava2DToValue() { NumberAxis axis = new NumberAxis(); axis.setRange(50.0, 100.0); Rectangle2D dataArea = new Rectangle2D.Double(10.0, 50.0, 400.0, 300.0); double y1 = axis.java2DToValue(75.0, dataArea, RectangleEdge.LEFT); assertEquals(y1, 95.8333333, EPSILON); double y2 = axis.java2DToValue(75.0, dataArea, RectangleEdge.RIGHT); assertEquals(y2, 95.8333333, EPSILON); double x1 = axis.java2DToValue(75.0, dataArea, RectangleEdge.TOP); assertEquals(x1, 58.125, EPSILON); double x2 = axis.java2DToValue(75.0, dataArea, RectangleEdge.BOTTOM); assertEquals(x2, 58.125, EPSILON); axis.setInverted(true); double y3 = axis.java2DToValue(75.0, dataArea, RectangleEdge.LEFT); assertEquals(y3, 54.1666667, EPSILON); double y4 = axis.java2DToValue(75.0, dataArea, RectangleEdge.RIGHT); assertEquals(y4, 54.1666667, EPSILON); double x3 = axis.java2DToValue(75.0, dataArea, RectangleEdge.TOP); assertEquals(x3, 91.875, EPSILON); double x4 = axis.java2DToValue(75.0, dataArea, RectangleEdge.BOTTOM); assertEquals(x4, 91.875, EPSILON); }
/** * Translates a Java2D coordinate into a data value. * * @param java2DValue the Java2D coordinate. * @param area the area. * @param edge the edge. * * @return The Java2D coordinate. */ @Override public double java2DToValue(double java2DValue, Rectangle2D area, RectangleEdge edge) { double result = 0.0; if (this.displayStart < this.displayEnd) { // regular number axis result = super.java2DToValue(java2DValue, area, edge); } else { // displayStart > displayEnd, need to handle split } return result; }
/** * Draws the title on a Java 2D graphics device (such as the screen or a * printer). * * @param g2 the graphics device. * @param area the area allocated for the title. */ @Override public void draw(Graphics2D g2, Rectangle2D area) { RectangleEdge position = getPosition(); if (position == RectangleEdge.TOP || position == RectangleEdge.BOTTOM) { drawHorizontal(g2, area); } else if (position == RectangleEdge.LEFT || position == RectangleEdge.RIGHT) { drawVertical(g2, area); } else { throw new RuntimeException("Invalid title position."); } }
/** * 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)); } }
/** * Draws the axis on a Java 2D graphics device (such as the screen or a * printer). * * @param g2 the graphics device ({@code null} not permitted). * @param cursor the cursor location. * @param plotArea the area within which the axis should be drawn * ({@code null} not permitted). * @param dataArea the area within which the plot is being drawn * ({@code null} not permitted). * @param edge the location of the axis ({@code null} not permitted). * @param plotState collects information about the plot * ({@code null} permitted). * * @return The axis state (never {@code null}). */ @Override public AxisState draw(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge, PlotRenderingInfo plotState) { // if the axis is not visible, don't draw it... if (!isVisible()) { return new AxisState(cursor); } if (isAxisLineVisible()) { drawAxisLine(g2, cursor, dataArea, edge); } AxisState state = new AxisState(cursor); if (isTickMarksVisible()) { drawTickMarks(g2, cursor, dataArea, edge, state); } createAndAddEntity(cursor, state, dataArea, edge, plotState); // draw the category labels and axis label state = drawCategoryLabels(g2, plotArea, dataArea, edge, state, plotState); if (getAttributedLabel() != null) { state = drawAttributedLabel(getAttributedLabel(), g2, plotArea, dataArea, edge, state); } else { state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state); } return state; }
/** * Draws the axis on a Java 2D graphics device (such as the screen or a * printer). * * @param g2 the graphics device ({@code null} not permitted). * @param cursor the cursor location (determines where to draw the axis). * @param plotArea the area within which the axes and plot should be drawn. * @param dataArea the area within which the data should be drawn. * @param edge the axis location ({@code null} not permitted). * @param plotState collects information about the plot ({@code null} * permitted). * * @return The axis state (never {@code null}). */ @Override public AxisState draw(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge, PlotRenderingInfo plotState) { AxisState state; // if the axis is not visible, don't draw it... if (!isVisible()) { state = new AxisState(cursor); // even though the axis is not visible, we need ticks for the // gridlines... List ticks = refreshTicks(g2, state, dataArea, edge); state.setTicks(ticks); return state; } state = drawTickMarksAndLabels(g2, cursor, plotArea, dataArea, edge); if (getAttributedLabel() != null) { state = drawAttributedLabel(getAttributedLabel(), g2, plotArea, dataArea, edge, state); } else { state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state); } createAndAddEntity(cursor, state, dataArea, edge, plotState); return state; }
/** * Draws the axis on a Java 2D graphics device (such as the screen or a * printer). * * @param g2 the graphics device ({@code null} not permitted). * @param cursor the cursor location. * @param plotArea the area within which the axis should be drawn * ({@code null} not permitted). * @param dataArea the area within which the plot is being drawn * ({@code null} not permitted). * @param edge the location of the axis ({@code null} not permitted). * @param plotState collects information about the plot * ({@code null} permitted). * * @return The axis state (never {@code null}). */ @Override public AxisState draw(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge, PlotRenderingInfo plotState) { // if the axis is not visible, don't draw it... if (!isVisible()) { return new AxisState(cursor); } if (isAxisLineVisible()) { drawAxisLine(g2, cursor, dataArea, edge); } // draw the category labels and axis label AxisState state = new AxisState(cursor); state = drawSubCategoryLabels(g2, plotArea, dataArea, edge, state, plotState); state = drawCategoryLabels(g2, plotArea, dataArea, edge, state, plotState); if (getAttributedLabel() != null) { state = drawAttributedLabel(getAttributedLabel(), g2, plotArea, dataArea, edge, state); } else { state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state); } return state; }
/** * Draws a the title horizontally within the specified area. This method * will be called from the {@link #draw(Graphics2D, Rectangle2D) draw} * method. * * @param g2 the graphics device. * @param area the area for the title. */ protected void drawHorizontal(Graphics2D g2, Rectangle2D area) { Rectangle2D titleArea = (Rectangle2D) area.clone(); g2.setFont(this.font); g2.setPaint(this.paint); TextBlockAnchor anchor = null; float x = 0.0f; HorizontalAlignment horizontalAlignment = getHorizontalAlignment(); if (horizontalAlignment == HorizontalAlignment.LEFT) { x = (float) titleArea.getX(); anchor = TextBlockAnchor.TOP_LEFT; } else if (horizontalAlignment == HorizontalAlignment.RIGHT) { x = (float) titleArea.getMaxX(); anchor = TextBlockAnchor.TOP_RIGHT; } else if (horizontalAlignment == HorizontalAlignment.CENTER) { x = (float) titleArea.getCenterX(); anchor = TextBlockAnchor.TOP_CENTER; } float y = 0.0f; RectangleEdge position = getPosition(); if (position == RectangleEdge.TOP) { y = (float) titleArea.getY(); } else if (position == RectangleEdge.BOTTOM) { y = (float) titleArea.getMaxY(); if (horizontalAlignment == HorizontalAlignment.LEFT) { anchor = TextBlockAnchor.BOTTOM_LEFT; } else if (horizontalAlignment == HorizontalAlignment.CENTER) { anchor = TextBlockAnchor.BOTTOM_CENTER; } else if (horizontalAlignment == HorizontalAlignment.RIGHT) { anchor = TextBlockAnchor.BOTTOM_RIGHT; } } this.content.draw(g2, x, y, anchor); }
/** * Draws a the title vertically within the specified area. This method * will be called from the {@link #draw(Graphics2D, Rectangle2D) draw} * method. * * @param g2 the graphics device. * @param area the area for the title. */ protected void drawVertical(Graphics2D g2, Rectangle2D area) { Rectangle2D titleArea = (Rectangle2D) area.clone(); g2.setFont(this.font); g2.setPaint(this.paint); TextBlockAnchor anchor = null; float y = 0.0f; VerticalAlignment verticalAlignment = getVerticalAlignment(); if (verticalAlignment == VerticalAlignment.TOP) { y = (float) titleArea.getY(); anchor = TextBlockAnchor.TOP_RIGHT; } else if (verticalAlignment == VerticalAlignment.BOTTOM) { y = (float) titleArea.getMaxY(); anchor = TextBlockAnchor.TOP_LEFT; } else if (verticalAlignment == VerticalAlignment.CENTER) { y = (float) titleArea.getCenterY(); anchor = TextBlockAnchor.TOP_CENTER; } float x = 0.0f; RectangleEdge position = getPosition(); if (position == RectangleEdge.LEFT) { x = (float) titleArea.getX(); } else if (position == RectangleEdge.RIGHT) { x = (float) titleArea.getMaxX(); if (verticalAlignment == VerticalAlignment.TOP) { anchor = TextBlockAnchor.BOTTOM_RIGHT; } else if (verticalAlignment == VerticalAlignment.CENTER) { anchor = TextBlockAnchor.BOTTOM_CENTER; } else if (verticalAlignment == VerticalAlignment.BOTTOM) { anchor = TextBlockAnchor.BOTTOM_LEFT; } } this.content.draw(g2, x, y, anchor, x, y, -Math.PI / 2.0); }
/** * 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 data 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 ticks = null; if (RectangleEdge.isTopOrBottom(edge)) { ticks = refreshTicksHorizontal(g2, dataArea, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { ticks = refreshTicksVertical(g2, dataArea, edge); } return ticks; }
/** * Initialises the renderer then returns the number of 'passes' through the * data that the renderer will require (usually just one). This method * will be called before the first item is rendered, giving the renderer * an opportunity to initialise any state information it wants to maintain. * The renderer can do nothing if it chooses. * * @param g2 the graphics device. * @param dataArea the area inside the axes. * @param plot the plot. * @param dataset the data. * @param info an optional info collection object to return data back to * the caller. * * @return The number of passes the renderer requires. */ @Override public XYItemRendererState initialise(Graphics2D g2, Rectangle2D dataArea, XYPlot plot, XYDataset dataset, PlotRenderingInfo info) { // calculate the maximum allowed candle width from the axis... ValueAxis axis = plot.getDomainAxis(); double x1 = axis.getLowerBound(); double x2 = x1 + this.maxCandleWidthInMilliseconds; RectangleEdge edge = plot.getDomainAxisEdge(); double xx1 = axis.valueToJava2D(x1, dataArea, edge); double xx2 = axis.valueToJava2D(x2, dataArea, edge); this.maxCandleWidth = Math.abs(xx2 - xx1); // Absolute value, since the relative x // positions are reversed for horizontal orientation // calculate the highest volume in the dataset... if (this.drawVolume) { OHLCDataset highLowDataset = (OHLCDataset) dataset; this.maxVolume = 0.0; for (int series = 0; series < highLowDataset.getSeriesCount(); series++) { for (int item = 0; item < highLowDataset.getItemCount(series); item++) { double volume = highLowDataset.getVolumeValue(series, item); if (volume > this.maxVolume) { this.maxVolume = volume; } } } } return new XYItemRendererState(info); }
private void checkPointsToJava2D(RectangleEdge edge, Rectangle2D plotArea) { assertEquals("Left most point on the axis should be beginning of " + "range.", plotArea.getX(), this.axis.valueToJava2D( this.axis.getLowerBound(), plotArea, edge), EPSILON); assertEquals("Right most point on the axis should be end of range.", plotArea.getX() + plotArea.getWidth(), this.axis.valueToJava2D(this.axis.getUpperBound(), plotArea, edge), EPSILON); assertEquals("Center point on the axis should geometric mean of the bounds.", plotArea.getX() + (plotArea.getWidth() / 2), this.axis.valueToJava2D(Math.sqrt(this.axis.getLowerBound() * this.axis.getUpperBound()), plotArea, edge), EPSILON); }