?? pieplot.java
字號:
* @param generator the generator (<code>null</code> not permitted).
*/
public void setLegendLabelGenerator(PieSectionLabelGenerator generator) {
if (generator == null) {
throw new IllegalArgumentException("Null 'generator' argument.");
}
this.legendLabelGenerator = generator;
notifyListeners(new PlotChangeEvent(this));
}
/**
* Initialises the drawing procedure. This method will be called before
* the first item is rendered, giving the plot an opportunity to initialise
* any state information it wants to maintain.
*
* @param g2 the graphics device.
* @param plotArea the plot area (<code>null</code> not permitted).
* @param plot the plot.
* @param index the secondary index (<code>null</code> for primary
* renderer).
* @param info collects chart rendering information for return to caller.
*
* @return A state object (maintains state information relevant to one
* chart drawing).
*/
public PiePlotState initialise(Graphics2D g2, Rectangle2D plotArea,
PiePlot plot, Integer index, PlotRenderingInfo info) {
PiePlotState state = new PiePlotState(info);
state.setPassesRequired(2);
state.setTotal(DatasetUtilities.calculatePieDatasetTotal(
plot.getDataset()));
state.setLatestAngle(plot.getStartAngle());
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
* (<code>null</code> permitted).
*/
public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
PlotState parentState, PlotRenderingInfo info) {
// adjust for insets...
RectangleInsets insets = getInsets();
insets.trim(area);
if (info != null) {
info.setPlotArea(area);
info.setDataArea(area);
}
drawBackground(g2, area);
drawOutline(g2, area);
Shape savedClip = g2.getClip();
g2.clip(area);
Composite originalComposite = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
getForegroundAlpha()));
if (!DatasetUtilities.isEmptyOrNull(this.dataset)) {
drawPie(g2, area, info);
}
else {
drawNoDataMessage(g2, area);
}
g2.setClip(savedClip);
g2.setComposite(originalComposite);
drawOutline(g2, area);
}
/**
* Draws the pie.
*
* @param g2 the graphics device.
* @param plotArea the plot area.
* @param info chart rendering info.
*/
protected void drawPie(Graphics2D g2, Rectangle2D plotArea,
PlotRenderingInfo info) {
PiePlotState state = initialise(g2, plotArea, this, null, info);
// adjust the plot area for interior spacing and labels...
double labelWidth = 0.0;
if (this.labelGenerator != null) {
labelWidth = this.labelGap + this.maximumLabelWidth
+ this.labelLinkMargin;
}
double gapHorizontal
= plotArea.getWidth() * (this.interiorGap + labelWidth);
double gapVertical = plotArea.getHeight() * this.interiorGap;
double linkX = plotArea.getX() + gapHorizontal / 2;
double linkY = plotArea.getY() + gapVertical / 2;
double linkW = plotArea.getWidth() - gapHorizontal;
double linkH = plotArea.getHeight() - gapVertical;
// make the link area a square if the pie chart is to be circular...
if (this.circular) {
double min = Math.min(linkW, linkH) / 2;
linkX = (linkX + linkX + linkW) / 2 - min;
linkY = (linkY + linkY + linkH) / 2 - min;
linkW = 2 * min;
linkH = 2 * min;
}
// the link area defines the dog leg points for the linking lines to
// the labels
Rectangle2D linkArea = new Rectangle2D.Double(linkX, linkY, linkW,
linkH);
state.setLinkArea(linkArea);
// the explode area defines the max circle/ellipse for the exploded
// pie sections. it is defined by shrinking the linkArea by the
// linkMargin factor.
double hh = linkArea.getWidth() * this.labelLinkMargin;
double vv = linkArea.getHeight() * this.labelLinkMargin;
Rectangle2D explodeArea = new Rectangle2D.Double(linkX + hh / 2.0,
linkY + vv / 2.0, linkW - hh, linkH - vv);
state.setExplodedPieArea(explodeArea);
// the pie area defines the circle/ellipse for regular pie sections.
// it is defined by shrinking the explodeArea by the explodeMargin
// factor.
double maximumExplodePercent = getMaximumExplodePercent();
double percent = maximumExplodePercent / (1.0 + maximumExplodePercent);
double h1 = explodeArea.getWidth() * percent;
double v1 = explodeArea.getHeight() * percent;
Rectangle2D pieArea = new Rectangle2D.Double(explodeArea.getX()
+ h1 / 2.0, explodeArea.getY() + v1 / 2.0,
explodeArea.getWidth() - h1, explodeArea.getHeight() - v1);
state.setPieArea(pieArea);
state.setPieCenterX(pieArea.getCenterX());
state.setPieCenterY(pieArea.getCenterY());
state.setPieWRadius(pieArea.getWidth() / 2.0);
state.setPieHRadius(pieArea.getHeight() / 2.0);
// plot the data (unless the dataset is null)...
if ((this.dataset != null) && (this.dataset.getKeys().size() > 0)) {
List keys = this.dataset.getKeys();
double totalValue
= DatasetUtilities.calculatePieDatasetTotal(this.dataset);
int passesRequired = state.getPassesRequired();
for (int pass = 0; pass < passesRequired; pass++) {
double runningTotal = 0.0;
for (int section = 0; section < keys.size(); section++) {
Number n = this.dataset.getValue(section);
if (n != null) {
double value = n.doubleValue();
if (value > 0.0) {
runningTotal += value;
drawItem(g2, section, explodeArea, state, pass);
}
}
}
}
drawLabels(g2, keys, totalValue, plotArea, linkArea, state);
}
else {
drawNoDataMessage(g2, plotArea);
}
}
/**
* 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) {
Number n = this.dataset.getValue(section);
if (n == null) {
return;
}
double value = n.doubleValue();
double angle1 = 0.0;
double angle2 = 0.0;
if (this.direction == Rotation.CLOCKWISE) {
angle1 = state.getLatestAngle();
angle2 = angle1 - value / state.getTotal() * 360.0;
}
else if (this.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.PIE);
if (currentPass == 0) {
if (this.shadowPaint != null) {
Shape shadowArc = ShapeUtilities.createTranslatedShape(
arc, (float) this.shadowXOffset,
(float) this.shadowYOffset);
g2.setPaint(this.shadowPaint);
g2.fill(shadowArc);
}
}
else if (currentPass == 1) {
Paint paint = getSectionPaint(section);
g2.setPaint(paint);
g2.fill(arc);
Paint outlinePaint = getSectionOutlinePaint(section);
Stroke outlineStroke = getSectionOutlineStroke(section);
if (this.sectionOutlinesVisible) {
g2.setPaint(outlinePaint);
g2.setStroke(outlineStroke);
g2.draw(arc);
}
// update the linking line target for later
// add an entity for the pie section
if (state.getInfo() != null) {
EntityCollection entities = state.getEntityCollection();
if (entities != null) {
Comparable key = this.dataset.getKey(section);
String tip = null;
if (this.toolTipGenerator != null) {
tip = this.toolTipGenerator.generateToolTip(
this.dataset, key);
}
String url = null;
if (this.urlGenerator != null) {
url = this.urlGenerator.generateURL(this.dataset,
key, this.pieIndex);
}
PieSectionEntity entity = new PieSectionEntity(
arc, this.dataset, this.pieIndex, section, key,
tip, url);
entities.add(entity);
}
}
}
}
state.setLatestAngle(angle2);
}
/**
* Draws the labels for the pie sections.
*
* @param g2 the graphics device.
* @param keys the keys.
* @param totalValue the total value.
* @param plotArea the plot area.
* @param linkArea the link area.
* @param state the state.
*/
protected void drawLabels(Graphics2D g2, List keys, double totalValue,
Rectangle2D plotArea, Rectangle2D linkArea,
PiePlotState state) {
Composite originalComposite = g2.getComposite();
g2.setComposite(
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
// classify the keys according to which side the label will appear...
DefaultKeyedValues leftKeys = new DefaultKeyedValues();
DefaultKeyedValues rightKeys = new DefaultKeyedValues();
double runningTotal1 = 0.0;
Iterator iterator1 = keys.iterator();
while (iterator1.hasNext()) {
Comparable key = (Comparable) iterator1.next();
boolean include = true;
double v = 0.0;
Number n = this.dataset.getValue(key);
if (n == null) {
include = !this.ignoreNullValues;
}
else {
v = n.doubleValue();
include = this.ignoreZeroValues ? v > 0.0 : v >= 0.0;
}
if (include) {
runningTotal1 = runningTotal1 + v;
// work out the mid angle (0 - 90 and 270 - 360) = right,
// otherwise left
double mid = this.startAngle + (this.direction.getFactor()
* ((runningTotal1 - v / 2.0) * 360) / totalValue);
if (Math.cos(Math.toRadians(mid)) < 0.0) {
leftKeys.addValue(key, new Double(mid));
}
else {
rightKeys.addValue(key, new Double(mid));
}
}
}
g2.setFont(getLabelFont());
float maxLabelWidth
= (float) (getMaximumLabelWidth() * plotArea.getWidth());
// draw the labels...
if (this.labelGenerator != null) {
drawLeftLabels(leftKeys, g2, plotArea, linkArea, maxLabelWidth,
state);
drawRightLabels(rightKeys, g2, plotArea, linkArea, maxLabelWidth,
state);
}
g2.setComposite(originalComposite);
}
/**
* Draws the left labels.
*
* @param leftKeys the keys.
* @param g2 the graphics device.
* @param plotArea the plot area.
* @param linkArea the link area.
* @param maxLabelWidth the maximum label width.
* @param state the state.
*/
protected void drawLeftLabels(KeyedValues leftKeys, Graphics2D g2,
Rectangle2D plotArea, Rectangle2D linkArea,
float maxLabelWidth, PiePlotState state) {
PieLabelDistributor distributor1 = new PieLabelDistributor(
leftKeys.getItemCount()
);
double lGap = plotArea.getWidth() * this.labelGap;
double verticalLinkRadius = state.getLinkArea().getHeight() / 2.0;
for (int i = 0; i < leftKeys.getItemCount(); i++) {
String label = this.labelGenerator.generateSectionLabel(
this.d
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -