1:
47:
48: package ;
49:
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56:
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70:
71:
75: public class LevelRenderer extends AbstractCategoryItemRenderer
76: implements Cloneable, PublicCloneable, Serializable {
77:
78:
79: private static final long serialVersionUID = -8204856624355025117L;
80:
81:
82: public static final double DEFAULT_ITEM_MARGIN = 0.20;
83:
84:
85: private double itemMargin;
86:
87:
88: private double maxItemWidth;
89:
90:
93: public LevelRenderer() {
94: super();
95: this.itemMargin = DEFAULT_ITEM_MARGIN;
96: this.maxItemWidth = 1.0;
97:
98: }
99:
100:
105: public double getItemMargin() {
106: return this.itemMargin;
107: }
108:
109:
116: public void setItemMargin(double percent) {
117: this.itemMargin = percent;
118: notifyListeners(new RendererChangeEvent(this));
119: }
120:
121:
129: public double getMaxItemWidth() {
130: return this.maxItemWidth;
131: }
132:
133:
142: public void setMaxItemWidth(double percent) {
143: this.maxItemWidth = percent;
144: notifyListeners(new RendererChangeEvent(this));
145: }
146:
147:
153: public double getMaximumItemWidth() {
154: return getMaxItemWidth();
155: }
156:
157:
164: public void setMaximumItemWidth(double percent) {
165: setMaxItemWidth(percent);
166: }
167:
168:
184: public CategoryItemRendererState initialise(Graphics2D g2,
185: Rectangle2D dataArea,
186: CategoryPlot plot,
187: int rendererIndex,
188: PlotRenderingInfo info) {
189:
190: CategoryItemRendererState state = super.initialise(g2, dataArea, plot,
191: rendererIndex, info);
192: calculateItemWidth(plot, dataArea, rendererIndex, state);
193: return state;
194:
195: }
196:
197:
205: protected void calculateItemWidth(CategoryPlot plot,
206: Rectangle2D dataArea,
207: int rendererIndex,
208: CategoryItemRendererState state) {
209:
210: CategoryAxis domainAxis = getDomainAxis(plot, rendererIndex);
211: CategoryDataset dataset = plot.getDataset(rendererIndex);
212: if (dataset != null) {
213: int columns = dataset.getColumnCount();
214: int rows = dataset.getRowCount();
215: double space = 0.0;
216: PlotOrientation orientation = plot.getOrientation();
217: if (orientation == PlotOrientation.HORIZONTAL) {
218: space = dataArea.getHeight();
219: }
220: else if (orientation == PlotOrientation.VERTICAL) {
221: space = dataArea.getWidth();
222: }
223: double maxWidth = space * getMaxItemWidth();
224: double categoryMargin = 0.0;
225: double currentItemMargin = 0.0;
226: if (columns > 1) {
227: categoryMargin = domainAxis.getCategoryMargin();
228: }
229: if (rows > 1) {
230: currentItemMargin = getItemMargin();
231: }
232: double used = space * (1 - domainAxis.getLowerMargin()
233: - domainAxis.getUpperMargin()
234: - categoryMargin - currentItemMargin);
235: if ((rows * columns) > 0) {
236: state.setBarWidth(Math.min(used / (rows * columns), maxWidth));
237: }
238: else {
239: state.setBarWidth(Math.min(used, maxWidth));
240: }
241: }
242: }
243:
244:
259: protected double calculateBarW0(CategoryPlot plot,
260: PlotOrientation orientation,
261: Rectangle2D dataArea,
262: CategoryAxis domainAxis,
263: CategoryItemRendererState state,
264: int row,
265: int column) {
266:
267: double space = 0.0;
268: if (orientation == PlotOrientation.HORIZONTAL) {
269: space = dataArea.getHeight();
270: }
271: else {
272: space = dataArea.getWidth();
273: }
274: double barW0 = domainAxis.getCategoryStart(column, getColumnCount(),
275: dataArea, plot.getDomainAxisEdge());
276: int seriesCount = getRowCount();
277: int categoryCount = getColumnCount();
278: if (seriesCount > 1) {
279: double seriesGap = space * getItemMargin()
280: / (categoryCount * (seriesCount - 1));
281: double seriesW = calculateSeriesWidth(space, domainAxis,
282: categoryCount, seriesCount);
283: barW0 = barW0 + row * (seriesW + seriesGap)
284: + (seriesW / 2.0) - (state.getBarWidth() / 2.0);
285: }
286: else {
287: barW0 = domainAxis.getCategoryMiddle(column, getColumnCount(),
288: dataArea, plot.getDomainAxisEdge()) - state.getBarWidth()
289: / 2.0;
290: }
291: return barW0;
292: }
293:
294:
308: public void drawItem(Graphics2D g2, CategoryItemRendererState state,
309: Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis,
310: ValueAxis rangeAxis, CategoryDataset dataset, int row, int column,
311: int pass) {
312:
313:
314: Number dataValue = dataset.getValue(row, column);
315: if (dataValue == null) {
316: return;
317: }
318:
319: double value = dataValue.doubleValue();
320:
321: PlotOrientation orientation = plot.getOrientation();
322: double barW0 = calculateBarW0(plot, orientation, dataArea, domainAxis,
323: state, row, column);
324: RectangleEdge edge = plot.getRangeAxisEdge();
325: double barL = rangeAxis.valueToJava2D(value, dataArea, edge);
326:
327:
328: Line2D line = null;
329: double x = 0.0;
330: double y = 0.0;
331: if (orientation == PlotOrientation.HORIZONTAL) {
332: x = barL;
333: y = barW0 + state.getBarWidth() / 2.0;
334: line = new Line2D.Double(barL, barW0, barL,
335: barW0 + state.getBarWidth());
336: }
337: else {
338: x = barW0 + state.getBarWidth() / 2.0;
339: y = barL;
340: line = new Line2D.Double(barW0, barL, barW0 + state.getBarWidth(),
341: barL);
342: }
343: Stroke itemStroke = getItemStroke(row, column);
344: Paint itemPaint = getItemPaint(row, column);
345: g2.setStroke(itemStroke);
346: g2.setPaint(itemPaint);
347: g2.draw(line);
348:
349: CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
350: column);
351: if (generator != null && isItemLabelVisible(row, column)) {
352: drawItemLabel(g2, orientation, dataset, row, column, x, y,
353: (value < 0.0));
354: }
355:
356:
357: if (state.getInfo() != null) {
358: EntityCollection entities = state.getEntityCollection();
359: if (entities != null) {
360: String tip = null;
361: CategoryToolTipGenerator tipster = getToolTipGenerator(row,
362: column);
363: if (tipster != null) {
364: tip = tipster.generateToolTip(dataset, row, column);
365: }
366: String url = null;
367: if (getItemURLGenerator(row, column) != null) {
368: url = getItemURLGenerator(row, column).generateURL(dataset,
369: row, column);
370: }
371: CategoryItemEntity entity = new CategoryItemEntity(
372: line.getBounds(), tip, url, dataset, row,
373: dataset.getColumnKey(column), column);
374: entities.add(entity);
375: }
376:
377: }
378:
379: }
380:
381:
391: protected double calculateSeriesWidth(double space, CategoryAxis axis,
392: int categories, int series) {
393: double factor = 1.0 - getItemMargin() - axis.getLowerMargin()
394: - axis.getUpperMargin();
395: if (categories > 1) {
396: factor = factor - axis.getCategoryMargin();
397: }
398: return (space * factor) / (categories * series);
399: }
400:
401:
408: public boolean equals(Object obj) {
409: if (obj == this) {
410: return true;
411: }
412: if (!(obj instanceof LevelRenderer)) {
413: return false;
414: }
415: if (!super.equals(obj)) {
416: return false;
417: }
418: LevelRenderer that = (LevelRenderer) obj;
419: if (this.itemMargin != that.itemMargin) {
420: return false;
421: }
422: if (this.maxItemWidth != that.maxItemWidth) {
423: return false;
424: }
425: return true;
426: }
427:
428: }