001: /*********************************************************************************
002: * The contents of this file are subject to the OpenI Public License Version 1.0
003: * ("License"); You may not use this file except in compliance with the
004: * License. You may obtain a copy of the License at
005: * http://www.openi.org/docs/LICENSE.txt
006: *
007: * Software distributed under the License is distributed on an "AS IS" basis,
008: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
009: * the specific language governing rights and limitations under the License.
010: *
011: * The Original Code is: OpenI Open Source
012: *
013: * The Initial Developer of the Original Code is Loyalty Matrix, Inc.
014: * Portions created by Loyalty Matrix, Inc. are
015: * Copyright (C) 2005 Loyalty Matrix, Inc.; All Rights Reserved.
016: *
017: * Contributor(s): i18n : Pedro Casals Fradera (2006/06/22)
018: *
019: ********************************************************************************/package org.openi.chart;
020:
021: import java.awt.Color;
022: import java.awt.Font;
023: import java.awt.Paint;
024: import java.text.NumberFormat;
025: import java.util.Iterator;
026: import java.util.LinkedList;
027: import java.util.List;
028: import java.util.Locale;
029: import java.util.ResourceBundle;
030:
031: import org.apache.log4j.Logger;
032: import org.jfree.chart.JFreeChart;
033: import org.jfree.chart.axis.CategoryLabelPosition;
034: import org.jfree.chart.axis.CategoryLabelPositions;
035: import org.jfree.chart.axis.CategoryLabelWidthType;
036: import org.jfree.chart.axis.NumberAxis;
037: import org.jfree.chart.block.BlockBorder;
038: import org.jfree.chart.plot.CategoryPlot;
039: import org.jfree.chart.plot.DatasetRenderingOrder;
040: import org.jfree.chart.plot.PiePlot;
041: import org.jfree.chart.plot.PiePlot3D;
042: import org.jfree.chart.plot.Plot;
043: import org.jfree.chart.plot.XYPlot;
044: import org.jfree.chart.renderer.category.CategoryItemRenderer;
045: import org.jfree.chart.renderer.category.LineAndShapeRenderer;
046: import org.jfree.chart.title.LegendTitle;
047: import org.jfree.chart.title.TextTitle;
048: import org.jfree.data.DataUtilities;
049: import org.jfree.data.KeyedValues;
050: import org.jfree.data.category.CategoryDataset;
051: import org.jfree.data.general.DatasetUtilities;
052: import org.jfree.data.general.PieDataset;
053: import org.jfree.text.TextBlockAnchor;
054: import org.jfree.ui.HorizontalAlignment;
055: import org.jfree.ui.RectangleAnchor;
056: import org.jfree.ui.RectangleEdge;
057: import org.jfree.ui.RectangleInsets;
058: import org.jfree.ui.TextAnchor;
059: import org.jfree.ui.VerticalAlignment;
060:
061: import com.tonbeller.jpivot.olap.model.Member;
062: import com.tonbeller.jpivot.olap.model.Position;
063: import com.tonbeller.jpivot.olap.model.Result;
064:
065: /**
066: * customizes chart properties based on model (enhanced chart component)
067: */
068: public class ChartCustomizer {
069: private static Logger logger = Logger
070: .getLogger(ChartCustomizer.class);
071:
072: public void customizeChart(JFreeChart chart, Paint bgPaint,
073: Font axisFont, Font axisTickFont, Font legendFont,
074: int legendPosition, double tickLabelRotate,
075: float foregoundAlpha) {
076: chart.setBackgroundPaint(bgPaint);
077: // chart.setBackgroundPaint(new Color(255, 255, 255));
078: logger.debug("setting background paint: " + bgPaint);
079:
080: Plot plot = chart.getPlot();
081: logger.debug("plot type: " + plot.getClass().getName());
082: plot.setForegroundAlpha(1.0f);
083:
084: if (plot instanceof CategoryPlot) {
085: CategoryPlot catPlot = (CategoryPlot) plot;
086: catPlot.getDomainAxis().setLabelFont(axisFont);
087: catPlot.getRangeAxis().setLabelFont(axisFont);
088: catPlot.getDomainAxis().setTickLabelFont(axisTickFont);
089: catPlot.getRangeAxis().setTickLabelFont(axisTickFont);
090: catPlot.getDomainAxis().setMaximumCategoryLabelWidthRatio(
091: 100.00f);
092:
093: double angle = (-2.0 * Math.PI) / 360.0 * tickLabelRotate;
094: CategoryLabelPositions oldp = catPlot.getDomainAxis()
095: .getCategoryLabelPositions();
096: /*CategoryLabelPositions newp = new CategoryLabelPositions(oldp
097: .getLabelPosition(RectangleEdge.TOP),
098: new CategoryLabelPosition(RectangleAnchor.TOP,
099: TextBlockAnchor.TOP_RIGHT,
100: TextAnchor.TOP_RIGHT, angle),
101: oldp.getLabelPosition(RectangleEdge.LEFT),
102: oldp.getLabelPosition(RectangleEdge.RIGHT));*/
103: CategoryLabelPositions newp = new CategoryLabelPositions(
104: oldp.getLabelPosition(RectangleEdge.TOP),
105: new CategoryLabelPosition(RectangleAnchor.TOP,
106: TextBlockAnchor.TOP_RIGHT,
107: TextAnchor.TOP_RIGHT, angle,
108: CategoryLabelWidthType.RANGE, 0.0f), oldp
109: .getLabelPosition(RectangleEdge.LEFT), oldp
110: .getLabelPosition(RectangleEdge.RIGHT));
111: catPlot.getDomainAxis().setCategoryLabelPositions(newp);
112:
113: // XXX: setting series colors
114: logger.info("setting up series colors");
115: setupSeriesPaint(this .getDefaultColorPalette(), chart
116: .getCategoryPlot().getRenderer());
117:
118: } else if (plot instanceof PiePlot3D) {
119: PiePlot3D piePlot = (PiePlot3D) plot;
120:
121: //piePlot.setSectionLabelFont(axisFont);
122: piePlot.setLabelFont(axisFont);
123:
124: //piePlot.setSeriesLabelFont(axisTickFont);
125: //piePlot.setSectionLabelType(piePlot.NO_LABELS);
126: piePlot.setDirection(org.jfree.util.Rotation.CLOCKWISE);
127: //casting int type to float type
128: piePlot.setNoDataMessage("No data to display");
129: } else if (plot instanceof PiePlot) {
130: PiePlot piePlot = (PiePlot) plot;
131: //piePlot.setSectionLabelFont(axisFont);
132: //piePlot.setSeriesLabelFont(axisTickFont);
133: piePlot.setLabelFont(axisFont);
134:
135: //piePlot.setSectionLabelType(piePlot.NO_LABELS);
136: } else if (plot instanceof XYPlot) {
137: XYPlot xyPlot = (XYPlot) plot;
138: xyPlot.getDomainAxis().setLabelFont(axisFont);
139: xyPlot.getRangeAxis().setLabelFont(axisFont);
140: xyPlot.getDomainAxis().setTickLabelFont(axisTickFont);
141: xyPlot.getRangeAxis().setTickLabelFont(axisTickFont);
142: // xyPlot.getDomainAxis().setMaxCategoryLabelWidthRatio(100);
143: xyPlot.setBackgroundPaint(bgPaint);
144: xyPlot.setRangeGridlinesVisible(true);
145: xyPlot.setRangeGridlinePaint(new Color(166, 166, 166));
146: // xyPlot.setRangeTickBandPaint(purple);
147: // Color purple = new Color(171, 25, 97);
148: // xyPlot.setRangeCrosshairPaint(purple);
149: xyPlot.getDomainAxis().setAxisLineVisible(false);
150: xyPlot.getRangeAxis().setAxisLineVisible(false);
151: xyPlot.setOutlinePaint(new Color(0, 0, 0));
152: //xyPlot.getRangeAxis().setMinimumAxisValue(0);
153: }
154:
155: customizeLegend(chart, legendFont, legendPosition);
156:
157: }
158:
159: /**
160: * @param component
161: * @param chart
162: * @param legendFont
163: */
164: private void customizeLegend(JFreeChart chart, Font legendFont,
165: int legendPosition) {
166: LegendTitle legend = (LegendTitle) chart.getLegend();
167:
168: if (legend != null) {
169: legend.setItemFont(legendFont);
170: // legend.setPreferredWidth(EnhancedChartComponent.DEFAULT_LEGEND_WIDTH);
171: /*legend.setAnchor(legendPosition);
172: legend.setOutlinePaint(legend.getBackgroundPaint());*/
173: legend.setBorder(BlockBorder.NONE);
174: RectangleEdge legendRectEdge = RectangleEdge.BOTTOM;
175: switch (legendPosition) {
176: case 0:
177: legendRectEdge = RectangleEdge.LEFT;
178: break;
179: case 1:
180: legendRectEdge = RectangleEdge.TOP;
181: break;
182: case 2:
183: legendRectEdge = RectangleEdge.RIGHT;
184: break;
185: case 3:
186: legendRectEdge = RectangleEdge.BOTTOM;
187: break;
188: }
189: legend.setPosition(legendRectEdge);
190: }
191: }
192:
193: private RectangleEdge createRectangleEdge(int slicerPosition) {
194: RectangleEdge slicerRectPos = RectangleEdge.BOTTOM;
195:
196: switch (slicerPosition) {
197: case 0:
198: slicerRectPos = RectangleEdge.LEFT;
199: break;
200:
201: case 1:
202: slicerRectPos = RectangleEdge.TOP;
203: break;
204:
205: case 2:
206: slicerRectPos = RectangleEdge.RIGHT;
207: break;
208:
209: case 3:
210: slicerRectPos = RectangleEdge.BOTTOM;
211: break;
212: }
213: return slicerRectPos;
214:
215: }
216:
217: private HorizontalAlignment createHorizontalAlignment(
218: int slicerAlignment) {
219: HorizontalAlignment slicerHorizAlignment = HorizontalAlignment.LEFT;
220:
221: switch (slicerAlignment) {
222: case 4:
223: slicerHorizAlignment = HorizontalAlignment.CENTER;
224: break;
225:
226: case 3:
227: slicerHorizAlignment = HorizontalAlignment.LEFT;
228: break;
229:
230: case 2:
231: slicerHorizAlignment = HorizontalAlignment.RIGHT;
232: break;
233: }
234:
235: return slicerHorizAlignment;
236: }
237:
238: /**
239: * Series paint will be set in the list order of the colorPallette
240: * parameter. Can contain a list of any java.awt.Paint objects
241: * (Color, GradientPaint, etc).
242: * Will only attempt if the paintList is not null.
243: *
244: * @param colorPalette list of java.awt.Paint objects
245: * @param renderer
246: */
247: public void setupSeriesPaint(List paintList,
248: CategoryItemRenderer renderer) {
249: logger.debug("setupSeriesPaint: " + paintList);
250:
251: if (paintList != null) {
252: Iterator palette = paintList.iterator();
253:
254: for (int i = 0; palette.hasNext(); i++) {
255: Paint current = (Paint) palette.next();
256: renderer.setSeriesPaint(i, current);
257: }
258: }
259: }
260:
261: public void generatePareto(CategoryPlot plot) {
262: CategoryDataset dataset = plot.getDataset();
263: PieDataset pieDataset = DatasetUtilities
264: .createPieDatasetForRow(dataset, 0);
265: KeyedValues cumulative = DataUtilities
266: .getCumulativePercentages(pieDataset);
267: LineAndShapeRenderer renderer = new LineAndShapeRenderer();
268:
269: CategoryDataset dataset2 = DatasetUtilities
270: .createCategoryDataset("Cumulative Pct", // will show up in legend
271: cumulative);
272: NumberAxis axis2 = new NumberAxis("Culmulative Percentage"); // axis label
273:
274: axis2
275: .setNumberFormatOverride(NumberFormat
276: .getPercentInstance());
277: //axis2.setMaximumAxisValue(1.0);//set max to 100%, otherwise defaults to 105%
278: axis2.setUpperBound(1.0);//1.0.1 update
279: //
280: plot.setRangeAxis(1, axis2);
281: plot.setDataset(1, dataset2);
282: plot.setRenderer(1, renderer);
283: plot.mapDatasetToRangeAxis(1, 1);
284: plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
285:
286: }
287:
288: /**
289: * build slicer text string
290: */
291: private String buildSlicer(Result result, Locale locale) {
292: StringBuffer slicer = new StringBuffer();
293:
294: ResourceBundle rb = ResourceBundle.getBundle(
295: "org.openi.labels", locale);
296: slicer.append(rb.getString("java_ChartCustomizer.slicer")
297: + ": ");
298:
299: Iterator pi = result.getSlicer().getPositions().iterator();
300:
301: while (pi.hasNext()) {
302: Position p = (Position) pi.next();
303: Member[] members = p.getMembers();
304:
305: for (int i = 0; i < members.length; i++) {
306: slicer.append(members[i].getLevel().getLabel());
307: slicer.append("=");
308: slicer.append(members[i].getLabel());
309:
310: if (i < (members.length - 1)) {
311: slicer.append(", ");
312: }
313: }
314: }
315:
316: return slicer.toString();
317: }
318:
319: /**
320: * Get cell value as a Number. Parses the cell value string
321: * using the locale set in this.locale.
322: * @param cell
323: * @return value as Number (can be null)
324: */
325:
326: /*
327: private Number getNumberValue(Cell cell) {
328: //**** HACK AR 2004.01.10
329: //String value = cell.getFormattedValue();
330: Object value = cell.getValue();
331:
332: //added to fix data format bug in range axis
333: if(cell.getFormattedValue()!=null && cell.getFormattedValue()!="" )
334: {
335:
336: String fmtValue=cell.getFormattedValue();
337: fmtValue=fmtValue.trim();
338: if(fmtValue.endsWith("%"))
339: {
340: rangeIsPercentage =true;
341: }
342: else if(fmtValue.startsWith("$"))
343: {
344: rangeIsCurrency=true;
345:
346: }
347: else
348: {
349: rangeIsDefault=true;
350: }
351: //rangeIsDefault=false;
352: //if(!cell.getFormat().isPercent())
353: // rangeIsPercentage=false;
354: }
355: ////////////////
356: DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
357: DecimalFormat formatter = new DecimalFormat();
358: formatter.setDecimalFormatSymbols(dfs);
359:
360: Number number = null;
361:
362: try {
363: // need this formatter so that we can properly render jfreecharts
364: number = formatter.parse(String.valueOf(value));
365: }
366: catch (Exception e) {
367: logger.error(e);
368: number = null;
369: }
370:
371: return number;
372: }
373: */
374: private float toFloat(double input) {
375: float output = 1.0f;
376:
377: try {
378: output = (float) input;
379: } catch (Exception e) {
380: logger.warn(e);
381: }
382:
383: return output;
384: }
385:
386: private List getDefaultColorPalette() {
387: List palette = new LinkedList();
388: palette.add(new Color(51, 102, 54));
389: palette.add(new Color(153, 204, 255));
390: palette.add(new Color(153, 153, 51));
391: palette.add(new Color(204, 153, 51));
392: palette.add(new Color(0, 102, 102));
393: palette.add(new Color(51, 153, 255));
394: palette.add(new Color(153, 51, 0));
395: palette.add(new Color(204, 204, 53));
396: palette.add(new Color(102, 153, 204));
397: palette.add(new Color(153, 153, 204));
398: palette.add(new Color(204, 204, 204));
399: palette.add(new Color(102, 153, 153));
400: palette.add(new Color(204, 204, 102));
401: palette.add(new Color(204, 102, 0));
402: palette.add(new Color(153, 153, 255));
403: palette.add(new Color(0, 102, 204));
404: palette.add(new Color(153, 204, 204));
405: palette.add(new Color(153, 153, 153));
406: palette.add(new Color(255, 204, 0));
407: palette.add(new Color(0, 153, 153));
408: palette.add(new Color(153, 204, 51));
409: palette.add(new Color(255, 153, 0));
410: palette.add(new Color(153, 153, 102));
411: palette.add(new Color(51, 153, 102));
412: palette.add(new Color(204, 204, 51));
413: return palette;
414: }
415:
416: public void formatNumberAxis(NumberFormat numberFormatter,
417: CategoryPlot plot) {
418: // format range if it is percent/currency
419: // TODO - need to bring this in from enhanced chart component
420: if (numberFormatter != null) {
421: NumberAxis numberAxis = (NumberAxis) plot.getRangeAxis();
422: numberAxis.setNumberFormatOverride(numberFormatter);
423: }
424:
425: /*
426: if(!rangeIsDefault && (catPlot.getRangeAxis() instanceof NumberAxis))
427: {
428: NumberAxis axis=(NumberAxis)catPlot.getRangeAxis();
429: if(rangeIsPercentage && !rangeIsCurrency)
430: {
431:
432: axis.setNumberFormatOverride(NumberFormat.getPercentInstance());
433: }
434: else if(rangeIsCurrency && !rangeIsPercentage)
435: {
436: NumberFormat fmt=NumberFormat.getCurrencyInstance();
437: fmt.setMaximumFractionDigits(0);
438: fmt.setMinimumFractionDigits(0);
439: axis.setNumberFormatOverride(fmt);
440: }
441: }
442: */
443: }
444:
445: public void customizeSlicer(JFreeChart chart, Result result,
446: Font slicerFont, int slicerPosition, int slicerAlignment,
447: Locale locale) {
448: logger.debug("customizing slicer position: " + slicerPosition);
449: /*TextTitle slicerText = new TextTitle(
450: buildSlicer(result, locale),
451: slicerFont,
452: this.createHorizontalAlignment(slicerAlignment) );*/
453: TextTitle slicerText = new TextTitle(
454: buildSlicer(result, locale), slicerFont, Color.BLACK,
455: this .createRectangleEdge(slicerPosition), this
456: .createHorizontalAlignment(slicerAlignment),
457: VerticalAlignment.CENTER, new RectangleInsets(0, 0, 0,
458: 0));
459:
460: slicerText
461: .setPosition(this.createRectangleEdge(slicerPosition));
462: chart.addSubtitle(slicerText);
463:
464: }
465:
466: }
|