/** * Estimates the maximum tick label height. * * @param g2 the graphics device. * @return The maximum height. * @since 1.0.7 */ protected double estimateMaximumTickLabelHeight(Graphics2D g2) { RectangleInsets tickLabelInsets = getTickLabelInsets(); double result = tickLabelInsets.getTop() + tickLabelInsets.getBottom(); Font tickLabelFont = getTickLabelFont(); FontRenderContext frc = g2.getFontRenderContext(); result += tickLabelFont.getLineMetrics("123", frc).getHeight(); return result; }
public static Object getPropertyValue(Object id, RectangleInsets ri, String preID) { if (ri == null) ri = PadUtil.RECTANGLE_INSETS; if (id.equals(preID + PadUtil.PADDING_TOP)) return ri.getTop(); if (id.equals(preID + PadUtil.PADDING_BOTTOM)) return ri.getBottom(); if (id.equals(preID + PadUtil.PADDING_LEFT)) return ri.getLeft(); if (id.equals(preID + PadUtil.PADDING_RIGHT)) return ri.getRight(); return null; }
protected void configureChart(JFreeChart jfreeChart, JRChartPlot jrPlot) throws JRException { super.configureChart(jfreeChart, jrPlot); TextTitle title = jfreeChart.getTitle(); if (title != null) { RectangleInsets padding = title.getPadding(); double bottomPadding = Math.max(padding.getBottom(), 15d); title.setPadding(padding.getTop(), padding.getLeft(), bottomPadding, padding.getRight()); } }
/** * Draws the plot on a Java 2D graphics device (such as the screen or a * printer). Will perform all the placement calculations for each * sub-plots and then tell these to draw themselves. * * @param g2 the graphics device. * @param area the area within which the plot (including axis labels) * should be drawn. * @param anchor the anchor point (<code>null</code> permitted). * @param parentState the parent state. * @param info collects information about the drawing (<code>null</code> * permitted). */ public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { // set up info collection... if (info != null) { info.setPlotArea(area); } // adjust the drawing area for plot insets (if any)... RectangleInsets insets = getInsets(); insets.trim(area); // calculate the data area... AxisSpace space = calculateAxisSpace(g2, area); Rectangle2D dataArea = space.shrink(area, null); // set the width and height of non-shared axis of all sub-plots setFixedDomainAxisSpaceForSubplots(space); // draw the shared axis ValueAxis axis = getRangeAxis(); RectangleEdge rangeEdge = getRangeAxisEdge(); double cursor = RectangleEdge.coordinate(dataArea, rangeEdge); AxisState state = axis.draw(g2, cursor, area, dataArea, rangeEdge, info); if (parentState == null) { parentState = new PlotState(); } parentState.getSharedAxisStates().put(axis, state); // draw all the charts for (int i = 0; i < this.subplots.size(); i++) { CategoryPlot plot = (CategoryPlot) this.subplots.get(i); PlotRenderingInfo subplotInfo = null; if (info != null) { subplotInfo = new PlotRenderingInfo(info.getOwner()); info.addSubplotInfo(subplotInfo); } Point2D subAnchor = null; if (anchor != null && this.subplotArea[i].contains(anchor)) { subAnchor = anchor; } plot.draw(g2, this.subplotArea[i], subAnchor, parentState, subplotInfo); } if (info != null) { info.setDataArea(dataArea); } }
/** * Sets the insets for the axis label, and sends an {@link AxisChangeEvent} to all registered * listeners. * * @param insets the insets (<code>null</code> not permitted). * @param notify notify listeners? * @since 1.0.10 */ public void setLabelInsets(RectangleInsets insets, boolean notify) { ParamChecks.nullNotPermitted(insets, "insets"); if (!insets.equals(this.labelInsets)) { this.labelInsets = insets; if (notify) { fireChangeEvent(); } } }
/** * Calculates the (x, y) coordinates for drawing a marker label. * * @param g2 the graphics device. * @param orientation the plot orientation. * @param dataArea the data area. * @param markerArea the rectangle surrounding the marker. * @param markerOffset the marker offset. * @param labelOffsetType the label offset type. * @param anchor the label anchor. * @return The coordinates for drawing the marker label. */ private Point2D calculateRangeMarkerTextAnchorPoint( Graphics2D g2, PlotOrientation orientation, Rectangle2D dataArea, Rectangle2D markerArea, RectangleInsets markerOffset, LengthAdjustmentType labelOffsetType, RectangleAnchor anchor) { Rectangle2D anchorRect = null; if (orientation == PlotOrientation.HORIZONTAL) { anchorRect = markerOffset.createAdjustedRectangle( markerArea, labelOffsetType, LengthAdjustmentType.CONTRACT); } else if (orientation == PlotOrientation.VERTICAL) { anchorRect = markerOffset.createAdjustedRectangle( markerArea, LengthAdjustmentType.CONTRACT, labelOffsetType); } return RectangleAnchor.coordinates(anchorRect, anchor); }
/** * Returns a rectangle that encloses the axis label. This is typically used for layout purposes * (it gives the maximum dimensions of the label). * * @param g2 the graphics device. * @param edge the edge of the plot area along which the axis is measuring. * @return The enclosing rectangle. */ protected Rectangle2D getLabelEnclosure(Graphics2D g2, RectangleEdge edge) { Rectangle2D result = new Rectangle2D.Double(); String axisLabel = getLabel(); if (axisLabel != null && !axisLabel.equals("")) { FontMetrics fm = g2.getFontMetrics(getLabelFont()); Rectangle2D bounds = TextUtilities.getTextBounds(axisLabel, g2, fm); RectangleInsets insets = getLabelInsets(); bounds = insets.createOutsetRectangle(bounds); double angle = getLabelAngle(); if (edge == RectangleEdge.LEFT || edge == RectangleEdge.RIGHT) { angle = angle - Math.PI / 2.0; } double x = bounds.getCenterX(); double y = bounds.getCenterY(); AffineTransform transformer = AffineTransform.getRotateInstance(angle, x, y); Shape labelBounds = transformer.createTransformedShape(bounds); result = labelBounds.getBounds2D(); } return result; }
/** * Draws the wafermap view. * * @param g2 the graphics device. * @param area the plot area. * @param anchor the anchor point (<code>null</code> permitted). * @param state the plot state. * @param info the plot rendering info. */ @Override public void draw( Graphics2D g2, Rectangle2D area, Point2D anchor, PlotState state, PlotRenderingInfo info) { // if the plot area is too small, just return... boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW); boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW); if (b1 || b2) { return; } // record the plot area... if (info != null) { info.setPlotArea(area); } // adjust the drawing area for the plot insets (if any)... RectangleInsets insets = getInsets(); insets.trim(area); dataset.drawChipGrid(g2, area, renderer, this); drawWaferEdge(g2, area); }
protected double estimateMaximumTickLabelWidth(Graphics2D g2, TickUnit unit) { RectangleInsets tickLabelInsets = getTickLabelInsets(); double result = tickLabelInsets.getLeft() + tickLabelInsets.getRight(); if (isVerticalTickLabels()) { FontRenderContext frc = g2.getFontRenderContext(); return result + ((double) getTickLabelFont().getLineMetrics("0", frc).getHeight()); } String lowerStr; String upperStr; FontMetrics fm = g2.getFontMetrics(getTickLabelFont()); Range range = getRange(); double lower = range.getLowerBound(); double upper = range.getUpperBound(); NumberFormat formatter = getNumberFormatOverride(); if (formatter != null) { lowerStr = formatter.format(lower); upperStr = formatter.format(upper); } else { lowerStr = unit.valueToString(lower); upperStr = unit.valueToString(upper); } return result + Math.max((double) fm.stringWidth(lowerStr), (double) fm.stringWidth(upperStr)); }
/** * Draws the axis label. * * @param label the label text. * @param g2 the graphics device. * @param plotArea the plot area. * @param dataArea the area inside the axes. * @param edge the location of the axis. * @param state the axis state (<code>null</code> not permitted). * @return Information about the axis. */ protected AxisState drawLabel( String label, Graphics2D g2, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge, AxisState state) { // it is unlikely that 'state' will be null, but check anyway... ParamChecks.nullNotPermitted(state, "state"); if ((label == null) || (label.equals(""))) { return state; } Font font = getLabelFont(); RectangleInsets insets = getLabelInsets(); g2.setFont(font); g2.setPaint(getLabelPaint()); FontMetrics fm = g2.getFontMetrics(); Rectangle2D labelBounds = TextUtilities.getTextBounds(label, g2, fm); if (edge == RectangleEdge.TOP) { AffineTransform t = AffineTransform.getRotateInstance( getLabelAngle(), labelBounds.getCenterX(), labelBounds.getCenterY()); Shape rotatedLabelBounds = t.createTransformedShape(labelBounds); labelBounds = rotatedLabelBounds.getBounds2D(); double labelx = dataArea.getCenterX(); double labely = state.getCursor() - insets.getBottom() - labelBounds.getHeight() / 2.0; TextUtilities.drawRotatedString( label, g2, (float) labelx, (float) labely, TextAnchor.CENTER, getLabelAngle(), TextAnchor.CENTER); state.cursorUp(insets.getTop() + labelBounds.getHeight() + insets.getBottom()); } else if (edge == RectangleEdge.BOTTOM) { AffineTransform t = AffineTransform.getRotateInstance( getLabelAngle(), labelBounds.getCenterX(), labelBounds.getCenterY()); Shape rotatedLabelBounds = t.createTransformedShape(labelBounds); labelBounds = rotatedLabelBounds.getBounds2D(); double labelx = dataArea.getCenterX(); double labely = state.getCursor() + insets.getTop() + labelBounds.getHeight() / 2.0; TextUtilities.drawRotatedString( label, g2, (float) labelx, (float) labely, TextAnchor.CENTER, getLabelAngle(), TextAnchor.CENTER); state.cursorDown(insets.getTop() + labelBounds.getHeight() + insets.getBottom()); } else if (edge == RectangleEdge.LEFT) { AffineTransform t = AffineTransform.getRotateInstance( getLabelAngle() - Math.PI / 2.0, labelBounds.getCenterX(), labelBounds.getCenterY()); Shape rotatedLabelBounds = t.createTransformedShape(labelBounds); labelBounds = rotatedLabelBounds.getBounds2D(); double labelx = state.getCursor() - insets.getRight() - labelBounds.getWidth() / 2.0; double labely = dataArea.getCenterY(); TextUtilities.drawRotatedString( label, g2, (float) labelx, (float) labely, TextAnchor.CENTER, getLabelAngle() - Math.PI / 2.0, TextAnchor.CENTER); state.cursorLeft(insets.getLeft() + labelBounds.getWidth() + insets.getRight()); } else if (edge == RectangleEdge.RIGHT) { AffineTransform t = AffineTransform.getRotateInstance( getLabelAngle() + Math.PI / 2.0, labelBounds.getCenterX(), labelBounds.getCenterY()); Shape rotatedLabelBounds = t.createTransformedShape(labelBounds); labelBounds = rotatedLabelBounds.getBounds2D(); double labelx = state.getCursor() + insets.getLeft() + labelBounds.getWidth() / 2.0; double labely = dataArea.getY() + dataArea.getHeight() / 2.0; TextUtilities.drawRotatedString( label, g2, (float) labelx, (float) labely, TextAnchor.CENTER, getLabelAngle() + Math.PI / 2.0, TextAnchor.CENTER); state.cursorRight(insets.getLeft() + labelBounds.getWidth() + insets.getRight()); } return state; }
/** * Draws the plot on a Java 2D graphics device (such as the screen or a printer). * * @param g2 the graphics device. * @param area the area within which the plot should be drawn. * @param anchor the anchor point (<code>null</code> permitted). * @param parentState the state from the parent plot, if there is one. * @param info collects info about the drawing. */ public void draw( Graphics2D g2, Rectangle2D area, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { // adjust the drawing area for the plot insets (if any)... RectangleInsets insets = getInsets(); insets.trim(area); drawBackground(g2, area); drawOutline(g2, area); // check that there is some data to display... if (DatasetUtilities.isEmptyOrNull(getDataset())) { drawNoDataMessage(g2, area); return; } int pieCount = 0; if (getDataExtractOrder() == TableOrder.BY_ROW) { pieCount = getDataset().getRowCount(); } else { pieCount = getDataset().getColumnCount(); } // the columns variable is always >= rows int displayCols = (int) Math.ceil(Math.sqrt(pieCount)); int displayRows = (int) Math.ceil((double) pieCount / (double) displayCols); // swap rows and columns to match plotArea shape if (displayCols > displayRows && area.getWidth() < area.getHeight()) { int temp = displayCols; displayCols = displayRows; displayRows = temp; } prefetchSectionPaints(); int x = (int) area.getX(); int y = (int) area.getY(); int width = ((int) area.getWidth()) / displayCols; int height = ((int) area.getHeight()) / displayRows; int row = 0; int column = 0; int diff = (displayRows * displayCols) - pieCount; int xoffset = 0; Rectangle rect = new Rectangle(); for (int pieIndex = 0; pieIndex < pieCount; pieIndex++) { rect.setBounds(x + xoffset + (width * column), y + (height * row), width, height); String title = null; if (getDataExtractOrder() == TableOrder.BY_ROW) { title = getDataset().getRowKey(pieIndex).toString(); } else { title = getDataset().getColumnKey(pieIndex).toString(); } getPieChart().setTitle(title); PieDataset piedataset = null; PieDataset dd = new CategoryToPieDataset(getDataset(), getDataExtractOrder(), pieIndex); if (getLimit() > 0.0) { piedataset = DatasetUtilities.createConsolidatedPieDataset(dd, getAggregatedItemsKey(), getLimit()); } else { piedataset = dd; } PiePlot piePlot = (PiePlot) getPieChart().getPlot(); piePlot.setDataset(piedataset); piePlot.setPieIndex(pieIndex); // update the section colors to match the global colors... for (int i = 0; i < piedataset.getItemCount(); i++) { Comparable key = piedataset.getKey(i); Paint p; if (key.equals(getAggregatedItemsKey())) { p = getAggregatedItemsPaint(); } else { p = (Paint) this.sectionPaints.get(key); } piePlot.setSectionPaint(key, p); } ChartRenderingInfo subinfo = null; if (info != null) { subinfo = new ChartRenderingInfo(); } getPieChart().draw(g2, rect, subinfo); if (info != null) { info.getOwner().getEntityCollection().addAll(subinfo.getEntityCollection()); info.addSubplotInfo(subinfo.getPlotInfo()); } ++column; if (column == displayCols) { column = 0; ++row; if (row == displayRows - 1 && diff != 0) { xoffset = (diff * width) / 2; } } } }
/** * Draws a single data item. * * @param g2 the graphics device (<code>null</code> not permitted). * @param section the section index. * @param dataArea the data plot area. * @param state state information for one chart. * @param currentPass the current pass index. */ protected void drawItem( Graphics2D g2, int section, Rectangle2D dataArea, PiePlotState state, int currentPass) { PieDataset dataset = getDataset(); Number n = dataset.getValue(section); if (n == null) { return; } double value = n.doubleValue(); double angle1 = 0.0; double angle2 = 0.0; Rotation direction = getDirection(); if (direction == Rotation.CLOCKWISE) { angle1 = state.getLatestAngle(); angle2 = angle1 - value / state.getTotal() * 360.0; } else if (direction == Rotation.ANTICLOCKWISE) { angle1 = state.getLatestAngle(); angle2 = angle1 + value / state.getTotal() * 360.0; } else { throw new IllegalStateException("Rotation type not recognised."); } double angle = (angle2 - angle1); if (Math.abs(angle) > getMinimumArcAngleToDraw()) { double ep = 0.0; double mep = getMaximumExplodePercent(); if (mep > 0.0) { ep = getExplodePercent(section) / mep; } Rectangle2D arcBounds = getArcBounds(state.getPieArea(), state.getExplodedPieArea(), angle1, angle, ep); Arc2D.Double arc = new Arc2D.Double(arcBounds, angle1, angle, Arc2D.OPEN); // create the bounds for the inner arc RectangleInsets s = new RectangleInsets( UnitType.RELATIVE, sectionDepth, sectionDepth, sectionDepth, sectionDepth); Rectangle2D innerArcBounds = new Rectangle2D.Double(); innerArcBounds.setRect(arcBounds); s.trim(innerArcBounds); // calculate inner arc in reverse direction, for later // GeneralPath construction Arc2D.Double arc2 = new Arc2D.Double(innerArcBounds, angle1 + angle, -angle, Arc2D.OPEN); GeneralPath path = new GeneralPath(); path.moveTo((float) arc.getStartPoint().getX(), (float) arc.getStartPoint().getY()); path.append(arc.getPathIterator(null), false); path.append(arc2.getPathIterator(null), true); path.closePath(); Line2D separator = new Line2D.Double(arc2.getEndPoint(), arc.getStartPoint()); if (currentPass == 0) { Paint shadowPaint = getShadowPaint(); double shadowXOffset = getShadowXOffset(); double shadowYOffset = getShadowYOffset(); if (shadowPaint != null) { Shape shadowArc = ShapeUtilities.createTranslatedShape( path, (float) shadowXOffset, (float) shadowYOffset); g2.setPaint(shadowPaint); g2.fill(shadowArc); } } else if (currentPass == 1) { Paint paint = getSectionPaint(section); g2.setPaint(paint); g2.fill(path); Paint outlinePaint = getSectionOutlinePaint(section); Stroke outlineStroke = getSectionOutlineStroke(section); if (getSectionOutlinesVisible()) { g2.setPaint(outlinePaint); g2.setStroke(outlineStroke); g2.draw(path); } // add an entity for the pie section if (state.getInfo() != null) { EntityCollection entities = state.getEntityCollection(); if (entities != null) { Comparable key = dataset.getKey(section); String tip = null; PieToolTipGenerator toolTipGenerator = getToolTipGenerator(); if (toolTipGenerator != null) { tip = toolTipGenerator.generateToolTip(dataset, key); } String url = null; PieURLGenerator urlGenerator = getURLGenerator(); if (urlGenerator != null) { url = urlGenerator.generateURL(dataset, key, getPieIndex()); } PieSectionEntity entity = new PieSectionEntity(path, dataset, getPieIndex(), section, key, tip, url); entities.add(entity); } } } else if (currentPass == 2) { // if there were 3 passes... if (this.sectionSeparatorsVisible) { Line2D extendedSeparator = extendLine(separator, this.innerSeparatorExtension, this.outerSeparatorExtension); g2.setStroke(this.separatorStroke); g2.setPaint(this.separatorPaint); g2.draw(extendedSeparator); } } } state.setLatestAngle(angle2); }
/** * Draws the plot on a Java 2D graphics device (such as the screen or a printer). * * @param g2 the graphics device. * @param area the area within which the plot should be drawn. * @param anchor the anchor point (<code>null</code> permitted). * @param parentState the state from the parent plot, if there is one. * @param info collects info about the drawing. */ public void draw( Graphics2D g2, Rectangle2D area, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { if (info != null) { info.setPlotArea(area); } // adjust for insets... RectangleInsets insets = getInsets(); insets.trim(area); area.setRect(area.getX() + 4, area.getY() + 4, area.getWidth() - 8, area.getHeight() - 8); // draw the background if (this.drawBorder) { drawBackground(g2, area); } // adjust the plot area by the interior spacing value double gapHorizontal = (2 * DEFAULT_BORDER_SIZE); double gapVertical = (2 * DEFAULT_BORDER_SIZE); double meterX = area.getX() + gapHorizontal / 2; double meterY = area.getY() + gapVertical / 2; double meterW = area.getWidth() - gapHorizontal; double meterH = area.getHeight() - gapVertical + ((this.meterAngle <= 180) && (this.shape != DialShape.CIRCLE) ? area.getHeight() / 1.25 : 0); double min = Math.min(meterW, meterH) / 2; meterX = (meterX + meterX + meterW) / 2 - min; meterY = (meterY + meterY + meterH) / 2 - min; meterW = 2 * min; meterH = 2 * min; Rectangle2D meterArea = new Rectangle2D.Double(meterX, meterY, meterW, meterH); Rectangle2D.Double originalArea = new Rectangle2D.Double( meterArea.getX() - 4, meterArea.getY() - 4, meterArea.getWidth() + 8, meterArea.getHeight() + 8); double meterMiddleX = meterArea.getCenterX(); double meterMiddleY = meterArea.getCenterY(); // plot the data (unless the dataset is null)... ValueDataset data = getDataset(); if (data != null) { double dataMin = this.range.getLowerBound(); double dataMax = this.range.getUpperBound(); Shape savedClip = g2.getClip(); g2.clip(originalArea); Composite originalComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getForegroundAlpha())); if (this.dialBackgroundPaint != null) { fillArc(g2, originalArea, dataMin, dataMax, this.dialBackgroundPaint, true); } drawTicks(g2, meterArea, dataMin, dataMax); drawArcForInterval( g2, meterArea, new MeterInterval("", this.range, this.dialOutlinePaint, new BasicStroke(1.0f), null)); Iterator iterator = this.intervals.iterator(); while (iterator.hasNext()) { MeterInterval interval = (MeterInterval) iterator.next(); drawArcForInterval(g2, meterArea, interval); } Number n = data.getValue(); if (n != null) { double value = n.doubleValue(); drawValueLabel(g2, meterArea); if (this.range.contains(value)) { g2.setPaint(this.needlePaint); g2.setStroke(new BasicStroke(2.0f)); double radius = (meterArea.getWidth() / 2) + DEFAULT_BORDER_SIZE + 15; double valueAngle = valueToAngle(value); double valueP1 = meterMiddleX + (radius * Math.cos(Math.PI * (valueAngle / 180))); double valueP2 = meterMiddleY - (radius * Math.sin(Math.PI * (valueAngle / 180))); Polygon arrow = new Polygon(); if ((valueAngle > 135 && valueAngle < 225) || (valueAngle < 45 && valueAngle > -45)) { double valueP3 = (meterMiddleY - DEFAULT_CIRCLE_SIZE / 4); double valueP4 = (meterMiddleY + DEFAULT_CIRCLE_SIZE / 4); arrow.addPoint((int) meterMiddleX, (int) valueP3); arrow.addPoint((int) meterMiddleX, (int) valueP4); } else { arrow.addPoint((int) (meterMiddleX - DEFAULT_CIRCLE_SIZE / 4), (int) meterMiddleY); arrow.addPoint((int) (meterMiddleX + DEFAULT_CIRCLE_SIZE / 4), (int) meterMiddleY); } arrow.addPoint((int) valueP1, (int) valueP2); g2.fill(arrow); Ellipse2D circle = new Ellipse2D.Double( meterMiddleX - DEFAULT_CIRCLE_SIZE / 2, meterMiddleY - DEFAULT_CIRCLE_SIZE / 2, DEFAULT_CIRCLE_SIZE, DEFAULT_CIRCLE_SIZE); g2.fill(circle); } } g2.setClip(savedClip); g2.setComposite(originalComposite); } if (this.drawBorder) { drawOutline(g2, area); } }
protected double estimateMaximumTickLabelHeight(Graphics2D g2) { RectangleInsets tickLabelInsets = getTickLabelInsets(); return (tickLabelInsets.getTop() + tickLabelInsets.getBottom()) + ((double) getTickLabelFont().getLineMetrics("123", g2.getFontRenderContext()).getHeight()); }
public static RectangleInsets setPropertyValue( Object id, Object value, RectangleInsets ri, String preID) { if (ri == null) ri = PadUtil.RECTANGLE_INSETS; if (id.equals(preID + PadUtil.PADDING_TOP)) return new RectangleInsets((Double) value, ri.getLeft(), ri.getBottom(), ri.getRight()); else if (id.equals(preID + PadUtil.PADDING_BOTTOM)) return new RectangleInsets(ri.getTop(), ri.getLeft(), (Double) value, ri.getRight()); else if (id.equals(preID + PadUtil.PADDING_LEFT)) return new RectangleInsets(ri.getTop(), (Double) value, ri.getBottom(), ri.getRight()); else if (id.equals(preID + PadUtil.PADDING_RIGHT)) return new RectangleInsets(ri.getTop(), ri.getLeft(), ri.getBottom(), (Double) value); return null; }