if (locationStyle == null) {
locationStyle = new Rectangle(-1, -1, -1, -1);
blackboard.put(LocationStyleContent.ID, locationStyle);
}
FontStyle fontStyle = (FontStyle) blackboard.get(FontStyleContent.ID);
if (fontStyle == null) {
fontStyle = new FontStyle();
blackboard.put(FontStyleContent.ID, fontStyle);
}
this.backgroundColour = legendStyle.backgroundColour;
this.foregroundColour = legendStyle.foregroundColour;
this.horizontalMargin = legendStyle.horizontalMargin;
this.verticalMargin = legendStyle.verticalMargin;
this.horizontalSpacing = legendStyle.horizontalSpacing;
this.verticalSpacing = legendStyle.verticalSpacing;
this.indentSize = legendStyle.indentSize;
this.imageHeight = legendStyle.imageHeight;
this.imageWidth = legendStyle.imageWidth;
final ViewportGraphics graphics = context.getGraphics();
if (fontStyle.getFont() != null) {
graphics.setFont(fontStyle.getFont());
}
List<Map<ILayer, LegendEntry[]>> layers = new ArrayList<Map<ILayer, LegendEntry[]>>();
int longestRow = 0; // used to calculate the width of the graphic
final int[] numberOfEntries = new int[1]; // total number of entries to
// draw
numberOfEntries[0] = 0;
/*
* Set up the layers that we want to draw so we can operate just on
* those ones. Layers at index 0 are on the bottom of the map, so we
* must iterate in reverse.
*
* While we are doing this, determine the longest row so we can properly
* draw the graphic's border.
*/
Dimension imageSize = new Dimension(imageWidth,imageHeight);
Dimension textSize = new Dimension(0, graphics.getFontHeight());
for (int i = context.getMapLayers().size() - 1; i >= 0; i--) {
ILayer layer = context.getMapLayers().get(i);
if (!(layer.getGeoResource() instanceof MapGraphicResource)
&& layer.isVisible()) {
if (layer.hasResource(MapGraphic.class)) {
// don't include mapgraphics
continue;
}
String layerName = layer.getName();
if (layerName == null) {
layerName = null;
}
LegendEntry layerEntry = new LegendEntry(layerName);
FeatureTypeStyle[] styles = locateStyle(layer);
LegendEntry[] entries = null;
if (styles == null) {
// we should have a label but no style
entries = new LegendEntry[] { layerEntry };
} else {
List<Rule> rules = rules(styles);
int ruleCount = rules.size();
if (ruleCount == 1
&& layer.getGeoResource().canResolve(
GridCoverage.class)) {
// grid coverage with single rule; lets see if it is a
// theming style
List<LegendEntry> cmEntries = ColorMapLegendCreator
.findEntries(styles, imageSize, textSize);
if (cmEntries != null) {
cmEntries.add(0, layerEntry); // add layer legend
// entry
entries = cmEntries
.toArray(new LegendEntry[cmEntries.size()]);
}
}
if (entries == null) {
List<LegendEntry> localEntries = new ArrayList<LegendEntry>();
if (ruleCount == 1) {
// only one rule so apply this to the layer legend
// entry
layerEntry.setRule(rules.get(0));
}
localEntries.add(layerEntry); // add layer legend entry
if (ruleCount > 1) {
// we have more than one rule so there is likely
// some
// themeing going on; add each of these rules
for (Rule rule : rules) {
LegendEntry rentry = new LegendEntry(rule);
localEntries.add(rentry);
}
}
entries = localEntries
.toArray(new LegendEntry[localEntries.size()]);
}
}
layers.add(Collections.singletonMap(layer, entries));
// compute maximum length for each entry
for (int j = 0; j < entries.length; j++) {
StringBuilder sb = new StringBuilder();
for (int k = 0; k < entries[j].getText().length; k++){
sb.append(entries[j].getText()[k]);
}
Rectangle2D bounds = graphics.getStringBounds(sb.toString());
int length = indentSize + imageWidth + horizontalSpacing
+ (int) bounds.getWidth();
if (length > longestRow) {
longestRow = length;
}
numberOfEntries[0]++;
}
}
}
if (numberOfEntries[0] == 0) {
// nothing to draw!
return;
}
final int rowHeight = Math.max(imageHeight, graphics.getFontHeight()); // space
// allocated
// to
// each
// layer
if (locationStyle.width == 0 || locationStyle.height == 0) {
// we want to change the location style as needed
// but not change the saved one so we create a copy here
locationStyle = new Rectangle(locationStyle);
if (locationStyle.width == 0) {
// we want to grow to whatever size we need
int width = longestRow + horizontalMargin * 2;
locationStyle.width = width;
}
if (locationStyle.height == 0) {
// we want to grow to whatever size we need
int height = rowHeight * numberOfEntries[0] + verticalMargin * 2;
for (int i = 0; i < layers.size(); i++) {
Map<ILayer, LegendEntry[]> map = layers.get(i);
final LegendEntry[] entries = map.values().iterator().next();
for (int j = 0; j < entries.length; j ++){
if (entries[j].getSpacingAfter() == null){
height += verticalSpacing;
}else{
height += entries[j].getSpacingAfter();
}
}
}
locationStyle.height = height- verticalSpacing;
}
}
// ensure box within the display
Dimension displaySize = context.getMapDisplay().getDisplaySize();
if (locationStyle.x < 0) {
locationStyle.x = displaySize.width - locationStyle.width
+ locationStyle.x;
}
if ((locationStyle.x + locationStyle.width + 6) > displaySize.width) {
locationStyle.x = displaySize.width - locationStyle.width - 5;
}
if (locationStyle.y < 0) {
locationStyle.y = displaySize.height - locationStyle.height - 5
+ locationStyle.y;
}
if ((locationStyle.y + locationStyle.height + 6) > displaySize.height) {
locationStyle.y = displaySize.height - locationStyle.height - 5;
}
graphics.setClip(new Rectangle(locationStyle.x, locationStyle.y,
locationStyle.width + 1, locationStyle.height + 1));
/*
* Draw the box containing the layers/icons
*/
drawOutline(graphics, context, locationStyle);
/*
* Draw the layer names/icons
*/
final int[] rowsDrawn = new int[1];
rowsDrawn[0] = 0;
final int[] x = new int[1];
x[0] = locationStyle.x + horizontalMargin;
final int[] y = new int[1];
y[0] = locationStyle.y + verticalMargin;
if (fontStyle.getFont() != null) {
graphics.setFont(fontStyle.getFont());
}
for (int i = 0; i < layers.size(); i++) {
Map<ILayer, LegendEntry[]> map = layers.get(i);
final ILayer layer = map.keySet().iterator().next();