1:
48:
49: package ;
50:
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63:
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76:
77:
82: public class LineRenderer3D extends LineAndShapeRenderer
83: implements Effect3D, Serializable {
84:
85:
86: private static final long serialVersionUID = 5467931468380928736L;
87:
88:
89: public static final double DEFAULT_X_OFFSET = 12.0;
90:
91:
92: public static final double DEFAULT_Y_OFFSET = 8.0;
93:
94:
95: public static final Paint DEFAULT_WALL_PAINT = new Color(0xDD, 0xDD, 0xDD);
96:
97:
98: private double xOffset;
99:
100:
101: private double yOffset;
102:
103:
104: private transient Paint wallPaint;
105:
106:
109: public LineRenderer3D() {
110: super(true, false);
111: this.xOffset = DEFAULT_X_OFFSET;
112: this.yOffset = DEFAULT_Y_OFFSET;
113: this.wallPaint = DEFAULT_WALL_PAINT;
114: }
115:
116:
121: public double getXOffset() {
122: return this.xOffset;
123: }
124:
125:
130: public double getYOffset() {
131: return this.yOffset;
132: }
133:
134:
139: public void setXOffset(double xOffset) {
140: this.xOffset = xOffset;
141: notifyListeners(new RendererChangeEvent(this));
142: }
143:
144:
149: public void setYOffset(double yOffset) {
150: this.yOffset = yOffset;
151: notifyListeners(new RendererChangeEvent(this));
152: }
153:
154:
160: public Paint getWallPaint() {
161: return this.wallPaint;
162: }
163:
164:
170: public void setWallPaint(Paint paint) {
171: this.wallPaint = paint;
172: notifyListeners(new RendererChangeEvent(this));
173: }
174:
175:
182: public void drawBackground(Graphics2D g2, CategoryPlot plot,
183: Rectangle2D dataArea) {
184:
185: float x0 = (float) dataArea.getX();
186: float x1 = x0 + (float) Math.abs(this.xOffset);
187: float x3 = (float) dataArea.getMaxX();
188: float x2 = x3 - (float) Math.abs(this.xOffset);
189:
190: float y0 = (float) dataArea.getMaxY();
191: float y1 = y0 - (float) Math.abs(this.yOffset);
192: float y3 = (float) dataArea.getMinY();
193: float y2 = y3 + (float) Math.abs(this.yOffset);
194:
195: GeneralPath clip = new GeneralPath();
196: clip.moveTo(x0, y0);
197: clip.lineTo(x0, y2);
198: clip.lineTo(x1, y3);
199: clip.lineTo(x3, y3);
200: clip.lineTo(x3, y1);
201: clip.lineTo(x2, y0);
202: clip.closePath();
203:
204:
205: Paint backgroundPaint = plot.getBackgroundPaint();
206: if (backgroundPaint != null) {
207: g2.setPaint(backgroundPaint);
208: g2.fill(clip);
209: }
210:
211: GeneralPath leftWall = new GeneralPath();
212: leftWall.moveTo(x0, y0);
213: leftWall.lineTo(x0, y2);
214: leftWall.lineTo(x1, y3);
215: leftWall.lineTo(x1, y1);
216: leftWall.closePath();
217: g2.setPaint(getWallPaint());
218: g2.fill(leftWall);
219:
220: GeneralPath bottomWall = new GeneralPath();
221: bottomWall.moveTo(x0, y0);
222: bottomWall.lineTo(x1, y1);
223: bottomWall.lineTo(x3, y1);
224: bottomWall.lineTo(x2, y0);
225: bottomWall.closePath();
226: g2.setPaint(getWallPaint());
227: g2.fill(bottomWall);
228:
229:
230: g2.setPaint(Color.lightGray);
231: Line2D corner = new Line2D.Double(x0, y0, x1, y1);
232: g2.draw(corner);
233: corner.setLine(x1, y1, x1, y3);
234: g2.draw(corner);
235: corner.setLine(x1, y1, x3, y1);
236: g2.draw(corner);
237:
238:
239: Image backgroundImage = plot.getBackgroundImage();
240: if (backgroundImage != null) {
241: Composite originalComposite = g2.getComposite();
242: g2.setComposite(AlphaComposite.getInstance(
243: AlphaComposite.SRC, plot.getBackgroundAlpha()));
244: g2.drawImage(backgroundImage, (int) x1, (int) y3,
245: (int) (x3 - x1 + 1), (int) (y1 - y3 + 1), null);
246: g2.setComposite(originalComposite);
247: }
248:
249: }
250:
251:
258: public void drawOutline(Graphics2D g2, CategoryPlot plot,
259: Rectangle2D dataArea) {
260:
261: float x0 = (float) dataArea.getX();
262: float x1 = x0 + (float) Math.abs(this.xOffset);
263: float x3 = (float) dataArea.getMaxX();
264: float x2 = x3 - (float) Math.abs(this.xOffset);
265:
266: float y0 = (float) dataArea.getMaxY();
267: float y1 = y0 - (float) Math.abs(this.yOffset);
268: float y3 = (float) dataArea.getMinY();
269: float y2 = y3 + (float) Math.abs(this.yOffset);
270:
271: GeneralPath clip = new GeneralPath();
272: clip.moveTo(x0, y0);
273: clip.lineTo(x0, y2);
274: clip.lineTo(x1, y3);
275: clip.lineTo(x3, y3);
276: clip.lineTo(x3, y1);
277: clip.lineTo(x2, y0);
278: clip.closePath();
279:
280:
281: Stroke outlineStroke = plot.getOutlineStroke();
282: Paint outlinePaint = plot.getOutlinePaint();
283: if ((outlineStroke != null) && (outlinePaint != null)) {
284: g2.setStroke(outlineStroke);
285: g2.setPaint(outlinePaint);
286: g2.draw(clip);
287: }
288:
289: }
290:
291:
301: public void drawDomainGridline(Graphics2D g2,
302: CategoryPlot plot,
303: Rectangle2D dataArea,
304: double value) {
305:
306: Line2D line1 = null;
307: Line2D line2 = null;
308: PlotOrientation orientation = plot.getOrientation();
309: if (orientation == PlotOrientation.HORIZONTAL) {
310: double y0 = value;
311: double y1 = value - getYOffset();
312: double x0 = dataArea.getMinX();
313: double x1 = x0 + getXOffset();
314: double x2 = dataArea.getMaxY();
315: line1 = new Line2D.Double(x0, y0, x1, y1);
316: line2 = new Line2D.Double(x1, y1, x2, y1);
317: }
318: else if (orientation == PlotOrientation.VERTICAL) {
319: double x0 = value;
320: double x1 = value + getXOffset();
321: double y0 = dataArea.getMaxY();
322: double y1 = y0 - getYOffset();
323: double y2 = dataArea.getMinY();
324: line1 = new Line2D.Double(x0, y0, x1, y1);
325: line2 = new Line2D.Double(x1, y1, x1, y2);
326: }
327: g2.setPaint(plot.getDomainGridlinePaint());
328: g2.setStroke(plot.getDomainGridlineStroke());
329: g2.draw(line1);
330: g2.draw(line2);
331:
332: }
333:
334:
345: public void drawRangeGridline(Graphics2D g2,
346: CategoryPlot plot,
347: ValueAxis axis,
348: Rectangle2D dataArea,
349: double value) {
350:
351: Range range = axis.getRange();
352:
353: if (!range.contains(value)) {
354: return;
355: }
356:
357: Rectangle2D adjusted = new Rectangle2D.Double(dataArea.getX(),
358: dataArea.getY() + getYOffset(),
359: dataArea.getWidth() - getXOffset(),
360: dataArea.getHeight() - getYOffset());
361:
362: Line2D line1 = null;
363: Line2D line2 = null;
364: PlotOrientation orientation = plot.getOrientation();
365: if (orientation == PlotOrientation.HORIZONTAL) {
366: double x0 = axis.valueToJava2D(value, adjusted,
367: plot.getRangeAxisEdge());
368: double x1 = x0 + getXOffset();
369: double y0 = dataArea.getMaxY();
370: double y1 = y0 - getYOffset();
371: double y2 = dataArea.getMinY();
372: line1 = new Line2D.Double(x0, y0, x1, y1);
373: line2 = new Line2D.Double(x1, y1, x1, y2);
374: }
375: else if (orientation == PlotOrientation.VERTICAL) {
376: double y0 = axis.valueToJava2D(value, adjusted,
377: plot.getRangeAxisEdge());
378: double y1 = y0 - getYOffset();
379: double x0 = dataArea.getMinX();
380: double x1 = x0 + getXOffset();
381: double x2 = dataArea.getMaxX();
382: line1 = new Line2D.Double(x0, y0, x1, y1);
383: line2 = new Line2D.Double(x1, y1, x2, y1);
384: }
385: g2.setPaint(plot.getRangeGridlinePaint());
386: g2.setStroke(plot.getRangeGridlineStroke());
387: g2.draw(line1);
388: g2.draw(line2);
389:
390: }
391:
392:
401: public void drawRangeMarker(Graphics2D g2,
402: CategoryPlot plot,
403: ValueAxis axis,
404: Marker marker,
405: Rectangle2D dataArea) {
406:
407: if (marker instanceof ValueMarker) {
408: ValueMarker vm = (ValueMarker) marker;
409: double value = vm.getValue();
410: Range range = axis.getRange();
411: if (!range.contains(value)) {
412: return;
413: }
414:
415: Rectangle2D adjusted = new Rectangle2D.Double(dataArea.getX(),
416: dataArea.getY() + getYOffset(),
417: dataArea.getWidth() - getXOffset(),
418: dataArea.getHeight() - getYOffset());
419:
420: GeneralPath path = null;
421: PlotOrientation orientation = plot.getOrientation();
422: if (orientation == PlotOrientation.HORIZONTAL) {
423: float x = (float) axis.valueToJava2D(value, adjusted,
424: plot.getRangeAxisEdge());
425: float y = (float) adjusted.getMaxY();
426: path = new GeneralPath();
427: path.moveTo(x, y);
428: path.lineTo((float) (x + getXOffset()),
429: y - (float) getYOffset());
430: path.lineTo((float) (x + getXOffset()),
431: (float) (adjusted.getMinY() - getYOffset()));
432: path.lineTo(x, (float) adjusted.getMinY());
433: path.closePath();
434: }
435: else if (orientation == PlotOrientation.VERTICAL) {
436: float y = (float) axis.valueToJava2D(value, adjusted,
437: plot.getRangeAxisEdge());
438: float x = (float) dataArea.getX();
439: path = new GeneralPath();
440: path.moveTo(x, y);
441: path.lineTo(x + (float) this.xOffset, y - (float) this.yOffset);
442: path.lineTo((float) (adjusted.getMaxX() + this.xOffset),
443: y - (float) this.yOffset);
444: path.lineTo((float) (adjusted.getMaxX()), y);
445: path.closePath();
446: }
447: g2.setPaint(marker.getPaint());
448: g2.fill(path);
449: g2.setPaint(marker.getOutlinePaint());
450: g2.draw(path);
451: }
452: }
453:
454:
468: public void drawItem(Graphics2D g2,
469: CategoryItemRendererState state,
470: Rectangle2D dataArea,
471: CategoryPlot plot,
472: CategoryAxis domainAxis,
473: ValueAxis rangeAxis,
474: CategoryDataset dataset,
475: int row,
476: int column,
477: int pass) {
478:
479: if (!getItemVisible(row, column)) {
480: return;
481: }
482:
483:
484: Number v = dataset.getValue(row, column);
485: if (v == null) {
486: return;
487: }
488:
489: Rectangle2D adjusted = new Rectangle2D.Double(dataArea.getX(),
490: dataArea.getY() + getYOffset(),
491: dataArea.getWidth() - getXOffset(),
492: dataArea.getHeight() - getYOffset());
493:
494: PlotOrientation orientation = plot.getOrientation();
495:
496:
497: double x1 = domainAxis.getCategoryMiddle(column, getColumnCount(),
498: adjusted, plot.getDomainAxisEdge());
499: double value = v.doubleValue();
500: double y1 = rangeAxis.valueToJava2D(value, adjusted,
501: plot.getRangeAxisEdge());
502:
503: Shape shape = getItemShape(row, column);
504: if (orientation == PlotOrientation.HORIZONTAL) {
505: shape = ShapeUtilities.createTranslatedShape(shape, y1, x1);
506: }
507: else if (orientation == PlotOrientation.VERTICAL) {
508: shape = ShapeUtilities.createTranslatedShape(shape, x1, y1);
509: }
510:
511: if (getItemLineVisible(row, column)) {
512: if (column != 0) {
513:
514: Number previousValue = dataset.getValue(row, column - 1);
515: if (previousValue != null) {
516:
517:
518: double previous = previousValue.doubleValue();
519: double x0 = domainAxis.getCategoryMiddle(column - 1,
520: getColumnCount(), adjusted,
521: plot.getDomainAxisEdge());
522: double y0 = rangeAxis.valueToJava2D(previous, adjusted,
523: plot.getRangeAxisEdge());
524:
525: double x2 = x0 + getXOffset();
526: double y2 = y0 - getYOffset();
527: double x3 = x1 + getXOffset();
528: double y3 = y1 - getYOffset();
529:
530: GeneralPath clip = new GeneralPath();
531:
532: if (orientation == PlotOrientation.HORIZONTAL) {
533: clip.moveTo((float) y0, (float) x0);
534: clip.lineTo((float) y1, (float) x1);
535: clip.lineTo((float) y3, (float) x3);
536: clip.lineTo((float) y2, (float) x2);
537: clip.lineTo((float) y0, (float) x0);
538: clip.closePath();
539: }
540: else if (orientation == PlotOrientation.VERTICAL) {
541: clip.moveTo((float) x0, (float) y0);
542: clip.lineTo((float) x1, (float) y1);
543: clip.lineTo((float) x3, (float) y3);
544: clip.lineTo((float) x2, (float) y2);
545: clip.lineTo((float) x0, (float) y0);
546: clip.closePath();
547: }
548:
549: g2.setPaint(getItemPaint(row, column));
550: g2.fill(clip);
551: g2.setStroke(getItemOutlineStroke(row, column));
552: g2.setPaint(getItemOutlinePaint(row, column));
553: g2.draw(clip);
554: }
555: }
556: }
557:
558:
559: if (isItemLabelVisible(row, column)) {
560: drawItemLabel(g2, orientation, dataset, row, column, x1, y1,
561: (value < 0.0));
562: }
563:
564:
565: EntityCollection entities = state.getEntityCollection();
566: if (entities != null) {
567: addItemEntity(entities, dataset, row, column, shape);
568: }
569:
570: }
571:
572: }