1:
51:
52: package ;
53:
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: import ;
77: import ;
78:
79:
82: public class GanttRenderer extends IntervalBarRenderer
83: implements Serializable {
84:
85:
86: private static final long serialVersionUID = -4010349116350119512L;
87:
88:
89: private transient Paint completePaint;
90:
91:
92: private transient Paint incompletePaint;
93:
94:
98: private double startPercent;
99:
100:
104: private double endPercent;
105:
106:
109: public GanttRenderer() {
110: super();
111: setIncludeBaseInRange(false);
112: this.completePaint = Color.green;
113: this.incompletePaint = Color.red;
114: this.startPercent = 0.35;
115: this.endPercent = 0.65;
116: }
117:
118:
125: public Paint getCompletePaint() {
126: return this.completePaint;
127: }
128:
129:
137: public void setCompletePaint(Paint paint) {
138: if (paint == null) {
139: throw new IllegalArgumentException("Null 'paint' argument.");
140: }
141: this.completePaint = paint;
142: notifyListeners(new RendererChangeEvent(this));
143: }
144:
145:
152: public Paint getIncompletePaint() {
153: return this.incompletePaint;
154: }
155:
156:
164: public void setIncompletePaint(Paint paint) {
165: if (paint == null) {
166: throw new IllegalArgumentException("Null 'paint' argument.");
167: }
168: this.incompletePaint = paint;
169: notifyListeners(new RendererChangeEvent(this));
170: }
171:
172:
180: public double getStartPercent() {
181: return this.startPercent;
182: }
183:
184:
192: public void setStartPercent(double percent) {
193: this.startPercent = percent;
194: notifyListeners(new RendererChangeEvent(this));
195: }
196:
197:
205: public double getEndPercent() {
206: return this.endPercent;
207: }
208:
209:
217: public void setEndPercent(double percent) {
218: this.endPercent = percent;
219: notifyListeners(new RendererChangeEvent(this));
220: }
221:
222:
236: public void drawItem(Graphics2D g2,
237: CategoryItemRendererState state,
238: Rectangle2D dataArea,
239: CategoryPlot plot,
240: CategoryAxis domainAxis,
241: ValueAxis rangeAxis,
242: CategoryDataset dataset,
243: int row,
244: int column,
245: int pass) {
246:
247: if (dataset instanceof GanttCategoryDataset) {
248: GanttCategoryDataset gcd = (GanttCategoryDataset) dataset;
249: drawTasks(g2, state, dataArea, plot, domainAxis, rangeAxis, gcd,
250: row, column);
251: }
252: else {
253: super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis,
254: dataset, row, column, pass);
255: }
256:
257: }
258:
259:
272: protected void drawTasks(Graphics2D g2,
273: CategoryItemRendererState state,
274: Rectangle2D dataArea,
275: CategoryPlot plot,
276: CategoryAxis domainAxis,
277: ValueAxis rangeAxis,
278: GanttCategoryDataset dataset,
279: int row,
280: int column) {
281:
282: int count = dataset.getSubIntervalCount(row, column);
283: if (count == 0) {
284: drawTask(g2, state, dataArea, plot, domainAxis, rangeAxis,
285: dataset, row, column);
286: }
287:
288: for (int subinterval = 0; subinterval < count; subinterval++) {
289:
290: RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
291:
292:
293: Number value0 = dataset.getStartValue(row, column, subinterval);
294: if (value0 == null) {
295: return;
296: }
297: double translatedValue0 = rangeAxis.valueToJava2D(
298: value0.doubleValue(), dataArea, rangeAxisLocation);
299:
300:
301: Number value1 = dataset.getEndValue(row, column, subinterval);
302: if (value1 == null) {
303: return;
304: }
305: double translatedValue1 = rangeAxis.valueToJava2D(
306: value1.doubleValue(), dataArea, rangeAxisLocation);
307:
308: if (translatedValue1 < translatedValue0) {
309: double temp = translatedValue1;
310: translatedValue1 = translatedValue0;
311: translatedValue0 = temp;
312: }
313:
314: double rectStart = calculateBarW0(plot, plot.getOrientation(),
315: dataArea, domainAxis, state, row, column);
316: double rectLength = Math.abs(translatedValue1 - translatedValue0);
317: double rectBreadth = state.getBarWidth();
318:
319:
320: Rectangle2D bar = null;
321:
322: if (plot.getOrientation() == PlotOrientation.HORIZONTAL) {
323: bar = new Rectangle2D.Double(translatedValue0, rectStart,
324: rectLength, rectBreadth);
325: }
326: else if (plot.getOrientation() == PlotOrientation.VERTICAL) {
327: bar = new Rectangle2D.Double(rectStart, translatedValue0,
328: rectBreadth, rectLength);
329: }
330:
331: Rectangle2D completeBar = null;
332: Rectangle2D incompleteBar = null;
333: Number percent = dataset.getPercentComplete(row, column,
334: subinterval);
335: double start = getStartPercent();
336: double end = getEndPercent();
337: if (percent != null) {
338: double p = percent.doubleValue();
339: if (plot.getOrientation() == PlotOrientation.HORIZONTAL) {
340: completeBar = new Rectangle2D.Double(translatedValue0,
341: rectStart + start * rectBreadth, rectLength * p,
342: rectBreadth * (end - start));
343: incompleteBar = new Rectangle2D.Double(translatedValue0
344: + rectLength * p, rectStart + start * rectBreadth,
345: rectLength * (1 - p), rectBreadth * (end - start));
346: }
347: else if (plot.getOrientation() == PlotOrientation.VERTICAL) {
348: completeBar = new Rectangle2D.Double(rectStart + start
349: * rectBreadth, translatedValue0 + rectLength
350: * (1 - p), rectBreadth * (end - start),
351: rectLength * p);
352: incompleteBar = new Rectangle2D.Double(rectStart + start
353: * rectBreadth, translatedValue0, rectBreadth
354: * (end - start), rectLength * (1 - p));
355: }
356:
357: }
358:
359: Paint seriesPaint = getItemPaint(row, column);
360: g2.setPaint(seriesPaint);
361: g2.fill(bar);
362: if (completeBar != null) {
363: g2.setPaint(getCompletePaint());
364: g2.fill(completeBar);
365: }
366: if (incompleteBar != null) {
367: g2.setPaint(getIncompletePaint());
368: g2.fill(incompleteBar);
369: }
370: if (isDrawBarOutline()
371: && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
372: g2.setStroke(getItemStroke(row, column));
373: g2.setPaint(getItemOutlinePaint(row, column));
374: g2.draw(bar);
375: }
376:
377:
378: if (state.getInfo() != null) {
379: EntityCollection entities = state.getEntityCollection();
380: if (entities != null) {
381: String tip = null;
382: if (getToolTipGenerator(row, column) != null) {
383: tip = getToolTipGenerator(row, column).generateToolTip(
384: dataset, row, column);
385: }
386: String url = null;
387: if (getItemURLGenerator(row, column) != null) {
388: url = getItemURLGenerator(row, column).generateURL(
389: dataset, row, column);
390: }
391: CategoryItemEntity entity = new CategoryItemEntity(
392: bar, tip, url, dataset, dataset.getRowKey(row),
393: dataset.getColumnKey(column));
394: entities.add(entity);
395: }
396: }
397: }
398: }
399:
400:
413: protected void drawTask(Graphics2D g2,
414: CategoryItemRendererState state,
415: Rectangle2D dataArea,
416: CategoryPlot plot,
417: CategoryAxis domainAxis,
418: ValueAxis rangeAxis,
419: GanttCategoryDataset dataset,
420: int row,
421: int column) {
422:
423: PlotOrientation orientation = plot.getOrientation();
424:
425: RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
426:
427:
428: Number value0 = dataset.getEndValue(row, column);
429: if (value0 == null) {
430: return;
431: }
432: double java2dValue0 = rangeAxis.valueToJava2D(value0.doubleValue(),
433: dataArea, rangeAxisLocation);
434:
435:
436: Number value1 = dataset.getStartValue(row, column);
437: if (value1 == null) {
438: return;
439: }
440: double java2dValue1 = rangeAxis.valueToJava2D(value1.doubleValue(),
441: dataArea, rangeAxisLocation);
442:
443: if (java2dValue1 < java2dValue0) {
444: double temp = java2dValue1;
445: java2dValue1 = java2dValue0;
446: java2dValue0 = temp;
447: Number tempNum = value1;
448: value1 = value0;
449: value0 = tempNum;
450: }
451:
452: double rectStart = calculateBarW0(plot, orientation, dataArea,
453: domainAxis, state, row, column);
454: double rectBreadth = state.getBarWidth();
455: double rectLength = Math.abs(java2dValue1 - java2dValue0);
456:
457: Rectangle2D bar = null;
458: if (orientation == PlotOrientation.HORIZONTAL) {
459: bar = new Rectangle2D.Double(java2dValue0, rectStart, rectLength,
460: rectBreadth);
461: }
462: else if (orientation == PlotOrientation.VERTICAL) {
463: bar = new Rectangle2D.Double(rectStart, java2dValue1, rectBreadth,
464: rectLength);
465: }
466:
467: Rectangle2D completeBar = null;
468: Rectangle2D incompleteBar = null;
469: Number percent = dataset.getPercentComplete(row, column);
470: double start = getStartPercent();
471: double end = getEndPercent();
472: if (percent != null) {
473: double p = percent.doubleValue();
474: if (plot.getOrientation() == PlotOrientation.HORIZONTAL) {
475: completeBar = new Rectangle2D.Double(java2dValue0,
476: rectStart + start * rectBreadth, rectLength * p,
477: rectBreadth * (end - start));
478: incompleteBar = new Rectangle2D.Double(java2dValue0
479: + rectLength * p, rectStart + start * rectBreadth,
480: rectLength * (1 - p), rectBreadth * (end - start));
481: }
482: else if (plot.getOrientation() == PlotOrientation.VERTICAL) {
483: completeBar = new Rectangle2D.Double(rectStart + start
484: * rectBreadth, java2dValue1 + rectLength * (1 - p),
485: rectBreadth * (end - start), rectLength * p);
486: incompleteBar = new Rectangle2D.Double(rectStart + start
487: * rectBreadth, java2dValue1, rectBreadth * (end
488: - start), rectLength * (1 - p));
489: }
490:
491: }
492:
493: Paint seriesPaint = getItemPaint(row, column);
494: g2.setPaint(seriesPaint);
495: g2.fill(bar);
496:
497: if (completeBar != null) {
498: g2.setPaint(getCompletePaint());
499: g2.fill(completeBar);
500: }
501: if (incompleteBar != null) {
502: g2.setPaint(getIncompletePaint());
503: g2.fill(incompleteBar);
504: }
505:
506:
507: if (isDrawBarOutline()
508: && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
509: Stroke stroke = getItemOutlineStroke(row, column);
510: Paint paint = getItemOutlinePaint(row, column);
511: if (stroke != null && paint != null) {
512: g2.setStroke(stroke);
513: g2.setPaint(paint);
514: g2.draw(bar);
515: }
516: }
517:
518: CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
519: column);
520: if (generator != null && isItemLabelVisible(row, column)) {
521: drawItemLabel(g2, dataset, row, column, plot, generator, bar,
522: false);
523: }
524:
525:
526: if (state.getInfo() != null) {
527: EntityCollection entities = state.getEntityCollection();
528: if (entities != null) {
529: String tip = null;
530: CategoryToolTipGenerator tipster = getToolTipGenerator(row,
531: column);
532: if (tipster != null) {
533: tip = tipster.generateToolTip(dataset, row, column);
534: }
535: String url = null;
536: if (getItemURLGenerator(row, column) != null) {
537: url = getItemURLGenerator(row, column).generateURL(
538: dataset, row, column);
539: }
540: CategoryItemEntity entity = new CategoryItemEntity(bar, tip,
541: url, dataset, dataset.getRowKey(row),
542: dataset.getColumnKey(column));
543: entities.add(entity);
544: }
545: }
546:
547: }
548:
549:
556: public boolean equals(Object obj) {
557: if (obj == this) {
558: return true;
559: }
560: if (!(obj instanceof GanttRenderer)) {
561: return false;
562: }
563: GanttRenderer that = (GanttRenderer) obj;
564: if (!PaintUtilities.equal(this.completePaint, that.completePaint)) {
565: return false;
566: }
567: if (!PaintUtilities.equal(this.incompletePaint, that.incompletePaint)) {
568: return false;
569: }
570: if (this.startPercent != that.startPercent) {
571: return false;
572: }
573: if (this.endPercent != that.endPercent) {
574: return false;
575: }
576: return super.equals(obj);
577: }
578:
579:
586: private void writeObject(ObjectOutputStream stream) throws IOException {
587: stream.defaultWriteObject();
588: SerialUtilities.writePaint(this.completePaint, stream);
589: SerialUtilities.writePaint(this.incompletePaint, stream);
590: }
591:
592:
600: private void readObject(ObjectInputStream stream)
601: throws IOException, ClassNotFoundException {
602: stream.defaultReadObject();
603: this.completePaint = SerialUtilities.readPaint(stream);
604: this.incompletePaint = SerialUtilities.readPaint(stream);
605: }
606:
607: }