/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI * for visualizing and manipulating spatial features with geometry and attributes. * * JUMP is Copyright (C) 2003 Vivid Solutions * * This program implements extensions to JUMP and is * Copyright (C) 2004 Integrated Systems Analysts, Inc. * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * For more information, contact: * * Integrated Systems Analysts, Inc. * 630C Anchors St., Suite 101 * Fort Walton Beach, Florida * USA * * (850)862-7321 * www.ashs.isa.com */ package org.openjump.core.ui.plugin.view; import java.awt.Component; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.text.DecimalFormat; import java.util.Iterator; import java.util.List; import org.openjump.core.geomutils.GeoUtils; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateList; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.util.UniqueCoordinateArrayFilter; import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.feature.AttributeType; import com.vividsolutions.jump.feature.Feature; import com.vividsolutions.jump.feature.FeatureCollectionWrapper; import com.vividsolutions.jump.feature.FeatureSchema; import com.vividsolutions.jump.workbench.model.Layer; import com.vividsolutions.jump.workbench.model.LayerManager; import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn; import com.vividsolutions.jump.workbench.plugin.PlugInContext; import com.vividsolutions.jump.workbench.ui.LayerViewPanel; import com.vividsolutions.jump.workbench.ui.TaskFrame; import com.vividsolutions.jump.workbench.ui.ToolTipWriter; public class MapToolTipPlugIn extends AbstractPlugIn { private class GeoData { public String type; public double distance; public int side; public double length; public double angle; public double area; public void set(GeoData geoData) { this.type = geoData.type; this.distance = geoData.distance; this.side = geoData.side; this.length = geoData.length; this.angle = geoData.angle; this.area = geoData.area; } } PlugInContext gContext; final static String sErrorSeeOutputWindow =I18N.get("org.openjump.core.ui.plugin.view.MapToolTipPlugIn.Error-See-Output-Window"); final static String sPoint =I18N.get("org.openjump.core.ui.plugin.view.MapToolTipPlugIn.Point"); final static String sSide =I18N.get("org.openjump.core.ui.plugin.view.MapToolTipPlugIn.Side"); final static String sLength =I18N.get("org.openjump.core.ui.plugin.edittoolbox.cursortools.length"); final static String sAngle =I18N.get("org.openjump.core.ui.plugin.edittoolbox.cursortools.angle"); final static String sDegrees =I18N.get("org.openjump.core.ui.plugin.edittoolbox.cursortools.degrees"); final static String sNoData =I18N.get("org.openjump.core.ui.plugin.view.MapToolTipPlugIn.No-Data"); final static String sArea =I18N.get("org.openjump.core.ui.plugin.edittoolbox.cursortools.area"); final static String pictureSuffix = "_p"; private MouseMotionAdapter mouseMotionAdapter = new MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { if (gContext.getWorkbenchContext().getLayerViewPanel() == null) { return; } //[Jon Aquino 2005-08-04] ToolTipWriter toolTipWriter = new ToolTipWriter(gContext.getWorkbenchContext().getLayerViewPanel()); toolTipWriter.setEnabled(gContext.getWorkbenchContext().getLayerViewPanel().getToolTipWriter().isEnabled()); String fid = toolTipWriter.write("{FID}", e.getPoint()); if (fid != null) { String toolTipText = getData(Integer.parseInt(fid), e.getPoint()); gContext.getWorkbenchContext().getLayerViewPanel().setToolTipText(toolTipText); } } }; public void initialize(final PlugInContext context) throws Exception { gContext = context; context.getWorkbenchFrame().getDesktopPane().addContainerListener( new ContainerListener() { public void componentAdded(ContainerEvent e) { Component child = e.getChild(); if (child.getClass().getName().equals("com.vividsolutions.jump.workbench.ui.TaskFrame")) { ((TaskFrame)child).getLayerViewPanel().addMouseMotionListener(mouseMotionAdapter); } } public void componentRemoved(ContainerEvent e) { Component child = e.getChild(); if (child.getClass().getName().equals("com.vividsolutions.jump.workbench.ui.TaskFrame")) { ((TaskFrame)child).getLayerViewPanel().removeMouseMotionListener(mouseMotionAdapter); } } }); } public boolean execute(PlugInContext context) throws Exception { try { return true; } catch (Exception e) { context.getWorkbenchFrame().warnUser(sErrorSeeOutputWindow); context.getWorkbenchFrame().getOutputFrame().createNewDocument(); context.getWorkbenchFrame().getOutputFrame().addText("MapToolTipPlugIn Exception:" + e.toString()); return false; } } private String getData(int fID, Point2D mouseLocation) { int maxLinesOfData = 10; String dataText = "<html>"; LayerViewPanel panel = gContext.getWorkbenchContext().getLayerViewPanel(); if (panel == null) {return "";} LayerManager layerManager = panel.getLayerManager(); List layerList = layerManager.getVisibleLayers(false); for (Iterator i = layerList.iterator(); i.hasNext();) { Layer layer = (Layer) i.next(); FeatureSchema featureSchema = layer.getFeatureCollectionWrapper().getFeatureSchema(); int numAttribs = featureSchema.getAttributeCount(); FeatureCollectionWrapper featureCollection = layer.getFeatureCollectionWrapper(); List featureList = featureCollection.getFeatures(); //for each layer iterate thru featureList for (Iterator j = featureList.iterator(); j.hasNext();) { Feature feature = (Feature) j.next(); int fid = feature.getID(); if (fid == fID) { Geometry geo = feature.getGeometry(); try { Coordinate coord = panel.getViewport().toModelCoordinate(mouseLocation); dataText += getGeoData(geo, coord); } catch (NoninvertibleTransformException e) { //let it go } int NumLinesOfData = 1; for (int num = 0; num < numAttribs; num++) { AttributeType type = featureSchema.getAttributeType(num); if (type == AttributeType.STRING) { String name = featureSchema.getAttributeName(num); String data = feature.getString(name).trim(); if (name.endsWith(pictureSuffix)) { data = "<img src=\"file:///" + data + "\">"; } if ((!data.equals("")) && (NumLinesOfData < maxLinesOfData)) { dataText += "<br>" + name + ": " + data; NumLinesOfData++; } } } return dataText + "</html>"; } } } dataText += sNoData + "</html>"; return dataText; } private String getGeoData(Geometry geo, Coordinate mousePt) { GeoData geoData = getClosest(geo, mousePt); DecimalFormat df2 = new DecimalFormat("##0.0#"); DecimalFormat df3 = new DecimalFormat("###,###,##0.0##"); String geoText = ""; if (geoData.area > 0) geoText = geoData.type + ": " + sSide + ": " + geoData.side + ", " + sLength + ": " + df3.format(geoData.length) + ", " + sAngle + ": " + df2.format(geoData.angle) + " " + sDegrees + ", " + sArea + ": " + df2.format(geoData.area); else geoText = geoData.type + ": " + sSide + ": " + geoData.side + ", " + sLength + ": " + df3.format(geoData.length) + ", " + sAngle +": " + df2.format(geoData.angle) + " " + sDegrees; if (geoData.type.equals("Point")) geoText = "Point"; return geoText; } private GeoData getClosest(Geometry geo, Coordinate mousePt) { GeoData geoData; if ((geo.getGeometryType().equals("GeometryCollection")) || (geo.getGeometryType().equals("MultiPoint")) || (geo.getGeometryType().equals("MultiLineString")) || (geo.getGeometryType().equals("MultiPolygon"))) { geoData = getClosest(((GeometryCollection)geo).getGeometryN(0), mousePt); for (int i = 1; i < ((GeometryCollection)geo).getNumGeometries(); i++) { GeoData geoData2 = getClosest(((GeometryCollection)geo).getGeometryN(i), mousePt); if (geoData2.distance < geoData.distance) { geoData.set(geoData2); } } } else { geo.getCoordinates(); CoordinateList coords = new CoordinateList(); UniqueCoordinateArrayFilter filter = new UniqueCoordinateArrayFilter(); geo.apply(filter); coords.add( filter.getCoordinates() ,false); //need to do this since UniqueCoordinateArrayFilter keeps the poly from being closed if ((geo instanceof Polygon) || (geo instanceof LinearRing)) { coords.add(coords.getCoordinate(0)); } int maxIndex = coords.size() - 1; int side = 1; double length = 0; double angle = 0; Coordinate p0; Coordinate p1; double distToClosestSide = mousePt.distance(coords.getCoordinate(0)); if (coords.size() > 1) { p0 = coords.getCoordinate(0); p1 = coords.getCoordinate(1); length = p0.distance(p1); angle = GeoUtils.getBearing180(p0, p1); distToClosestSide = GeoUtils.getDistance(mousePt, p0, p1); } for (int i = 1; i < maxIndex; i++) { p0 = coords.getCoordinate(i); p1 = coords.getCoordinate(i+1); double distToSide = GeoUtils.getDistance(mousePt, p0, p1); if (distToSide < distToClosestSide) { side = i + 1; length = p0.distance(p1); angle = GeoUtils.getBearing180(p0, p1); distToClosestSide = distToSide; } } geoData = new GeoData(); geoData.type = geo.getGeometryType(); geoData.side = side; geoData.length = length; geoData.angle = angle; geoData.distance = distToClosestSide; geoData.area = geo.getArea(); } return geoData; } } // this code shows how to add an ItemListener to a menu item // so that you know when a menu item changes // private ItemListener itemListener = // new ItemListener() // { // public void itemStateChanged(ItemEvent e) // { //// String chk = context.getFeatureInstaller().menuBar().getMenu(2).getItem(13).getText(); // java.awt.Toolkit.getDefaultToolkit().beep(); // } // }; // add this to the initializer // context.getFeatureInstaller().menuBar().getMenu(2).getItem(13).addItemListener(itemListener);