/*
* Copyright (C) 2014 Alec Dhuse
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package co.foldingmap.map.visualization;
import co.foldingmap.map.MapView;
import co.foldingmap.map.Overlay;
import co.foldingmap.xml.XmlOutput;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
import java.util.Collections;
/**
*
* @author Alec
*/
public class HeatMapKey extends Overlay {
public static final int NONE = 0;
public static final int TOP_LEFT = 1;
public static final int TOP_RIGHT = 2;
public static final int BOTTOM_LEFT = 3;
public static final int BOTTOM_RIGHT = 4;
public static final String VERTICAL = "Vertical";
public static final String HORIZONTAL = "Horizontal";
protected ArrayList<Color> colors;
protected ArrayList<String> labels;
protected boolean horizontal;
protected Color outlineColor, fillColor;
protected double maxLabelWidth;
protected FontMetrics fontMetrics;
protected int positionReference;
protected RoundRectangle2D outline;
public HeatMapKey(ArrayList<String> labels,
ArrayList<Color> colors,
int keyPosition,
String orientation) {
this.labels = labels;
this.colors = colors;
this.maxLabelWidth = -1;
this.positionReference = keyPosition;
if (orientation.equalsIgnoreCase(VERTICAL)) {
this.horizontal = false;
//If the key is vertical we should have high values on top
Collections.reverse(colors);
Collections.reverse(labels);
} else {
this.horizontal = true;
}
outline = new RoundRectangle2D.Float(20, 20, 266, 40, 10, 10);
fillColor = new Color(68,68,68, 120);
outlineColor = new Color(255,255,255, 77);
}
public HeatMapKey(ArrayList<String> labels,
ArrayList<Color> colors,
int keyPosition,
boolean horizontal) {
this.labels = labels;
this.colors = colors;
this.maxLabelWidth = -1;
this.positionReference = keyPosition;
this.horizontal = horizontal;
outline = new RoundRectangle2D.Float(20, 20, 266, 40, 10, 10);
fillColor = new Color(68,68,68, 120);
outlineColor = new Color(255,255,255, 77);
//If the key is vertical we should have high values on top
if (!horizontal) {
Collections.reverse(colors);
Collections.reverse(labels);
}
}
@Override
public Overlay copyOverlay() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void drawObject(Graphics2D g2, MapView mapView) {
int x, y;
float height, width;
float labelHeight, labelWidth;
float labelY;
Rectangle2D colorRect;
String currentLabel;
fontMetrics = g2.getFontMetrics();
//Get the max label width as it may affect the outline size
if (maxLabelWidth == -1) {
maxLabelWidth = fontMetrics.getStringBounds(getLongestLabel(), g2).getWidth();
}
if (positionReference == TOP_LEFT || positionReference == BOTTOM_LEFT) {
x = 10;
} else if (positionReference == TOP_RIGHT || positionReference == BOTTOM_RIGHT) {
if (horizontal) {
x = (int) mapView.getDisplayWidth() - 276;
} else {
x = (int) mapView.getDisplayWidth() - 55;
}
} else {
x = 0;
}
if (positionReference == TOP_LEFT || positionReference == TOP_RIGHT) {
y = 10;
} else if (positionReference == BOTTOM_LEFT || positionReference == BOTTOM_RIGHT) {
if (horizontal) {
y = (int) mapView.getDisplayHeight() - 105;
} else {
y = (int) mapView.getDisplayHeight() - 310;
}
} else {
y = 0;
}
if (horizontal) {
height = 8;
width = 256f / colors.size();
outline.setRoundRect(x, y, 266, 40, 10, 10);
} else {
height = 256f / colors.size();
width = 8;
outline.setRoundRect(x, y, (23 + maxLabelWidth), 266, 10, 10);
}
colorRect = new Rectangle2D.Float(x, 40, width, 5);
g2.setColor(outlineColor);
g2.draw(outline);
g2.setColor(fillColor);
g2.fill(outline);
if (horizontal) {
x = (int) (outline.getX() + 5);
y = (int) (outline.getY() + 25);
} else {
y = (int) (outline.getY() + 5);
if (positionReference == TOP_LEFT || positionReference == BOTTOM_LEFT) {
//Left Side
x = (int) (outline.getX() + 5);
} else {
//Right Side
x = (int) (mapView.getDisplayWidth() - 18);
}
}
for (Color c: colors) {
colorRect.setRect(x, y, width, height);
g2.setColor(c);
g2.fill(colorRect);
if (horizontal) {
//increment x by the color box width
x += width;
} else {
//increment y by the color box height
y += height;
}
}
if (labels != null) {
g2.setColor(Color.WHITE);
if (labels.size() > 0) {
labelWidth = (float) fontMetrics.getStringBounds(labels.get(labels.size() - 1), g2).getWidth();
labelHeight = (float) fontMetrics.getStringBounds(labels.get(labels.size() - 1), g2).getHeight();
if (horizontal) {
g2.drawString(labels.get(labels.size() - 1), (float) (x - labelWidth), (float) (outline.getY() + 15));
x = (int) (outline.getX() + 5);
y = (int) (outline.getY() + 15);
g2.drawString(labels.get(0), x, y);
} else {
if (positionReference == TOP_LEFT || positionReference == BOTTOM_LEFT) {
x = (int) (outline.getX() + outline.getWidth() - 30);
} else {
x = (int) (outline.getX() + 4);
}
if (labels.size() > 3) {
y = (int) (outline.getY() + 15);
for (int i = 0; i < labels.size(); i++) {
currentLabel = labels.get(i);
labelY = (((height /2f) - (labelHeight / 2f)));
g2.drawString(currentLabel, (x + width + 1), (y + (height * i) + labelY));
}
} else {
y = (int) (outline.getY() + outline.getHeight()) - 8;
g2.drawString(labels.get(labels.size() - 1), x, y);
y = (int) (outline.getY() + 15);
g2.drawString(labels.get(0), x, y);
}
}
}
}
}
public ArrayList<Color> getColors() {
return this.colors;
}
private String getLongestLabel() {
String longestLabel = "";
for (String s: this.labels) {
if (s.length() > longestLabel.length()) {
longestLabel = s;
}
}
return longestLabel;
}
public int getPositionReference() {
return positionReference;
}
public boolean hasHorizontalOrientation() {
return horizontal;
}
@Override
public boolean isObjectWithinRectangle(Rectangle2D range) {
return outline.intersects(range);
}
public void setFillColor(Color c) {
this.fillColor = c;
}
public void setHorizontal(boolean horizontal) {
if (horizontal != this.horizontal) {
//If the key is vertical we should have high values on top
Collections.reverse(colors);
Collections.reverse(labels);
}
this.horizontal = horizontal;
}
public void setOutlineColor(Color c) {
this.outlineColor = c;
}
public void setPositionReference(int ref) {
positionReference = ref;
}
@Override
public void toXML(XmlOutput kmlWriter) {
throw new UnsupportedOperationException("Not supported yet.");
}
}