/* Copyright (c) 2010, skobbler GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.openstreetmap.josm.plugins.mapdust;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.ImageObserver;
import java.text.DateFormat;
import java.util.List;
import java.util.Locale;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JToolTip;
import org.openstreetmap.josm.actions.RenameLayerAction;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
import org.openstreetmap.josm.gui.MapView;
import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
import org.openstreetmap.josm.gui.layer.Layer;
import org.openstreetmap.josm.plugins.mapdust.gui.MapdustGUI;
import org.openstreetmap.josm.plugins.mapdust.service.value.MapdustBug;
import org.openstreetmap.josm.tools.ImageProvider;
/**
* Defines the MapDust JOSM layer main functionality.
*
* @author Bea
*/
public class MapdustLayer extends Layer {
/** The <code>MapdustGUI</code> object */
private MapdustGUI mapdustGUI;
/** The list of <code>MapdustBugList</code> objects */
private List<MapdustBug> mapdustBugList;
/** The selected <code>MapdustBug</code> object */
private MapdustBug bugSelected;
/**
* Builds a <code>MapdustLayer</code> object based on the given parameters.
*
* @param name The name of the layer
* @param mapdustGUI The <code>MapdustGUI</code> object
* @param mapdustBugList The list of <code>MapdustBug</code> objects
*/
public MapdustLayer(String name, MapdustGUI mapdustGUI,
List<MapdustBug> mapdustBugList) {
super(name);
this.mapdustGUI = mapdustGUI;
this.mapdustBugList = mapdustBugList;
this.bugSelected = null;
}
/**
* Updates the <code>MapdustLayer</code> with the new
* <code>MapdustGUI</code> and <code>MapdustBug</code> list.
*
* @param mapdustGUI The <code>MapdustGUI</code>
* @param mapdustBugList The <code>MapdustBug</code> list
*/
public void update(MapdustGUI mapdustGUI, List<MapdustBug> mapdustBugList) {
this.mapdustGUI = mapdustGUI;
this.mapdustBugList = mapdustBugList;
this.bugSelected = null;
}
/**
* Returns the icon of the MapDust layer.
*
* @return icon
*/
@Override
public Icon getIcon() {
Icon layerIcon = ImageProvider.get("dialogs/mapdust_icon16.png");
return layerIcon;
}
/**
* Returns the info components of the MapDust layer.
*
* @return object
*/
@Override
public Object getInfoComponent() {
String infoComponent = "Shows the Mapdust bug reporter issues.";
return tr(infoComponent);
}
/**
* Returns the menu entries of the MapDust layer.
*
* @return an array of <code>Action</code> objects.
*/
@Override
public Action[] getMenuEntries() {
Action[] menuEntries = new Action[6];
menuEntries[0] =
LayerListDialog.getInstance().createShowHideLayerAction();
menuEntries[1] =
LayerListDialog.getInstance().createDeleteLayerAction();
menuEntries[2] = SeparatorLayerAction.INSTANCE;
menuEntries[3] = new RenameLayerAction(null, this);
menuEntries[4] = SeparatorLayerAction.INSTANCE;
menuEntries[5] = new LayerListPopup.InfoAction(this);
return menuEntries;
}
/**
* Returns the text of the tool tip of the MapDust layer.
*
* @return the tooltip text
*/
@Override
public String getToolTipText() {
String toolTipText = "Shows Mapdust bug reporter issues.";
return tr(toolTipText);
}
/**
* Returns the image icon based on the given status and type.
*
* @param iconType The type of the bug
* @param status The status of the bug
* @param bugType The type of the bug
* @return A <code>ImageIcom</code> object
*/
private ImageIcon getImageIcon(String iconType, String status,
String bugType) {
String iconName = "bugs/" + iconType + "/";
iconName += status.toLowerCase() + "_";
iconName += bugType;
iconName += ".png";
ImageIcon icon = ImageProvider.get(iconName);
return icon;
}
/**
* Draw the objects to the given map view. Also draws the MapDust bugs to
* the map, and the tool-tip for the selected MapDust bug.
*
* @param g The <code>Graphics2D</code> object
* @param mv The <code>MapView</code> object
* @param bounds The <code>Bounds</code> object
*/
@Override
public void paint(Graphics2D g, MapView mv, Bounds bounds) {
JToolTip tooltip = new JToolTip();
if (mapdustBugList != null && mapdustBugList.size() > 0) {
/* draw the current visible bugs */
for (MapdustBug bug : mapdustBugList) {
LatLon ll = bug.getLatLon();
Point p = mv.getPoint(ll);
/* get the icon */
String status = bug.getStatus().getValue();
String type = bug.getType().getKey();
ImageIcon icon = getImageIcon("normal", status, type);
int width = icon.getIconWidth();
int height = icon.getIconHeight();
/*
* need to do drawing 2 times, because in some areas the bug
* image is invisible
*/
for (int i = 0; i < 2; i++) {
g.drawImage(icon.getImage(), p.x - (width / 2), p.y
- (height / 2), new ImageObserver() {
@Override
public boolean imageUpdate(Image img, int infoflags,
int x, int y, int width, int height) {
return false;
}
});
}
}
/* draw the selected bug description */
/* selected by clicking */
MapdustBug clickedBug = getBugSelected();
/* selected from the list */
MapdustBug bugSelected = getMapdustGUI().getSelectedBug();
if (bugSelected == null) {
bugSelected = clickedBug;
}
setBugSelected(bugSelected);
if (bugSelected != null) {
LatLon ll = bugSelected.getLatLon();
Point p = mv.getPoint(ll);
String status = bugSelected.getStatus().getValue();
String type = bugSelected.getType().getKey();
ImageIcon icon = getImageIcon("selected", status, type);
int width = icon.getIconWidth();
int height = icon.getIconHeight();
/* draw the icon */
g.drawImage(icon.getImage(), p.x - (width / 2), p.y
- (height / 2), new ImageObserver() {
@Override
public boolean imageUpdate(Image img, int infoflags, int x,
int y, int width, int height) {
return false;
}
});
/* draw description */
String text = buildTooltipText(bugSelected);
tooltip.setTipText(text);
tooltip.setFont(new Font("Times New Roman", Font.PLAIN, 13));
tooltip.setBackground(Color.WHITE);
tooltip.setForeground(Color.BLUE);
tooltip.setLocation(p);
tooltip.setFocusable(true);
int tx = p.x + (width / 4);
int ty = (p.y + height / 4);
g.translate(tx, ty);
Dimension d = tooltip.getUI().getPreferredSize(tooltip);
d.width = Math.min(d.width, (mv.getWidth() * 2 / 3));
tooltip.setSize(d);
tooltip.paint(g);
g.translate(-tx, -ty);
}
}
}
/**
* No need to implement this.
*/
@Override
public boolean isMergable(Layer layer) {
return false;
}
/**
* No need to implement this.
*/
@Override
public void mergeFrom(Layer layer) {}
/**
* Builds the text of the tool-tip containing a short description of the
* given <code>MapdustBug</code> object.
*
* @param bug The <code>MapdustBug</code> object
* @return A string containing the description text
*/
private String buildTooltipText(MapdustBug bug) {
DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT,
Locale.getDefault());
String text = "<html><b>Type:</b> " + bug.getType().getValue();
text += "<br/>";
text += "<b>Status:</b> " + bug.getStatus().getValue() + "<br/>";
text += "<b>Relevance:</b> " + bug.getRelevance().getName() + "<br/>";
text += "<b>Address:</b> " + bug.getAddress() + " <br/>";
text += "<b>Created by:</b> " + bug.getNickname() + "<br/>";
text += "<b>Created on:</b> " + df.format(bug.getDateCreated());
text += "<br/>";
text += "<b>Last modified on:</b> "+ df.format(bug.getDateUpdated());
text += "<br/>";
text += "<b>Comments:</b> " + bug.getNumberOfComments();
text += "</html>";
return text;
}
/**
* No need to implement this.
*/
@Override
public void visitBoundingBox(BoundingXYVisitor arg0) {}
/**
* Returns the <code>MapdustGUI</code> object
*
* @return the mapdustGUI
*/
public MapdustGUI getMapdustGUI() {
return mapdustGUI;
}
/**
* Sets the <code>MapdustGUI</code> object
*
* @param mapdustGUI the mapdustGUI to set
*/
public void setMapdustGUI(MapdustGUI mapdustGUI) {
this.mapdustGUI = mapdustGUI;
}
/**
* Returns the list of <code>MapdustBug</code> objects
*
* @return the mapdustBugList
*/
public List<MapdustBug> getMapdustBugList() {
return mapdustBugList;
}
/**
* Returns the selected bug
*
* @return the bugSelected
*/
public MapdustBug getBugSelected() {
return bugSelected;
}
/**
* Sets the selected bug
*
* @param bugSelected the bugSelected to set
*/
public void setBugSelected(MapdustBug bugSelected) {
this.bugSelected = bugSelected;
}
/**
* Sets the list of <code>MapdustBug</code> objects
*
* @param mapdustBugList the mapdustBugList to set
*/
public void setMapdustBugList(List<MapdustBug> mapdustBugList) {
this.mapdustBugList = mapdustBugList;
}
}