view flys-artifacts/src/main/java/de/intevation/flys/exports/LegendProcessor.java @ 4255:670e98f5a441

Fixed leak while merging facets. The ThemeList that is used by OutputHelper to sort the Facets for an Output now uses a list to store the ManagedFacets. The correct order is made up by sorting the List using Collections.sort() function of the Java JDK. Therfore, the ManagedFacet class implements the Comparable interface. The return value of its compareTo(other) method depends on the value of the 'position' field.
author Ingo Weinzierl <weinzierl.ingo@googlemail.com>
date Thu, 25 Oct 2012 14:01:46 +0200
parents 3dc26ec2558d
children
line wrap: on
line source
package de.intevation.flys.exports;

import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;

import org.jfree.chart.LegendItem;
import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.plot.XYPlot;


/** Class to process Plots legends. */
public abstract class LegendProcessor {

    /** (Empty) shape for aggregated Legend Items. */
    private static final Line2D.Double SPACE = new Line2D.Double(0,0,0,0);


    /** Prevent instantiations. */
    private LegendProcessor() {
    }


    /**
     * Create a hash from a legenditem.
     * This hash can then be used to merge legend items labels.
     * @return hash for given legenditem to identify mergeables.
     */
    protected static String legendItemHash(LegendItem li) {
        // TODO Do proper implementation. Ensure that only mergable sets are created.
        // getFillPaint()
        // getFillPaintTransformer()
        // getLabel()
        // getLine()
        // getLinePaint()
        // getLineStroke()
        // getOutminePaint()
        // getOutlineStroke()
        // Shape getShape()
        // String getToolTipText()
        // String getURLText()
        // boolean isLineVisible()
        // boolean isShapeFilled()
        // boolean isShapeOutlineVisible()
        // boolean isShapeVisible()
        String hash = li.getLinePaint().toString();
        // XXX: DEAD CODE // String label = li.getLabel();
        /*if (label.startsWith("W (") || label.startsWith("W(")) {
            hash += "-W-";
        }
        else if (label.startsWith("Q(") || label.startsWith("Q (")) {
            hash += "-Q-";
        }*/

        // WQ.java holds example of using regex Matcher/Pattern.

        return hash;
    }


    /**
     * Create new legend entries, dependent on settings.
     * @param plot The plot for which to modify the legend.
     * @param threshold How many items are needed for aggregation to
     *                  be triggered?
     */
    public static void aggregateLegendEntries(XYPlot plot, int threshold) {
        LegendItemCollection old = plot.getLegendItems();
        // Find "similar" entries if aggregation is enabled.

        int maxListSize = 0;
        int AGGR_THRESHOLD = threshold;

        if (AGGR_THRESHOLD > old.getItemCount() || AGGR_THRESHOLD <= 0){
            return;
        }

        HashMap<String, List<LegendItem>> entries = new LinkedHashMap<String, List<LegendItem>>();
        for (Iterator<LegendItem> i = old.iterator(); i.hasNext();) {
            LegendItem item = i.next();
            String hash = legendItemHash(item);
            List<LegendItem> itemList = entries.get(hash);
            if (itemList == null) {
                itemList = new ArrayList<LegendItem>();
                entries.put(hash, itemList);
            }
            itemList.add(item);

            if (itemList.size() > maxListSize) {
                maxListSize = itemList.size();
            }
        }

        if (maxListSize < AGGR_THRESHOLD) {
            // No need to do anything.
            return;
        }

        // Run over collected entries, merge their names and create new
        // entry if needed.
        LegendItemCollection newLegend = new LegendItemCollection();
        for (List<LegendItem> itemList: entries.values()) {
            if (itemList.size() >= AGGR_THRESHOLD) {
                // Now do merging.
                // XXX: DEAD CODE // LegendItem item = itemList.get(0);
                // Unfortunately we cannot clone and just setDescription, as this
                // method was added in JFreeChart 1.0.14 (we are at .13).

                // Remove the shapes of all but the first items,
                // to prevent "overfill" of legenditemblock.
                for (int i = 0; i < itemList.size(); i++) {
                    if (i != 0) {
                        LegendItem litem = itemList.get(i);

                        // Make shape and line really small.
                        LegendItem merged = new LegendItem(
                            "," + litem.getLabel(), litem.getDescription(), litem.getToolTipText(),
                            litem.getURLText(), false, SPACE,
                            false, litem.getFillPaint(), false,
                            litem.getOutlinePaint(), litem.getOutlineStroke(), false,
                            SPACE, litem.getLineStroke(), litem.getLinePaint());
                        newLegend.add(merged);
                    }
                    else {
                        newLegend.add(itemList.get(i));
                    }
                }
            }
            else {
                // Do not merge entries.
                for (LegendItem li: itemList) {
                    newLegend.add(li);
                }
            }
        }

        plot.setFixedLegendItems (newLegend);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org