Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java @ 2584:5d5457a1bd5f
Stubby legend aggregation.
flys-artifacts/trunk@4136 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Felix Wolfsteller <felix.wolfsteller@intevation.de> |
---|---|
date | Fri, 09 Mar 2012 12:57:23 +0000 |
parents | 3598690dc9e2 |
children | bece6f604899 |
comparison
equal
deleted
inserted
replaced
2583:046d5c82ea0c | 2584:5d5457a1bd5f |
---|---|
8 | 8 |
9 import java.text.NumberFormat; | 9 import java.text.NumberFormat; |
10 | 10 |
11 import java.util.ArrayList; | 11 import java.util.ArrayList; |
12 import java.util.HashMap; | 12 import java.util.HashMap; |
13 import java.util.Iterator; | |
13 import java.util.List; | 14 import java.util.List; |
15 import java.util.LinkedHashMap; | |
14 import java.util.Map; | 16 import java.util.Map; |
15 | 17 |
16 import org.w3c.dom.Document; | 18 import org.w3c.dom.Document; |
17 | 19 |
18 import org.apache.log4j.Logger; | 20 import org.apache.log4j.Logger; |
19 | 21 |
20 import org.jfree.chart.ChartFactory; | 22 import org.jfree.chart.ChartFactory; |
21 import org.jfree.chart.JFreeChart; | 23 import org.jfree.chart.JFreeChart; |
24 import org.jfree.chart.LegendItem; | |
22 import org.jfree.chart.LegendItemCollection; | 25 import org.jfree.chart.LegendItemCollection; |
23 import org.jfree.chart.annotations.XYBoxAnnotation; | 26 import org.jfree.chart.annotations.XYBoxAnnotation; |
24 import org.jfree.chart.annotations.XYLineAnnotation; | 27 import org.jfree.chart.annotations.XYLineAnnotation; |
25 import org.jfree.chart.annotations.XYTextAnnotation; | 28 import org.jfree.chart.annotations.XYTextAnnotation; |
26 import org.jfree.chart.axis.NumberAxis; | 29 import org.jfree.chart.axis.NumberAxis; |
228 adjustAxes(plot); | 231 adjustAxes(plot); |
229 autoZoom(plot); | 232 autoZoom(plot); |
230 | 233 |
231 // These have to go after the autozoom. | 234 // These have to go after the autozoom. |
232 addAnnotationsToRenderer(plot); | 235 addAnnotationsToRenderer(plot); |
236 | |
237 aggregateLegendEntries(plot); | |
233 | 238 |
234 return chart; | 239 return chart; |
235 } | 240 } |
236 | 241 |
237 | 242 |
1020 doAnnotations(annotations, null, theme, visible); | 1025 doAnnotations(annotations, null, theme, visible); |
1021 addAxisSeries(series, axisIndex, visible); | 1026 addAxisSeries(series, axisIndex, visible); |
1022 } | 1027 } |
1023 | 1028 |
1024 | 1029 |
1030 /** | |
1031 * Create a hash from a legenditem. | |
1032 * This hash can then be used to merge legend items labels. | |
1033 * @return hash for given legenditem to identify mergeables. | |
1034 */ | |
1035 public static String legendItemHash(LegendItem li) { | |
1036 // TODO Do proper implementation. Ensure that only mergable sets are created. | |
1037 // getFillPaint() | |
1038 // getFillPaintTransformer() | |
1039 // getLabel() | |
1040 // getLine() | |
1041 // getLinePaint() | |
1042 // getLineStroke() | |
1043 // getOutlinePaint() | |
1044 // getOutlineStroke() | |
1045 // Shape getShape() | |
1046 // String getToolTipText() | |
1047 // String getURLText() | |
1048 // boolean isLineVisible() | |
1049 // boolean isShapeFilled() | |
1050 // boolean isShapeOutlineVisible() | |
1051 // boolean isShapeVisible() | |
1052 return li.getLinePaint().toString(); | |
1053 } | |
1054 | |
1055 | |
1056 /** | |
1057 * Create a label for multiple items. | |
1058 * | |
1059 * For example from "W(Q=100)" and "W(Q=220)" | |
1060 * "W(Q= {100, 22})" would result. | |
1061 * | |
1062 * @param items list of legenditems. | |
1063 * @return the merged label. | |
1064 */ | |
1065 public String mergeLegendNames(List<LegendItem> items) { | |
1066 if (items.size() == 0) { | |
1067 return null; | |
1068 } | |
1069 if (items.size() == 1) { | |
1070 return items.get(0).getLabel(); | |
1071 } | |
1072 // TODO consider using regionMathches for implementation. | |
1073 int lastMatchedChar = 0; | |
1074 boolean first = true; | |
1075 String startPattern = ""; | |
1076 String endPattern = ""; | |
1077 String name = ""; | |
1078 // First, figure out beginning and end patterns, then merge. | |
1079 for (LegendItem item : items) { | |
1080 if (first) { | |
1081 startPattern = item.getLabel(); | |
1082 endPattern = item.getLabel(); | |
1083 first = false; | |
1084 continue; | |
1085 } | |
1086 while (startPattern.length() > 0 && !item.getLabel().startsWith(startPattern)) { | |
1087 startPattern = startPattern.substring(0, startPattern.length() -1); | |
1088 } | |
1089 while (endPattern.length() > 0 && !item.getLabel().endsWith(endPattern)) { | |
1090 endPattern = endPattern.substring(1); | |
1091 } | |
1092 } | |
1093 | |
1094 // Then, merge. | |
1095 name = startPattern + " {"; | |
1096 first = true; | |
1097 for (LegendItem item : items) { | |
1098 if (!first) { | |
1099 name += ", "; | |
1100 } | |
1101 else { | |
1102 first = false; | |
1103 } | |
1104 name += item.getLabel().substring(startPattern.length(), | |
1105 item.getLabel().length() - endPattern.length()); | |
1106 } | |
1107 name += "} "; | |
1108 name += endPattern; | |
1109 | |
1110 return name; | |
1111 } | |
1112 | |
1113 | |
1114 /** | |
1115 * Create new legend entries, dependant on settings. | |
1116 * @param plot The plot for which to modify the legend. | |
1117 */ | |
1118 public void aggregateLegendEntries(XYPlot plot) { | |
1119 LegendItemCollection old = plot.getLegendItems(); | |
1120 // Find "similar" entries if aggregation is enabled. | |
1121 | |
1122 int maxListSize = 0; | |
1123 int AGGR_THRESHOLD = 2; | |
1124 | |
1125 HashMap<String, List<LegendItem>> entries = new LinkedHashMap<String, List<LegendItem>>(); | |
1126 for (Iterator i = old.iterator(); i.hasNext();) { | |
1127 LegendItem item = (LegendItem) i.next(); | |
1128 String hash = legendItemHash(item); | |
1129 List<LegendItem> itemList = entries.get(hash); | |
1130 if (itemList == null) { | |
1131 itemList = new ArrayList<LegendItem>(); | |
1132 } | |
1133 itemList.add(item); | |
1134 | |
1135 if (itemList.size() > maxListSize) { | |
1136 maxListSize = itemList.size(); | |
1137 } | |
1138 | |
1139 entries.put(legendItemHash(item), itemList); | |
1140 } | |
1141 | |
1142 if (maxListSize < AGGR_THRESHOLD) { | |
1143 // No need to do anything. | |
1144 return; | |
1145 } | |
1146 | |
1147 // Run over collected entries, merge their names and create new | |
1148 // entry if needed. | |
1149 LegendItemCollection newLegend = new LegendItemCollection(); | |
1150 for (Map.Entry<String, List<LegendItem>> cursor: entries.entrySet()) { | |
1151 List<LegendItem> itemList = cursor.getValue(); | |
1152 if (itemList.size() >= AGGR_THRESHOLD) { | |
1153 // TODO now do merging | |
1154 } | |
1155 else { | |
1156 // TODO create singular new entry | |
1157 } | |
1158 | |
1159 LegendItem item = (LegendItem) itemList.get(0); | |
1160 // Unfortunately we cannot clone and just setDescription, as this | |
1161 // method was added in JFreeChart 1.0.14 (we are at .13). | |
1162 LegendItem merged = new LegendItem( | |
1163 mergeLegendNames(itemList), item.getDescription(), item.getToolTipText(), | |
1164 item.getURLText(), item.isShapeVisible(), item.getShape(), | |
1165 item.isShapeFilled(), item.getFillPaint(), item.isShapeOutlineVisible(), | |
1166 item.getOutlinePaint(), item.getOutlineStroke(), item.isLineVisible(), | |
1167 item.getLine(), item.getLineStroke(), item.getLinePaint()); | |
1168 newLegend.add(merged); | |
1169 } | |
1170 | |
1171 plot.setFixedLegendItems (newLegend); | |
1172 } | |
1173 | |
1174 | |
1025 /** Two Ranges that span a rectangular area. */ | 1175 /** Two Ranges that span a rectangular area. */ |
1026 public static class Area { | 1176 public static class Area { |
1027 protected Range xRange; | 1177 protected Range xRange; |
1028 protected Range yRange; | 1178 protected Range yRange; |
1029 | 1179 |