/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package de.cismet.cismap.commons.gui.piccolo.eventlistener;
import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
import org.apache.log4j.Logger;
import org.jfree.util.Log;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import de.cismet.cismap.commons.features.DefaultStyledFeature;
import de.cismet.cismap.commons.features.SignaturedFeature;
import de.cismet.cismap.commons.gui.MappingComponent;
import de.cismet.cismap.commons.gui.featureinfowidget.FeatureInfoDisplay;
import de.cismet.cismap.commons.gui.featureinfowidget.FeatureInfoWidget;
import de.cismet.cismap.commons.gui.featureinfowidget.MultipleFeatureInfoRequestsDisplay;
import de.cismet.cismap.commons.gui.piccolo.FeatureAnnotationSymbol;
import de.cismet.cismap.commons.gui.piccolo.FixedPImage;
import de.cismet.cismap.commons.gui.piccolo.PFeature;
import de.cismet.cismap.commons.interaction.CismapBroker;
import de.cismet.cismap.commons.interaction.MapClickListener;
import de.cismet.cismap.commons.interaction.events.MapClickedEvent;
/**
* DOCUMENT ME!
*
* @author thorsten.hell@cismet.de
* @version $Revision$, $Date$
*/
public class GetFeatureInfoClickDetectionListener extends PBasicInputEventHandler implements HoldListener {
//~ Static fields/initializers ---------------------------------------------
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(
"de.cismet.cismap.commons.gui.capabilitywidget.CapabilityWidget"); // NOI18N
public static final String FEATURE_INFO_MODE = "FEATURE_INFO_CLICK"; // NOI18N
private static final transient Logger LOG = Logger.getLogger(GetFeatureInfoClickDetectionListener.class);
//~ Instance fields --------------------------------------------------------
private BufferedImage info;
private FixedPImage pInfo;
private double lastClickX = 0;
private double lastClickY = 0;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new instance of GetFeatureInfoClickDetectionListener.
*
* @throws IllegalStateException DOCUMENT ME!
*/
public GetFeatureInfoClickDetectionListener() {
final InputStream is = this.getClass().getResourceAsStream("/de/cismet/cismap/commons/gui/res/featureInfo.png"); // NOI18N
try {
info = ImageIO.read(is);
} catch (IOException ex) {
LOG.warn("Could not load featureInfo icon", ex); // NO18N
}
if (info == null) {
final String msg = "Could not load featureInfoIcon"; // NOI18N
LOG.error(msg);
throw new IllegalStateException(msg);
}
final Graphics2D g2 = (Graphics2D)info.getGraphics();
// g2.setPaint(new Color(255, 85, 85));
// g2.setStroke(new BasicStroke(4));
// g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f));
// g2.drawOval(6, 8, 26, 26);
pInfo = new FixedPImage(new ImageIcon(info).getImage());
getPInfo().setSweetSpotX(0.5d);
getPInfo().setSweetSpotY(1d);
}
//~ Methods ----------------------------------------------------------------
@Override
public void mouseClicked(final edu.umd.cs.piccolo.event.PInputEvent pInputEvent) {
if (pInputEvent.getComponent() instanceof MappingComponent) {
lastClickX = pInputEvent.getPosition().getX();
lastClickY = pInputEvent.getPosition().getY();
boolean paintFeatureInfoIcon = true;
final Vector<MapClickListener> v = CismapBroker.getInstance().getMapClickListeners();
for (final MapClickListener listener : v) {
if (listener instanceof FeatureInfoWidget) {
final FeatureInfoWidget infoWidget = (FeatureInfoWidget)listener;
final Map<Object, FeatureInfoDisplay> displays = infoWidget.getDisplays();
final Collection<FeatureInfoDisplay> c = displays.values();
for (final FeatureInfoDisplay d : c) {
if (d instanceof MultipleFeatureInfoRequestsDisplay) {
final MultipleFeatureInfoRequestsDisplay multiRequestDisplay =
(MultipleFeatureInfoRequestsDisplay)d;
if ( // multiRequestDisplay.isOnHold()&&
multiRequestDisplay.isDisplayVisible()) {
paintFeatureInfoIcon = false;
}
}
}
}
}
if (paintFeatureInfoIcon) {
final MappingComponent mc = (MappingComponent)pInputEvent.getComponent();
mc.addStickyNode(getPInfo());
mc.getRubberBandLayer().removeAllChildren();
mc.getTmpFeatureLayer().removeAllChildren();
// pInfo = new PImage(info.getImage());
mc.getRubberBandLayer().addChild(getPInfo());
getPInfo().setScale(1 / mc.getCamera().getViewScale());
getPInfo().setOffset(pInputEvent.getPosition().getX(), pInputEvent.getPosition().getY());
if (log.isDebugEnabled()) {
log.debug(getPInfo().getGlobalBounds().getWidth());
}
getPInfo().setVisible(true);
// mc.getCasmera().animateViewToCenterBounds(pInfo.getBounds(),true,1000);
getPInfo().repaint();
mc.repaint();
}
}
CismapBroker.getInstance().fireClickOnMap(new MapClickedEvent(FEATURE_INFO_MODE, pInputEvent));
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public FixedPImage getPInfo() {
return pInfo;
}
@Override
public void holdFeaturesChanged(final HoldFeatureChangeEvent evt) {
showCustomFeatureInfo(evt.getHoldFeatures(), evt.getMultipleFeautureInfoRequestDisplay());
}
/**
* DOCUMENT ME!
*
* @param c DOCUMENT ME!
* @param display DOCUMENT ME!
*
* @throws IllegalStateException DOCUMENT ME!
*/
private void showCustomFeatureInfo(final Collection<SignaturedFeature> c,
final MultipleFeatureInfoRequestsDisplay display) {
final MappingComponent mc = CismapBroker.getInstance().getMappingComponent();
// TODO if !display.isOnHold paint the standard icon...
if ( /*!display.isOnHold()*/
!display.isDisplayVisible()
|| ((c == null) || c.isEmpty())) {
if (LOG.isDebugEnabled()) {
LOG.debug(
"MultipleFeauteInfoRequestsDisplay is not on hold or holdFeautureCollection is null or empty."); // NOI18N
}
return;
} else {
mc.getRubberBandLayer().removeAllChildren();
mc.getTmpFeatureLayer().removeAllChildren();
BufferedImage featureInfoIcon = null;
BufferedImage lastFeatureInfoIcon = null;
BufferedImage originalFeatureInfoIcon = null;
InputStream is = this.getClass().getResourceAsStream("/de/cismet/cismap/commons/gui/res/featureInfo.png"); // NOI18N
try {
originalFeatureInfoIcon = ImageIO.read(is);
is.close();
is = this.getClass().getResourceAsStream("/de/cismet/cismap/commons/gui/res/featureInfo.png");
featureInfoIcon = ImageIO.read(is);
is.close();
is = this.getClass().getResourceAsStream("/de/cismet/cismap/commons/gui/res/lastFeatureInfo.png");
if (is != null) {
lastFeatureInfoIcon = ImageIO.read(is);
is.close();
}
} catch (IOException ex) {
LOG.warn("Could not load featureInfo icon", ex); // NO18N
}
if (featureInfoIcon == null) {
final String msg = "Could not load featureInfoIcon"; // NOI18N
LOG.error(msg);
throw new IllegalStateException(msg);
} else if (lastFeatureInfoIcon == null) {
final String msg = "Could not load lastFeatureInfoIcon"; // NOI18N
LOG.error(msg);
}
// set default values for the overlay area to the upper right edge of the icon..
int width = 16;
int height = 16;
int xPos = featureInfoIcon.getWidth() - width;
int yPos = 0;
int bgR = 255;
int bgG = 255;
int bgB = 255;
Color standardBG = new Color(bgR, bgG, bgB, 1);
int lastBGR = 255;
int lastBGG = 255;
int lastBGB = 255;
Color lastBG = new Color(lastBGR, lastBGG, lastBGB, 1);
BufferedImage subimage = featureInfoIcon.getSubimage(xPos, yPos, width, height);
Graphics2D g2d = (Graphics2D)subimage.getGraphics();
// try to get metainformation for overlay position, width, color from properties file and override the
// default values if succesfull
final Properties iconProps = new Properties();
try {
final InputStream in = getClass().getResourceAsStream(
"/de/cismet/cismap/commons/gui/res/featureInfoIcon.properties"); // NOI18N
if (in != null) {
iconProps.load(in);
in.close();
} else {
LOG.warn(
"Could not laod featureInfoIcon.properties file. Default values for overlay area are used"); // NOI18N
}
} catch (IOException ex) {
LOG.error(
"Could not read featureInfoIcon.properties file. Default values for overlay area are used",
ex); // NOI18N
}
if (iconProps.isEmpty()
|| !(iconProps.containsKey("overlayPositionX")
&& iconProps.containsKey("overlayPositionY") // NOI18N
&& iconProps.containsKey("overlayWidth") && iconProps.containsKey("overlayHeigth") // NOI18N
&& iconProps.containsKey("overlayBackgroundColorR") // NOI18N
&& iconProps.containsKey("overlayBackgroundColorG") // NOI18N
&& iconProps.containsKey("overlayBackgroundColorB")
&& iconProps.containsKey("lastOverlayBackgroundColorR") // NOI18N
&& iconProps.containsKey("lastOverlayBackgroundColorG") // NOI18N
&& iconProps.containsKey("lastOverlayBackgroundColorB"))) { // NOI18N
LOG.warn(
"featureInfoIcon.properties file does not contain all needed keys. Default values for overlay area are used"); // NOI18N
} else {
try {
xPos = Integer.parseInt((String)iconProps.get("overlayPositionX")); // NOI18N
yPos = Integer.parseInt((String)iconProps.get("overlayPositionY")); // NOI18N
width = Integer.parseInt((String)iconProps.get("overlayWidth")); // NOI18N
height = Integer.parseInt((String)iconProps.get("overlayHeigth")); // NOI18N
bgR = Integer.parseInt((String)iconProps.get("overlayBackgroundColorR")); // NOI18N
bgG = Integer.parseInt((String)iconProps.get("overlayBackgroundColorG")); // NOI18N
bgB = Integer.parseInt((String)iconProps.get("overlayBackgroundColorB")); // NOI18N
lastBGR = Integer.parseInt((String)iconProps.get("lastOverlayBackgroundColorR")); // NOI18N
lastBGG = Integer.parseInt((String)iconProps.get("lastOverlayBackgroundColorG")); // NOI18N
lastBGB = Integer.parseInt((String)iconProps.get("lastOverlayBackgroundColorB")); // NOI18N
subimage = featureInfoIcon.getSubimage(xPos, yPos, width, height);
standardBG = new Color(bgR, bgG, bgB);
lastBG = new Color(lastBGR, lastBGG, lastBGB);
g2d = (Graphics2D)subimage.getGraphics();
} catch (NumberFormatException ex) {
Log.error(
"Error while retrieving properties for overlay area. Default values for overlay area are used", // NOI18N
ex);
} catch (Exception e) {
Log.error(
"Could not compute ovaerlay area for feature Info Icon.Default Area is used. Maybe you should check the properties in the properties file", // NOI18N
e);
}
}
// add a node for each SignaturedFeature to the map
int nr = 0;
for (final SignaturedFeature f : c) {
final DefaultStyledFeature dsf = new DefaultStyledFeature();
final FeatureAnnotationSymbol symb;
if (f.getOverlayIcon() == null) {
// paint standard overlay, little circle and a number within or so...
symb = new FeatureAnnotationSymbol(originalFeatureInfoIcon);
Log.warn(
"OverlayIcon for MultipleFeautreInfoRequestDisplay is null, default FeatureInfoIcon is used"); // NOI18N
} else {
if ((nr == (c.size() - 1)) && (lastFeatureInfoIcon != null)) {
// default
g2d = (Graphics2D)lastFeatureInfoIcon.getSubimage(lastFeatureInfoIcon.getWidth() - 16,
0,
16,
16).getGraphics();
try {
g2d = (Graphics2D)lastFeatureInfoIcon.getSubimage(xPos, yPos, width, height).getGraphics();
} catch (Exception e) {
Log.error(
"Could not compute ovaerlay area for lastFeatureInfoIcon. Default Area is used. Maybe you should check the properties in the properties file", // NOI18N
e);
}
g2d.drawImage(f.getOverlayIcon(), 0, 0, lastBG, null);
symb = new FeatureAnnotationSymbol(lastFeatureInfoIcon);
} else {
g2d.drawImage(f.getOverlayIcon(), 0, 0, standardBG, null);
symb = new FeatureAnnotationSymbol(featureInfoIcon);
}
}
symb.setSweetSpotX(0.5);
symb.setSweetSpotY(0.9);
dsf.setPointAnnotationSymbol(symb);
dsf.setGeometry(f.getGeometry());
final PFeature pf = new PFeature(dsf, mc);
mc.getTmpFeatureLayer().addChild(pf);
nr++;
}
mc.rescaleStickyNodes();
mc.repaint();
}
}
/**
* DOCUMENT ME!
*/
public void addFeatureInfoIconForLastClick() {
final MappingComponent mc = CismapBroker.getInstance().getMappingComponent();
mc.addStickyNode(getPInfo());
mc.getRubberBandLayer().removeAllChildren();
mc.getTmpFeatureLayer().removeAllChildren();
// pInfo = new PImage(info.getImage());
mc.getRubberBandLayer().addChild(getPInfo());
getPInfo().setScale(1 / mc.getCamera().getViewScale());
getPInfo().setOffset(lastClickX, lastClickY);
if (log.isDebugEnabled()) {
log.debug(getPInfo().getGlobalBounds().getWidth());
}
getPInfo().setVisible(true);
// mc.getCasmera().animateViewToCenterBounds(pInfo.getBounds(),true,1000);
getPInfo().repaint();
mc.repaint();
}
}