teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.exports; felix@3183: felix@3183: import java.awt.geom.Line2D; felix@3183: import java.util.ArrayList; felix@3183: import java.util.HashMap; felix@3183: import java.util.Iterator; christian@4021: import java.util.LinkedHashMap; felix@3183: import java.util.List; felix@3183: felix@3183: import org.jfree.chart.LegendItem; felix@3183: import org.jfree.chart.LegendItemCollection; felix@3183: import org.jfree.chart.plot.XYPlot; felix@3183: felix@3183: /** Class to process Plots legends. */ felix@3183: public abstract class LegendProcessor { felix@3183: felix@3183: /** (Empty) shape for aggregated Legend Items. */ gernotbelger@9496: private static final Line2D.Double SPACE = new Line2D.Double(0, 0, 0, 0); felix@3183: felix@3183: /** Prevent instantiations. */ felix@3183: private LegendProcessor() { felix@3183: } felix@3183: felix@3183: /** felix@3183: * Create a hash from a legenditem. felix@3183: * This hash can then be used to merge legend items labels. gernotbelger@9496: * felix@3183: * @return hash for given legenditem to identify mergeables. felix@3183: */ gernotbelger@9496: protected static String legendItemHash(final LegendItem li) { tom@8856: // TODO Do proper implementation. tom@8856: // Ensure that only mergable sets are created. felix@3183: // getFillPaint() felix@3183: // getFillPaintTransformer() felix@3183: // getLabel() felix@3183: // getLine() felix@3183: // getLinePaint() felix@3183: // getLineStroke() felix@3183: // getOutminePaint() felix@3183: // getOutlineStroke() felix@3183: // Shape getShape() felix@3183: // String getToolTipText() felix@3183: // String getURLText() felix@3183: // boolean isLineVisible() felix@3183: // boolean isShapeFilled() felix@3183: // boolean isShapeOutlineVisible() felix@3183: // boolean isShapeVisible() gernotbelger@9496: final String hash = li.getLinePaint().toString(); teichmann@4046: // XXX: DEAD CODE // String label = li.getLabel(); gernotbelger@9496: /* gernotbelger@9496: * if (label.startsWith("W (") || label.startsWith("W(")) { gernotbelger@9496: * hash += "-W-"; gernotbelger@9496: * } gernotbelger@9496: * else if (label.startsWith("Q(") || label.startsWith("Q (")) { gernotbelger@9496: * hash += "-Q-"; gernotbelger@9496: * } gernotbelger@9496: */ felix@3183: felix@3183: // WQ.java holds example of using regex Matcher/Pattern. felix@3183: felix@3183: return hash; felix@3183: } felix@3183: felix@3183: /** felix@3183: * Create new legend entries, dependent on settings. gernotbelger@9496: * gernotbelger@9496: * @param plot gernotbelger@9496: * The plot for which to modify the legend. gernotbelger@9496: * @param threshold gernotbelger@9496: * How many items are needed for aggregation to gernotbelger@9496: * be triggered? felix@3183: */ gernotbelger@9496: public static void aggregateLegendEntries(final XYPlot plot, final int threshold) { gernotbelger@9496: final LegendItemCollection old = plot.getLegendItems(); felix@3183: // Find "similar" entries if aggregation is enabled. felix@3183: felix@3183: int maxListSize = 0; gernotbelger@9496: final int AGGR_THRESHOLD = threshold; felix@3183: gernotbelger@9496: if (AGGR_THRESHOLD > old.getItemCount() || AGGR_THRESHOLD <= 0) { felix@3183: return; felix@3183: } felix@3183: gernotbelger@9496: final HashMap> entries = new LinkedHashMap<>(); gernotbelger@9496: // for (Iterator i = old.iterator(); i.hasNext();) { gernotbelger@9496: gernotbelger@9496: final Iterator iterator = old.iterator(); gernotbelger@9496: while (iterator.hasNext()) { gernotbelger@9496: final LegendItem item = iterator.next(); gernotbelger@9496: final String hash = legendItemHash(item); felix@3183: List itemList = entries.get(hash); felix@3183: if (itemList == null) { gernotbelger@9496: itemList = new ArrayList<>(); teichmann@4046: entries.put(hash, itemList); felix@3183: } felix@3183: itemList.add(item); felix@3183: felix@3183: if (itemList.size() > maxListSize) { felix@3183: maxListSize = itemList.size(); felix@3183: } felix@3183: } felix@3183: felix@3183: if (maxListSize < AGGR_THRESHOLD) { felix@3183: // No need to do anything. felix@3183: return; felix@3183: } felix@3183: felix@3183: // Run over collected entries, merge their names and create new felix@3183: // entry if needed. gernotbelger@9496: final LegendItemCollection newLegend = new LegendItemCollection(); gernotbelger@9496: for (final List itemList : entries.values()) { felix@3183: if (itemList.size() >= AGGR_THRESHOLD) { felix@3183: // Now do merging. teichmann@4046: // XXX: DEAD CODE // LegendItem item = itemList.get(0); tom@8856: // Unfortunately we cannot clone and just setDescription, tom@8856: // as this method was added in JFreeChart 1.0.14 tom@8856: // (we are at .13). felix@3183: felix@3183: // Remove the shapes of all but the first items, felix@3183: // to prevent "overfill" of legenditemblock. teichmann@7254: for (int i = 0, I = itemList.size(); i < I; i++) { felix@3183: if (i != 0) { gernotbelger@9496: final LegendItem litem = itemList.get(i); felix@3183: felix@3183: // Make shape and line really small. gernotbelger@9496: final LegendItem merged = new LegendItem("," + litem.getLabel(), litem.getDescription(), litem.getToolTipText(), litem.getURLText(), gernotbelger@9496: false, SPACE, false, litem.getFillPaint(), false, litem.getOutlinePaint(), litem.getOutlineStroke(), false, SPACE, gernotbelger@9496: litem.getLineStroke(), litem.getLinePaint()); felix@3183: newLegend.add(merged); gernotbelger@9496: } else { felix@3183: newLegend.add(itemList.get(i)); felix@3183: } felix@3183: } gernotbelger@9496: } else { felix@3183: // Do not merge entries. gernotbelger@9496: for (final LegendItem li : itemList) { felix@3183: newLegend.add(li); felix@3183: } felix@3183: } felix@3183: } felix@3183: gernotbelger@9496: plot.setFixedLegendItems(newLegend); felix@3183: } felix@3183: } felix@3183: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :