/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package de.cismet.cismap.commons.gui;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import edu.umd.cs.piccolo.*;
import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.event.PInputEventListener;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.util.PAffineTransform;
import edu.umd.cs.piccolo.util.PBounds;
import edu.umd.cs.piccolo.util.PPaintContext;
import org.apache.log4j.Logger;
import org.jdom.Attribute;
import org.jdom.DataConversionException;
import org.jdom.Element;
import org.openide.util.NbBundle;
import pswing.PSwingCanvas;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import javax.swing.*;
import javax.swing.Timer;
import de.cismet.cismap.commons.*;
import de.cismet.cismap.commons.features.*;
import de.cismet.cismap.commons.featureservice.DocumentFeatureService;
import de.cismet.cismap.commons.featureservice.JDBCFeatureService;
import de.cismet.cismap.commons.featureservice.WebFeatureService;
import de.cismet.cismap.commons.gui.layerwidget.ActiveLayerModel;
import de.cismet.cismap.commons.gui.piccolo.*;
import de.cismet.cismap.commons.gui.piccolo.eventlistener.*;
import de.cismet.cismap.commons.gui.printing.PrintingSettingsWidget;
import de.cismet.cismap.commons.gui.printing.PrintingWidget;
import de.cismet.cismap.commons.gui.printing.Scale;
import de.cismet.cismap.commons.gui.progresswidgets.DocumentProgressWidget;
import de.cismet.cismap.commons.gui.simplelayerwidget.LayerControl;
import de.cismet.cismap.commons.gui.simplelayerwidget.NewSimpleInternalLayerWidget;
import de.cismet.cismap.commons.interaction.CismapBroker;
import de.cismet.cismap.commons.interaction.CrsChangeListener;
import de.cismet.cismap.commons.interaction.GetFeatureInfoListener;
import de.cismet.cismap.commons.interaction.events.CrsChangedEvent;
import de.cismet.cismap.commons.interaction.events.MapDnDEvent;
import de.cismet.cismap.commons.interaction.events.StatusEvent;
import de.cismet.cismap.commons.interaction.memento.Memento;
import de.cismet.cismap.commons.interaction.memento.MementoInterface;
import de.cismet.cismap.commons.preferences.CismapPreferences;
import de.cismet.cismap.commons.preferences.GlobalPreferences;
import de.cismet.cismap.commons.preferences.LayersPreferences;
import de.cismet.cismap.commons.rasterservice.FeatureAwareRasterService;
import de.cismet.cismap.commons.rasterservice.MapService;
import de.cismet.cismap.commons.rasterservice.RasterMapService;
import de.cismet.cismap.commons.retrieval.AbstractRetrievalService;
import de.cismet.cismap.commons.retrieval.RepaintEvent;
import de.cismet.cismap.commons.retrieval.RepaintListener;
import de.cismet.cismap.commons.retrieval.RetrievalEvent;
import de.cismet.cismap.commons.retrieval.RetrievalListener;
import de.cismet.tools.CismetThreadPool;
import de.cismet.tools.CurrentStackTrace;
import de.cismet.tools.StaticDebuggingTools;
import de.cismet.tools.configuration.Configurable;
import de.cismet.tools.gui.StaticSwingTools;
import de.cismet.tools.gui.WaitDialog;
import de.cismet.tools.gui.historybutton.DefaultHistoryModel;
import de.cismet.tools.gui.historybutton.HistoryModel;
import static java.lang.Thread.sleep;
/**
* DOCUMENT ME!
*
* @author thorsten.hell@cismet.de
* @version $Revision$, $Date$
*/
public final class MappingComponent extends PSwingCanvas implements MappingModelListener,
FeatureCollectionListener,
HistoryModel,
Configurable,
DropTargetListener,
CrsChangeListener {
//~ Static fields/initializers ---------------------------------------------
/** Wenn false, werden alle debug statements vom compiler wegoptimiert. */
private static final boolean DEBUG = Debug.DEBUG;
public static final String PROPERTY_MAP_INTERACTION_MODE = "INTERACTION_MODE"; // NOI18N
public static final String MOTION = "MOTION"; // NOI18N
public static final String PERPENDICULAR_INTERSECTION = "PERPENDICULAR_INTERSECTION"; // NOI18N
public static final String SELECT = "SELECT"; // NOI18N
public static final String GEO_REF = "GEO_REF"; // NOI18N
public static final String ZOOM = "ZOOM"; // NOI18N
public static final String PAN = "PAN"; // NOI18N
public static final String ALKIS_PRINT = "ALKIS_PRINT"; // NOI18N
public static final String FEATURE_INFO = "FEATURE_INFO"; // NOI18N
public static final String FEATURE_INFO_MULTI_GEOM = "FEATURE_INFO_MULTI_GEOM"; // NOI18N
public static final String CREATE_SEARCH_POLYGON = "SEARCH_POLYGON"; // NOI18N
public static final String CREATE_SIMPLE_GEOMETRY = "CREATE_SIMPLE_GEOMETRY"; // NOI18N
public static final String MOVE_POLYGON = "MOVE_POLYGON"; // NOI18N
public static final String REMOVE_POLYGON = "REMOVE_POLYGON"; // NOI18N
public static final String NEW_POLYGON = "NEW_POLYGON"; // NOI18N
public static final String SPLIT_POLYGON = "SPLIT_POLYGON"; // NOI18N
public static final String JOIN_POLYGONS = "JOIN_POLYGONS"; // NOI18N
public static final String RAISE_POLYGON = "RAISE_POLYGON"; // NOI18N
public static final String ROTATE_POLYGON = "ROTATE_POLYGON"; // NOI18N
public static final String REFLECT_POLYGON = "REFLECT_POLYGON"; // NOI18N
public static final String ATTACH_POLYGON_TO_ALPHADATA = "ATTACH_POLYGON_TO_ALPHADATA"; // NOI18N
public static final String MOVE_HANDLE = "MOVE_HANDLE"; // NOI18N
public static final String REMOVE_HANDLE = "REMOVE_HANDLE"; // NOI18N
public static final String ADD_HANDLE = "ADD_HANDLE"; // NOI18N
public static final String MEASUREMENT = "MEASUREMENT"; // NOI18N
public static final String LINEAR_REFERENCING = "LINEMEASUREMENT"; // NOI18N
public static final String PRINTING_AREA_SELECTION = "PRINTING_AREA_SELECTION"; // NOI18N
public static final String CUSTOM_FEATUREACTION = "CUSTOM_FEATUREACTION"; // NOI18N
public static final String CUSTOM_FEATUREINFO = "CUSTOM_FEATUREINFO"; // NOI18N
public static final String OVERVIEW = "OVERVIEW"; // NOI18N
static final double OGC_DEGREE_TO_METERS = 6378137.0 * 2.0 * Math.PI / 360;
private static MappingComponent THIS;
/** Name of the internal Simple Layer Widget. */
public static final String LAYERWIDGET = "SimpleInternalLayerWidget"; // NOI18N
/** Name of the internal Document Progress Widget. */
public static final String PROGRESSWIDGET = "DocumentProgressWidget"; // NOI18N
/** Internat Widget at position north west. */
public static final int POSITION_NORTHWEST = 1;
/** Internat Widget at position south west. */
public static final int POSITION_SOUTHWEST = 2;
/** Internat Widget at position north east. */
public static final int POSITION_NORTHEAST = 4;
/** Internat Widget at position south east. */
public static final int POSITION_SOUTHEAST = 8;
/** Delay after a compoent resize event triggers a service reload request. */
private static final int RESIZE_DELAY = 500;
/** If a document exceeds the criticalDocumentSize, the document progress widget is displayed. */
private static final long criticalDocumentSize = 10000000; // 10MB
private static final transient Logger LOG = Logger.getLogger(MappingComponent.class);
//~ Instance fields --------------------------------------------------------
private boolean featureServiceLayerVisible = true;
private final List<LayerControl> layerControls = new ArrayList<LayerControl>();
private boolean gridEnabled = true;
private MappingModel mappingModel;
private ConcurrentHashMap<Feature, PFeature> pFeatureHM = new ConcurrentHashMap<Feature, PFeature>();
private WorldToScreenTransform wtst = null;
private double clip_offset_x;
private double clip_offset_y;
private double printingResolution = 0d;
private boolean backgroundEnabled = true;
private PLayer featureLayer = new PLayer();
private PLayer tmpFeatureLayer = new PLayer();
private PLayer mapServicelayer = new PLayer();
private PLayer featureServiceLayer = new PLayer();
private PLayer handleLayer = new PLayer();
private PLayer snapHandleLayer = new PLayer();
private PLayer rubberBandLayer = new PLayer();
private PLayer highlightingLayer = new PLayer();
private PLayer crosshairLayer = new PLayer();
private PLayer stickyLayer = new PLayer();
private PLayer dragPerformanceImproverLayer = new PLayer();
private boolean readOnly = true;
private boolean snappingEnabled = true;
private boolean snappingOnLineEnabled = false;
private boolean visualizeSnappingEnabled = true;
private boolean visualizeSnappingRectEnabled = false;
private int snappingRectSize = 20;
private final Map<String, Cursor> cursors = new HashMap<String, Cursor>();
private final Map<String, PBasicInputEventHandler> inputEventListener =
new HashMap<String, PBasicInputEventHandler>();
private final Action zoomAction;
private int acceptableActions = DnDConstants.ACTION_COPY_OR_MOVE;
private FeatureCollection featureCollection;
private boolean infoNodesVisible = false;
private boolean fixedMapExtent = false;
private boolean fixedMapScale = false;
private boolean inGlueIdenticalPointsMode = true;
/** Holds value of property interactionMode. */
private String interactionMode;
/** Holds value of property handleInteractionMode. */
private String handleInteractionMode;
// "Phantom PCanvas" der nie selbst dargestellt wird
// wird nur dazu benutzt das Graphics Objekt up to date
// zu halten und dann als Hintergrund von z.B. einem
// Panel zu fungieren
// coooooooool, was ? ;-)
private final PCanvas selectedObjectPresenter = new PCanvas();
// private BoundingBox currentBoundingBox = null;
private Rectangle2D newViewBounds;
private int animationDuration = 500;
private int taskCounter = 0;
private CismapPreferences cismapPrefs;
private DefaultHistoryModel historyModel = new DefaultHistoryModel();
// Scales
private final List<Scale> scales = new ArrayList<Scale>();
// Printing
private PrintingSettingsWidget printingSettingsDialog;
private PrintingWidget printingDialog;
// Scalebar
private double screenResolution = 100.0;
private volatile boolean locked = true;
private final List<PSticky> stickyPNodes = Collections.synchronizedList(new ArrayList<PSticky>());
// Undo- & Redo-Stacks
private final MementoInterface memUndo = new Memento();
private final MementoInterface memRedo = new Memento();
private boolean featureDebugging = false;
private BoundingBox fixedBoundingBox = null;
// Object handleFeatureServiceBlocker = new Object();
private final List<MapListener> mapListeners = new ArrayList<MapListener>();
/** Contains the internal widgets. */
private final Map<String, JInternalFrame> internalWidgets = new HashMap<String, JInternalFrame>();
/** Contains the positions of the internal widgets. */
private final Map<String, Integer> internalWidgetPositions = new HashMap<String, Integer>();
/** The timer that delays the reload requests. */
private Timer delayedResizeEventTimer = null;
private DocumentProgressListener documentProgressListener = null;
private List<Crs> crsList = new ArrayList<Crs>();
private CrsTransformer transformer;
private boolean resetCrs = false;
private final Timer showHandleDelay;
private final Map<MapService, Future<?>> serviceFuturesMap = new HashMap<MapService, Future<?>>();
/** Utility field used by bound properties. */
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
private ButtonGroup interactionButtonGroup;
private boolean mainMappingComponent = false;
private volatile boolean rescaleStickyNodesEnabled = true;
private volatile int retrievalCompleteInProgressCount = 0;
private double featurePrintingDpi = PrintingSettingsWidget.FEATURE_RESOLUTION_FACTOR;
/**
* Creates new PFeatures for all features in the given array and adds them to the PFeatureHashmap. Then adds the
* PFeature to the featurelayer.
*
* <p>DANGER: there's a bug risk here because the method runs in an own thread! It is possible that a PFeature of a
* feature is demanded but not yet added to the hashmap which causes in most cases a NullPointerException!</p>
*
* @param features array with features to add
*/
private final HashMap<String, PLayer> featureGrpLayerMap = new HashMap<String, PLayer>();
private BoundingBox initialBoundingBox;
private WaitDialog crsChangedWaitingDialog = null;
private final ArrayList<RepaintListener> repaintListeners = new ArrayList<RepaintListener>();
private boolean resizeEventActivated = true;
private double stickyFeatureCorrectionFactor = 1d;
private volatile Coordinate currentCrosshairPoint;
private Thread specialFeatureZoomThread;
private long specialFeatureZoomTime;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new instance of MappingComponent.
*/
public MappingComponent() {
this(false);
}
/**
* Creates a new MappingComponent object.
*
* @param mainMappingComponent DOCUMENT ME!
*/
public MappingComponent(final boolean mainMappingComponent) {
super();
this.mainMappingComponent = mainMappingComponent;
locked = true;
THIS = this;
// wird in der Regel wieder ueberschrieben
setSnappingRectSize(20);
setSnappingEnabled(false);
setVisualizeSnappingEnabled(false);
setAnimationDuration(500);
setInteractionMode(ZOOM);
showHandleDelay = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
showHandles(false);
}
});
showHandleDelay.setRepeats(false);
featureDebugging = StaticDebuggingTools.checkHomeForFile("cismetTurnOnFeatureDebugging"); // NOI18N
setFeatureCollection(new DefaultFeatureCollection());
addMapListener((DefaultFeatureCollection)getFeatureCollection());
final DropTarget dt = new DropTarget(this, acceptableActions, this);
setDefaultRenderQuality(PPaintContext.LOW_QUALITY_RENDERING);
setAnimatingRenderQuality(PPaintContext.LOW_QUALITY_RENDERING);
removeInputEventListener(getPanEventHandler());
removeInputEventListener(getZoomEventHandler());
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(final ComponentEvent evt) {
if (resizeEventActivated) {
if (MappingComponent.this.delayedResizeEventTimer == null) {
delayedResizeEventTimer = new Timer(RESIZE_DELAY, new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
delayedResizeEventTimer.stop();
delayedResizeEventTimer = null;
// perform delayed resize:
// rescape map + move widgets + reload services
componentResizedDelayed();
}
});
delayedResizeEventTimer.start();
} else {
// perform intermediate resize:
// rescape map + move widgets
componentResizedIntermediate();
delayedResizeEventTimer.restart();
}
}
}
});
final PRoot root = getRoot();
final PCamera otherCamera = new PCamera();
otherCamera.addLayer(featureLayer);
selectedObjectPresenter.setCamera(otherCamera);
root.addChild(otherCamera);
getLayer().addChild(mapServicelayer);
getLayer().addChild(featureServiceLayer);
getLayer().addChild(featureLayer);
getLayer().addChild(tmpFeatureLayer);
getLayer().addChild(rubberBandLayer);
getLayer().addChild(crosshairLayer);
getLayer().addChild(highlightingLayer);
getLayer().addChild(dragPerformanceImproverLayer);
getCamera().addLayer(mapServicelayer);
getCamera().addLayer(featureLayer);
getCamera().addLayer(tmpFeatureLayer);
getCamera().addLayer(rubberBandLayer);
getCamera().addLayer(crosshairLayer);
getCamera().addLayer(highlightingLayer);
getCamera().addLayer(dragPerformanceImproverLayer);
getCamera().addChild(snapHandleLayer);
getCamera().addChild(handleLayer);
getCamera().addChild(stickyLayer);
handleLayer.moveToFront();
otherCamera.setTransparency(0.05f);
initInputListener();
initCursors();
addInputEventListener(getInputListener(MOTION));
addInputEventListener(getInputListener(CUSTOM_FEATUREACTION));
final KeyboardListener k = new KeyboardListener(this);
addInputEventListener(k);
getRoot().getDefaultInputManager().setKeyboardFocus(k);
setInteractionMode(ZOOM);
setHandleInteractionMode(MOVE_HANDLE);
dragPerformanceImproverLayer.setVisible(false);
historyModel.setMaximumPossibilities(30);
zoomAction = new AbstractAction() {
{
putValue(
Action.NAME,
org.openide.util.NbBundle.getMessage(
MappingComponent.class,
"MappingComponent.zoomAction.NAME")); // NOI18N
putValue(
Action.SMALL_ICON,
new ImageIcon(getClass().getResource("/de/cismet/cismap/commons/raster/wms/res/layers.png"))); // NOI18N
putValue(
Action.SHORT_DESCRIPTION,
org.openide.util.NbBundle.getMessage(
MappingComponent.class,
"MappingComponent.zoomAction.SHORT_DESCRIPTION")); // NOI18N
putValue(
Action.LONG_DESCRIPTION,
org.openide.util.NbBundle.getMessage(
MappingComponent.class,
"MappingComponent.zoomAction.LONG_DESCRIPTION")); // NOI18N
putValue(Action.MNEMONIC_KEY, Integer.valueOf('Z')); // NOI18N
putValue(Action.ACTION_COMMAND_KEY, "zoom.action"); // NOI18N
}
@Override
public void actionPerformed(final ActionEvent event) {
zoomAction.putValue(
Action.SMALL_ICON,
new ImageIcon(getClass().getResource("/de/cismet/cismap/commons/raster/wms/res/server.png"))); // NOI18N
setInteractionMode(MappingComponent.ZOOM);
}
};
this.getCamera().addPropertyChangeListener(PCamera.PROPERTY_VIEW_TRANSFORM, new PropertyChangeListener() {
private double lastScale = -1;
@Override
public void propertyChange(final PropertyChangeEvent evt) {
final PAffineTransform transform = ((PAffineTransform)evt.getNewValue());
checkAndFixErroneousTransformation();
handleLayer.removeAllChildren();
showHandleDelay.restart();
if ((transform == null) || (lastScale != transform.getScale())) {
rescaleStickyNodes();
}
if (transform != null) {
lastScale = transform.getScale();
}
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.SCALE, interactionMode));
}
});
}
//~ Methods ----------------------------------------------------------------
/**
* If <code>resizeEventActivated</code> is true, then the mapping component makes a new query for its services, when
* it is resized. This happens for example if the window of the mapping component is resized. The default value for
* <code>resizeEventActivated</code> is true.
*
* @return DOCUMENT ME!
*/
public boolean isResizeEventActivated() {
return resizeEventActivated;
}
/**
* Set <code>resizeEventActivated</code> to true so that the mapping component makes a query for its services on a
* resize event (Such an event is for example fired when the window of the mapping component is resized). The
* default value for <code>resizeEventActivated</code> is true.
*
* @param resizeEventActivated DOCUMENT ME!
*/
public void setResizeEventActivated(final boolean resizeEventActivated) {
this.resizeEventActivated = resizeEventActivated;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public ButtonGroup getInteractionButtonGroup() {
return interactionButtonGroup;
}
/**
* DOCUMENT ME!
*
* @param interactionButtonGroup DOCUMENT ME!
*/
public void setInteractionButtonGroup(final ButtonGroup interactionButtonGroup) {
this.interactionButtonGroup = interactionButtonGroup;
}
/**
* DOCUMENT ME!
*
* @param mapListener DOCUMENT ME!
*/
public void addMapListener(final MapListener mapListener) {
if (mapListener != null) {
mapListeners.add(mapListener);
}
}
/**
* DOCUMENT ME!
*
* @param mapListener DOCUMENT ME!
*/
public void removeMapListener(final MapListener mapListener) {
if (mapListener != null) {
mapListeners.remove(mapListener);
}
}
/**
* DOCUMENT ME!
*/
public void dispose() {
CismapBroker.getInstance().removeCrsChangeListener(this);
getFeatureCollection().removeAllFeatures();
}
/**
* DOCUMENT ME!
*
* @return true, if debug-messages are logged.
*/
public boolean isFeatureDebugging() {
return featureDebugging;
}
/**
* Creates printingDialog and printingSettingsDialog.
*/
public void initPrintingDialogs() {
printingSettingsDialog = new PrintingSettingsWidget(true, this);
printingDialog = new PrintingWidget(true, this);
}
/**
* Returns the momentary image of the PCamera of this MappingComponent.
*
* @return Image
*/
public Image getImage() {
// this.getCamera().print();
return this.getCamera().toImage(this.getWidth(), this.getHeight(), Color.white);
}
/**
* Adds the given PCamera to the PRoot of this MappingComponent.
*
* @param cam PCamera-object
*/
public void addToPRoot(final PCamera cam) {
getRoot().addChild(cam);
}
/**
* Adds a PNode to the StickyNode-vector.
*
* @param pn PNode-object
*/
public void addStickyNode(final PSticky pn) {
// if(DEBUG)log.debug("addStickyNode:" + pn);
if (pn != null) {
stickyPNodes.add(pn);
}
}
/**
* Removes a specific PNode from the StickyNode-vector.
*
* @param pn PNode that should be removed
*/
public void removeStickyNode(final PSticky pn) {
stickyPNodes.remove(pn);
}
/**
* DOCUMENT ME!
*
* @param specialFeatureClass DOCUMENT ME!
*/
public void adjustMapForSpecialFeatureClasses(final Class specialFeatureClass) {
final int delayTime = 500;
specialFeatureZoomTime = System.currentTimeMillis() + delayTime;
if ((specialFeatureZoomThread == null) || !specialFeatureZoomThread.isAlive()) {
specialFeatureZoomThread = new Thread("specialFeatureZoomThread for:"
+ specialFeatureClass.getCanonicalName()) {
@Override
public void run() {
while (System.currentTimeMillis() < specialFeatureZoomTime) {
try {
sleep(100);
// log.debug("WAIT");
} catch (InterruptedException iex) {
}
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ensureVisibilityOfSpecialFeatures(specialFeatureClass);
}
});
}
};
specialFeatureZoomThread.setPriority(Thread.NORM_PRIORITY);
CismetThreadPool.execute(specialFeatureZoomThread);
}
}
/**
* DOCUMENT ME!
*
* @param specialFeatureClass DOCUMENT ME!
* @param fixedScale DOCUMENT ME!
*/
public void ensureVisibilityOfSpecialFeatures(final Class specialFeatureClass, final boolean fixedScale) {
if (!isFixedMapExtent()) {
zoomToAFeatureCollection(getSpecialFeatureCollection(specialFeatureClass),
false,
fixedScale);
}
}
/**
* DOCUMENT ME!
*
* @param specialFeatureClass DOCUMENT ME!
*/
public void ensureVisibilityOfSpecialFeatures(final Class specialFeatureClass) {
ensureVisibilityOfSpecialFeatures(specialFeatureClass, isFixedMapScale());
}
/**
* DOCUMENT ME!
*
* @param <T> DOCUMENT ME!
* @param featureclass DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public <T extends Feature> Collection<T> getSpecialFeatureCollection(final Class<T> featureclass) {
final ArrayList<T> fc = new ArrayList<>();
for (final Feature f : getFeatureCollection().getAllFeatures()) {
if (featureclass.isInstance(f)) {
fc.add((T)f);
}
}
return fc;
}
/**
* DOCUMENT ME!
*
* @return Vector<PNode> with all sticky PNodes
*/
public List<PSticky> getStickyNodes() {
return stickyPNodes;
}
/**
* Calls private method rescaleStickyNodeWork(node) to rescale the sticky PNode. Forces the execution to the EDT.
*
* @param n PNode to rescale
*/
public void rescaleStickyNode(final PSticky n) {
if (rescaleStickyNodesEnabled && (n != null)) {
if (!EventQueue.isDispatchThread()) {
EventQueue.invokeLater(new Thread("MappingComponent rescaleStickyNode()") {
@Override
public void run() {
rescaleStickyNodeWork(n);
}
});
} else {
rescaleStickyNodeWork(n);
}
}
}
/**
* Calls private method rescaleStickyNodeWork(node) to rescale the sticky PNode. Forces the execution to the EDT.
*
* @param nodes n PNode to rescale
*/
public void rescaleStickyNodes(final List<PSticky> nodes) {
if ((nodes != null) && !nodes.isEmpty()) {
if (!EventQueue.isDispatchThread()) {
EventQueue.invokeLater(new Thread("MappingComponent rescaleStickyNodes()") {
@Override
public void run() {
final List<PSticky> nodesCopy = new ArrayList<PSticky>(nodes);
for (final PSticky node : nodesCopy) {
rescaleStickyNodeWork(node);
}
}
});
} else {
final List<PSticky> nodesCopy = new ArrayList<PSticky>(nodes);
for (final PSticky node : nodesCopy) {
rescaleStickyNodeWork(node);
}
}
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private double getPrintingResolution() {
return this.printingResolution;
}
/**
* DOCUMENT ME!
*
* @param printingResolution DOCUMENT ME!
*/
public void setPrintingResolution(final double printingResolution) {
this.printingResolution = printingResolution;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public double getStickyFeatureCorrectionFactor() {
return stickyFeatureCorrectionFactor;
}
/**
* DOCUMENT ME!
*
* @param stickyFeatureCorrectionFactor DOCUMENT ME!
*/
public void setStickyFeatureCorrectionFactor(final double stickyFeatureCorrectionFactor) {
this.stickyFeatureCorrectionFactor = stickyFeatureCorrectionFactor;
}
/**
* Sets the scale of the given PNode to the value of the camera scale.
*
* @param n PNode to rescale
*/
private void rescaleStickyNodeWork(final PSticky n) {
final double s = MappingComponent.this.getCamera().getViewScale();
n.setScale(getStickyFeatureCorrectionFactor() / s);
}
/**
* Rescales all nodes inside the StickyNode-vector.
*/
public void rescaleStickyNodes() {
if (rescaleStickyNodesEnabled) {
final List<PSticky> stickyNodeList = new ArrayList<PSticky>();
final List<PSticky> stickyNodeCopy = new ArrayList<PSticky>(getStickyNodes());
for (final PSticky each : stickyNodeCopy) {
if ((each instanceof PSticky) && each.getVisible()) {
stickyNodeList.add(each);
} else if ((each.getParent() == null)) {
removeStickyNode(each);
}
}
rescaleStickyNodes(stickyNodeList);
}
}
/**
* Returns the custom created Action zoomAction.
*
* @return Action-object
*/
public Action getZoomAction() {
return zoomAction;
}
/**
* Pans to the given bounds without creating a historyaction to undo the action.
*
* @param bounds new bounds of the camera
*/
public void gotoBoundsWithoutHistory(PBounds bounds) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("gotoBoundsWithoutHistory(PBounds: " + bounds, new CurrentStackTrace()); // NOI18N
}
}
try {
try {
handleLayer.removeAllChildren();
} catch (final Exception e) {
LOG.warn("error during removeAllCHildren", e); // NOI18N
}
if (bounds.getWidth() < 0) {
bounds.setSize(bounds.getWidth() * (-1), bounds.getHeight());
}
if (bounds.getHeight() < 0) {
bounds.setSize(bounds.getWidth(), bounds.getHeight() * (-1));
}
if (bounds instanceof PBoundsWithCleverToString) {
final PBoundsWithCleverToString boundWCTS = (PBoundsWithCleverToString)bounds;
if (!boundWCTS.getCrsCode().equals(mappingModel.getSrs().getCode())) {
try {
final Rectangle2D pos = new Rectangle2D.Double();
XBoundingBox bbox = boundWCTS.getWorldCoordinates();
final CrsTransformer trans = new CrsTransformer(mappingModel.getSrs().getCode());
bbox = trans.transformBoundingBox(bbox);
bounds = bbox.getPBounds(getWtst());
} catch (final Exception e) {
LOG.error("Cannot transform the bounding box from " + boundWCTS.getCrsCode() + " to "
+ mappingModel.getSrs().getCode());
}
}
}
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("before animateView"); // NOI18N
}
}
getCamera().animateViewToCenterBounds((bounds), true, animationDuration);
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("after animateView"); // NOI18N
}
}
queryServicesWithoutHistory();
showHandles(true);
} catch (NullPointerException npe) {
LOG.warn("NPE in gotoBoundsWithoutHistory(" + bounds + ")", npe); // NOI18N
}
}
/**
* Checks out the y-camerascales for negative value and fixes it by negating both x- and y-scales.
*/
private void checkAndFixErroneousTransformation() {
if (getCamera().getViewTransform().getScaleY() < 0) {
final double y = getCamera().getViewTransform().getScaleY();
final double x = getCamera().getViewTransform().getScaleX();
LOG.warn("Erroneous ViewTransform: getViewTransform (scaleY=" + y + " scaleX=" + x + "). Try to fix it."); // NOI18N
getCamera().getViewTransformReference()
.setToScale(getCamera().getViewTransform().getScaleX() * (-1), y * (-1));
}
}
/**
* Re-adds the default layers in a given order.
*/
private void adjustLayers() {
int counter = 0;
getCamera().addLayer(counter++, mapServicelayer);
for (int i = 0; i < featureServiceLayer.getChildrenCount(); ++i) {
getCamera().addLayer(counter++, (PLayer)featureServiceLayer.getChild(i));
}
getCamera().addLayer(counter++, featureLayer);
getCamera().addLayer(counter++, tmpFeatureLayer);
getCamera().addLayer(counter++, rubberBandLayer);
getCamera().addLayer(counter++, dragPerformanceImproverLayer);
}
/**
* Assigns the listeners to the according interactionmodes.
*/
public void initInputListener() {
inputEventListener.put(MOTION, new SimpleMoveListener(this));
inputEventListener.put(PERPENDICULAR_INTERSECTION, new PerpendicularIntersectionListener(this));
inputEventListener.put(ZOOM, new RubberBandZoomListener());
inputEventListener.put(PAN, new PanAndMousewheelZoomListener());
inputEventListener.put(SELECT, new SelectionListener());
inputEventListener.put(GEO_REF, RasterGeoReferencingInputListener.getInstance());
inputEventListener.put(FEATURE_INFO, new GetFeatureInfoClickDetectionListener());
inputEventListener.put(FEATURE_INFO_MULTI_GEOM, new GetFeatureInfoMultiGeomListener());
inputEventListener.put(CREATE_SEARCH_POLYGON, new MetaSearchCreateSearchGeometryListener(this));
inputEventListener.put(CREATE_SIMPLE_GEOMETRY, new CreateSimpleGeometryListener(this));
inputEventListener.put(MOVE_POLYGON, new FeatureMoveListener(this));
inputEventListener.put(NEW_POLYGON, new CreateNewGeometryListener(this));
inputEventListener.put(RAISE_POLYGON, new RaisePolygonListener(this));
inputEventListener.put(REMOVE_POLYGON, new DeleteFeatureListener(this));
inputEventListener.put(ATTACH_POLYGON_TO_ALPHADATA, new AttachFeatureListener());
inputEventListener.put(JOIN_POLYGONS, new JoinPolygonsListener());
inputEventListener.put(SPLIT_POLYGON, new SplitPolygonListener(this));
inputEventListener.put(LINEAR_REFERENCING, new CreateLinearReferencedMarksListener(this));
inputEventListener.put(MEASUREMENT, new MeasurementListener(this));
// inputEventListener.put(PRINTING_AREA_SELECTION, new PrintingFrameListener(this));
inputEventListener.put(PRINTING_AREA_SELECTION, new PrintingTemplatePreviewListener(this));
inputEventListener.put(CUSTOM_FEATUREINFO, new CustomFeatureInfoListener());
inputEventListener.put(OVERVIEW, new OverviewModeListener());
}
/**
* Assigns a custom interactionmode with an own PBasicInputEventHandler.
*
* @param key interactionmode as String
* @param listener new PBasicInputEventHandler
*/
public void addCustomInputListener(final String key, final PBasicInputEventHandler listener) {
inputEventListener.put(key, listener);
}
/**
* Assigns the cursors to the according interactionmodes.
*/
public void initCursors() {
putCursor(SELECT, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(PERPENDICULAR_INTERSECTION, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(ZOOM, new Cursor(Cursor.CROSSHAIR_CURSOR));
putCursor(PAN, new Cursor(Cursor.HAND_CURSOR));
putCursor(GEO_REF, new Cursor(Cursor.CROSSHAIR_CURSOR));
putCursor(FEATURE_INFO, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(FEATURE_INFO_MULTI_GEOM, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(CREATE_SEARCH_POLYGON, new Cursor(Cursor.CROSSHAIR_CURSOR));
putCursor(MOVE_POLYGON, new Cursor(Cursor.HAND_CURSOR));
putCursor(ROTATE_POLYGON, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(NEW_POLYGON, new Cursor(Cursor.CROSSHAIR_CURSOR));
putCursor(RAISE_POLYGON, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(REMOVE_POLYGON, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(ATTACH_POLYGON_TO_ALPHADATA, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(JOIN_POLYGONS, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(SPLIT_POLYGON, new Cursor(Cursor.CROSSHAIR_CURSOR));
putCursor(MEASUREMENT, new Cursor(Cursor.CROSSHAIR_CURSOR));
putCursor(LINEAR_REFERENCING, new Cursor(Cursor.DEFAULT_CURSOR));
putCursor(CREATE_SIMPLE_GEOMETRY, new Cursor(Cursor.CROSSHAIR_CURSOR));
putCursor(MOVE_HANDLE, new Cursor(Cursor.CROSSHAIR_CURSOR));
putCursor(REMOVE_HANDLE, new Cursor(Cursor.CROSSHAIR_CURSOR));
putCursor(ADD_HANDLE, new Cursor(Cursor.CROSSHAIR_CURSOR));
}
/**
* Shows the printingsetting-dialog that resets the interactionmode after printing.
*/
public void showPrintingSettingsDialog() {
showPrintingSettingsDialog(false);
}
/**
* Shows the printingsetting-dialog that resets the interactionmode after printing.
*
* @param chooseFile DOCUMENT ME!
*/
public void showPrintingSettingsDialog(final boolean chooseFile) {
printingSettingsDialog = printingSettingsDialog.cloneWithNewParent(true, this);
printingSettingsDialog.setChooseFileName(chooseFile);
StaticSwingTools.showDialog(printingSettingsDialog);
}
/**
* Shows the printing-dialog that resets the interactionmode after printing.
*/
public void showPrintingDialog() {
setPointerAnnotationVisibility(false);
printingDialog = printingDialog.cloneWithNewParent(true, this);
try {
printingDialog.startLoading();
StaticSwingTools.showDialog(printingDialog);
} catch (final Exception e) {
LOG.error("Fehler beim Anzeigen des Printing Dialogs", e); // NOI18N
}
}
/**
* DOCUMENT ME!
*/
public void printingAction() {
showPrintingSettingsDialog();
}
/**
* backward compatibility function.
*
* @param ignoredHandlerString DOCUMENT ME!
*
* @deprecated DOCUMENT ME!
*/
public void showPrintingSettingsDialog(final String ignoredHandlerString) {
showPrintingSettingsDialog();
}
/**
* Getter for property interactionMode.
*
* @return Value of property interactionMode.
*/
public String getInteractionMode() {
return this.interactionMode;
}
/**
* Changes the interactionmode.
*
* @param interactionMode new interactionmode as String
*/
public void setInteractionMode(final String interactionMode) {
try {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("setInteractionMode(" + interactionMode + ")\nAlter InteractionMode:"
+ this.interactionMode + "",
new Exception()); // NOI18N
}
}
try {
handleLayer.removeAllChildren();
} catch (final Exception e) {
LOG.warn("Fehler bei removeAllCHildren", e); // NOI18N
}
setPointerAnnotationVisibility(false);
if (this.interactionMode != null) {
if (interactionMode.equals(FEATURE_INFO)) {
((GetFeatureInfoClickDetectionListener)this.getInputListener(interactionMode)).getPInfo()
.setVisible(true);
} else {
((GetFeatureInfoClickDetectionListener)this.getInputListener(FEATURE_INFO)).getPInfo()
.setVisible(false);
}
if (isReadOnly()) {
((DefaultFeatureCollection)(getFeatureCollection())).removeFeaturesByInstance(PureNewFeature.class);
}
final PInputEventListener pivl = this.getInputListener(this.interactionMode);
if (pivl != null) {
removeInputEventListener(pivl);
} else {
LOG.warn("this.getInputListener(this.interactionMode)==null"); // NOI18N
}
if (interactionMode.equals(NEW_POLYGON) || interactionMode.equals(CREATE_SEARCH_POLYGON)) { // ||interactionMode==SELECT) {
featureCollection.unselectAll();
}
if ((interactionMode.equals(SELECT) || interactionMode.equals(LINEAR_REFERENCING)
|| interactionMode.equals(SPLIT_POLYGON) || interactionMode.equals(MOVE_POLYGON)
|| interactionMode.equals(PRINTING_AREA_SELECTION))
&& (this.readOnly == false)) {
featureSelectionChanged(null);
}
if (interactionMode.equals(JOIN_POLYGONS)) {
try {
handleLayer.removeAllChildren();
} catch (final Exception e) {
LOG.warn("Fehler bei removeAllCHildren", e); // NOI18N
}
}
}
final PropertyChangeEvent interactionModeChangedEvent = new PropertyChangeEvent(
this,
PROPERTY_MAP_INTERACTION_MODE,
this.interactionMode,
interactionMode);
this.interactionMode = interactionMode;
final PInputEventListener pivl = getInputListener(interactionMode);
if (pivl != null) {
addInputEventListener(pivl);
propertyChangeSupport.firePropertyChange(interactionModeChangedEvent);
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.MAPPING_MODE, interactionMode));
} else {
LOG.warn("this.getInputListener(this.interactionMode)==null bei interactionMode=" + interactionMode); // NOI18N
}
} catch (final Exception e) {
LOG.error("Fehler beim Ändern des InteractionModes", e); // NOI18N
}
}
/**
* DOCUMENT ME!
*
* @param evt DOCUMENT ME!
*/
@Deprecated
public void formComponentResized(final ComponentEvent evt) {
this.componentResizedDelayed();
}
/**
* Resizes the map and does not reload all services.
*
* @see #componentResizedDelayed()
*/
public void componentResizedIntermediate() {
if (!this.isLocked()) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("componentResizedIntermediate " + MappingComponent.this.getSize()); // NOI18N
}
}
if ((MappingComponent.this.getSize().height >= 0) && (MappingComponent.this.getSize().width >= 0)) {
if (mappingModel != null) {
// rescale map
if (historyModel.getCurrentElement() != null) {
PBounds bounds = (PBounds)historyModel.getCurrentElement();
if (bounds == null) {
bounds = initialBoundingBox.getPBounds(wtst);
}
if (bounds.getWidth() < 0) {
bounds.setSize(bounds.getWidth() * (-1), bounds.getHeight());
}
if (bounds.getHeight() < 0) {
bounds.setSize(bounds.getWidth(), bounds.getHeight() * (-1));
}
getCamera().animateViewToCenterBounds(bounds, true, animationDuration);
}
}
}
// move internal widgets
for (final String internalWidget : this.internalWidgets.keySet()) {
if (this.getInternalWidget(internalWidget).isVisible()) {
showInternalWidget(internalWidget, true, 0);
}
}
}
}
/**
* Resizes the map and reloads all services.
*
* @see #componentResizedIntermediate()
*/
public void componentResizedDelayed() {
if (!this.isLocked()) {
try {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("componentResizedDelayed " + MappingComponent.this.getSize()); // NOI18N
}
}
if ((MappingComponent.this.getSize().height >= 0) && (MappingComponent.this.getSize().width >= 0)) {
if (mappingModel != null) {
final PBounds bounds = (PBounds)historyModel.getCurrentElement();
if (bounds != null) {
gotoBoundsWithoutHistory(bounds);
} else {
gotoBoundsWithoutHistory(getInitialBoundingBox().getPBounds(wtst));
}
// move internal widgets
for (final String internalWidget : this.internalWidgets.keySet()) {
if (this.getInternalWidget(internalWidget).isVisible()) {
showInternalWidget(internalWidget, true, 0);
}
}
}
}
} catch (final Exception t) {
LOG.error("Fehler in formComponentResized()", t); // NOI18N
}
}
}
/**
* syncSelectedObjectPresenter(int i).
*
* @param i DOCUMENT ME!
*/
public void syncSelectedObjectPresenter(final int i) {
selectedObjectPresenter.setVisible(true);
if (featureCollection.getSelectedFeatures().size() > 0) {
if (featureCollection.getSelectedFeatures().size() == 1) {
final PFeature selectedFeature = (PFeature)pFeatureHM.get(
featureCollection.getSelectedFeatures().toArray()[0]);
if (selectedFeature != null) {
selectedObjectPresenter.getCamera()
.animateViewToCenterBounds(selectedFeature.getBounds(), true, getAnimationDuration() * 2);
}
} else {
// todo
}
} else {
LOG.warn("in syncSelectedObjectPresenter(" + i + "): selectedFeature==null"); // NOI18N
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public BoundingBox getInitialBoundingBox() {
if (initialBoundingBox == null) {
return mappingModel.getInitialBoundingBox();
} else {
return initialBoundingBox;
}
}
/**
* Returns the current featureCollection.
*
* @return DOCUMENT ME!
*/
public FeatureCollection getFeatureCollection() {
return featureCollection;
}
/**
* Replaces the old featureCollection with a new one.
*
* @param featureCollection the new featureCollection
*/
public void setFeatureCollection(final FeatureCollection featureCollection) {
this.featureCollection = featureCollection;
featureCollection.addFeatureCollectionListener(this);
}
/**
* DOCUMENT ME!
*
* @param visibility DOCUMENT ME!
*/
public void setFeatureCollectionVisibility(final boolean visibility) {
featureLayer.setVisible(visibility);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isFeatureCollectionVisible() {
return featureLayer.getVisible();
}
/**
* Adds a new mapservice at a specific place of the layercontrols.
*
* @param mapService the new mapservice
* @param position the index where to position the mapservice
*/
public void addMapService(final MapService mapService, final int position) {
try {
PNode p = new PNode();
if (mapService instanceof RasterMapService) {
LOG.info("adding RasterMapService '" + mapService + "' " + mapService.getClass().getSimpleName()
+ ")"); // NOI18N
if (mapService.getPNode() instanceof XPImage) {
p = (XPImage)mapService.getPNode();
} else {
p = new XPImage();
mapService.setPNode(p);
}
mapService.addRetrievalListener(new MappingComponentRasterServiceListener(
position,
p,
(ServiceLayer)mapService));
} else if (mapService instanceof ModeLayer) {
// skip
return;
// a addMapService is called via a fireLAyerAdded when a Mode is selected
} else {
LOG.info("adding FeatureMapService '" + mapService + "' (" + mapService.getClass().getSimpleName()
+ ")"); // NOI18N
p = new PLayer();
mapService.setPNode(p);
if (DocumentFeatureService.class.isAssignableFrom(mapService.getClass())) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("FeatureMapService(" + mapService
+ "): isDocumentFeatureService, checking document size"); // NOI18N
}
}
final DocumentFeatureService documentFeatureService = (DocumentFeatureService)mapService;
if (documentFeatureService.getDocumentSize() > this.criticalDocumentSize) {
LOG.warn("FeatureMapService(" + mapService + "): DocumentFeatureService '"
+ documentFeatureService.getName() + "' size of "
+ (documentFeatureService.getDocumentSize() / 1000000)
+ "MB exceeds critical document size (" + (this.criticalDocumentSize / 1000000)
+ "MB)"); // NOI18N
if (this.documentProgressListener == null) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("FeatureMapService(" + mapService
+ "): lazy instantiation of documentProgressListener"); // NOI18N
}
}
this.documentProgressListener = new DocumentProgressListener();
}
if (this.documentProgressListener.getRequestId() != -1) {
LOG.error("FeatureMapService(" + mapService
+ "): The documentProgressListener is already in use by request '"
+ this.documentProgressListener.getRequestId()
+ ", document progress cannot be tracked"); // NOI18N
} else {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("FeatureMapService(" + mapService
+ "): adding documentProgressListener"); // NOI18N
}
}
documentFeatureService.addRetrievalListener(this.documentProgressListener);
}
}
}
if (JDBCFeatureService.class.isAssignableFrom(mapService.getClass())) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("FeatureMapService(" + mapService
+ "): isDocumentFeatureService, checking document size"); // NOI18N
}
}
final JDBCFeatureService documentFeatureService = (JDBCFeatureService)mapService;
if (this.documentProgressListener == null) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("FeatureMapService(" + mapService
+ "): lazy instantiation of documentProgressListener"); // NOI18N
}
}
this.documentProgressListener = new DocumentProgressListener();
}
if (this.documentProgressListener.getRequestId() != -1) {
LOG.error("FeatureMapService(" + mapService
+ "): The documentProgressListener is already in use by request '"
+ this.documentProgressListener.getRequestId()
+ ", document progress cannot be tracked"); // NOI18N
} else {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("FeatureMapService(" + mapService
+ "): adding documentProgressListener"); // NOI18N
}
}
documentFeatureService.addRetrievalListener(this.documentProgressListener);
}
}
mapService.addRetrievalListener(new MappingComponentFeatureServiceListener(
(ServiceLayer)mapService,
(PLayer)mapService.getPNode()));
}
p.setTransparency(mapService.getTranslucency());
p.setVisible(mapService.isVisible());
mapServicelayer.addChild(p);
} catch (final Exception e) {
LOG.error("addMapService(" + mapService + "): Fehler beim hinzufuegen eines Layers: " + e.getMessage(), e); // NOI18N
}
}
/**
* DOCUMENT ME!
*
* @param mm DOCUMENT ME!
*/
public void preparationSetMappingModel(final MappingModel mm) {
mappingModel = mm;
}
/**
* Sets a new mappingmodel in this MappingComponent.
*
* @param mm the new mappingmodel
*/
public void setMappingModel(final MappingModel mm) {
LOG.info("setMappingModel"); // NOI18N
// FIXME: why is the default uncaught exception handler set in such a random place?
if (Thread.getDefaultUncaughtExceptionHandler() == null) {
LOG.info("setDefaultUncaughtExceptionHandler"); // NOI18N
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread t, final Throwable e) {
LOG.error("Error", e);
}
});
}
mappingModel = mm;
// currentBoundingBox = mm.getInitialBoundingBox();
final Runnable r = new Thread("MappingComponent setMappingModel()") {
@Override
public void run() {
mappingModel.addMappingModelListener(MappingComponent.this);
final TreeMap rs = mappingModel.getRasterServices();
// Rückwärts wegen der Reihenfolge der Layer im Layer Widget
final Iterator it = rs.keySet().iterator();
while (it.hasNext()) {
final Object key = it.next();
final int rsi = (Integer)key;
final Object o = rs.get(key);
if (o instanceof MapService) {
addMapService(((MapService)o), rsi);
}
}
adjustLayers();
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("Set Mapping Modell done"); // NOI18N
}
}
}
};
CismetThreadPool.execute(new Thread(r, "MappingComponent adjustLayers()"));
}
/**
* Returns the current mappingmodel.
*
* @return current mappingmodel
*/
public MappingModel getMappingModel() {
return mappingModel;
}
/**
* Animates a component to a given x/y-coordinate in a given time.
*
* @param c the component to animate
* @param toX final x-position
* @param toY final y-position
* @param animationDuration duration of the animation
* @param hideAfterAnimation should the component be hidden after animation?
*/
private void animateComponent(final JComponent c,
final int toX,
final int toY,
final int animationDuration,
final boolean hideAfterAnimation) {
if (animationDuration > 0) {
final int x = (int)c.getBounds().getX() - toX;
final int y = (int)c.getBounds().getY() - toY;
int sx;
int sy;
if (x > 0) {
sx = -1;
} else {
sx = 1;
}
if (y > 0) {
sy = -1;
} else {
sy = 1;
}
int big;
if (Math.abs(x) > Math.abs(y)) {
big = Math.abs(x);
} else {
big = Math.abs(y);
}
final int sleepy;
if ((animationDuration / big) < 1) {
sleepy = 1;
} else {
sleepy = animationDuration / big;
}
final int directionY = sy;
final int directionX = sx;
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("animateComponent: directionX=" + directionX + ", directionY=" + directionY
+ ", currentX=" + c.getBounds().getX() + ", currentY=" + c.getBounds().getY() + ", toX="
+ toX + ", toY=" + toY); // NOI18N
}
}
final Thread timer = new Thread("MappingComponent timer") {
@Override
public void run() {
while (!isInterrupted()) {
try {
sleep(sleepy);
} catch (final Exception iex) {
}
EventQueue.invokeLater(new Thread("MappingComponent updateBounds") {
@Override
public void run() {
int currentY = (int)c.getBounds().getY();
int currentX = (int)c.getBounds().getX();
if (currentY != toY) {
currentY = currentY + directionY;
}
if (currentX != toX) {
currentX = currentX + directionX;
}
c.setBounds(currentX, currentY, c.getWidth(), c.getHeight());
}
});
if ((c.getBounds().getY() == toY) && (c.getBounds().getX() == toX)) {
if (hideAfterAnimation) {
EventQueue.invokeLater(new Thread("MappingComponent hide") {
@Override
public void run() {
c.setVisible(false);
c.hide();
}
});
}
break;
}
}
}
};
timer.setPriority(Thread.NORM_PRIORITY);
timer.start();
} else {
c.setBounds(toX, toY, c.getWidth(), c.getHeight());
if (hideAfterAnimation) {
c.setVisible(false);
}
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @deprecated DOCUMENT ME!
*/
@Deprecated
public NewSimpleInternalLayerWidget getInternalLayerWidget() {
return (NewSimpleInternalLayerWidget)this.getInternalWidget(LAYERWIDGET);
}
/**
* Adds a new internal widget to the map.<br/>
* If a {@code widget} with the same {@code name} already exisits, the old widget will be removed and the new widget
* will be added. If a widget with a different name already exisit at the same {@code position} the new widget will
* not be added and the operation returns {@code false}.
*
* @param name unique name of the widget
* @param position position of the widget
* @param widget the widget
*
* @return {@code true} if the widget could be added, {@code false} otherwise
*
* @see #POSITION_NORTHEAST
* @see #POSITION_NORTHWEST
* @see #POSITION_SOUTHEAST
* @see #POSITION_SOUTHWEST
*/
public boolean addInternalWidget(final String name, final int position, final JInternalFrame widget) {
if (LOG.isDebugEnabled()) {
LOG.debug("adding internal widget '" + name + "' to position '" + position + "'"); // NOI18N
}
if (this.internalWidgets.containsKey(name)) {
LOG.warn("widget '" + name + "' already added, removing old widget"); // NOI18N
this.remove(this.getInternalWidget(name));
} else if (this.internalWidgetPositions.containsValue(position)) {
LOG.warn("widget position '" + position + "' already taken"); // NOI18N
return false;
}
this.internalWidgets.put(name, widget);
this.internalWidgetPositions.put(name, position);
widget.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE); // NOI18N
this.add(widget);
widget.pack();
return true;
}
/**
* Removes an existing internal widget from the map.
*
* <p><b>Note:</b> the internalFrame will be disposed and then removed from the mappingComponent. This has to be
* done because of a Java Bug, as otherwise a memory leak will be created. See
* https://bugs.openjdk.java.net/browse/JDK-8041452 for a similar problem.</p>
*
* @param name name of the widget to be removed
*
* @return {@code true} id the widget was found and removed, {@code false} otherwise
*/
public boolean removeInternalWidget(final String name) {
if (LOG.isDebugEnabled()) {
LOG.debug("removing internal widget '" + name + "'"); // NOI18N
}
if (!this.internalWidgets.containsKey(name)) {
LOG.warn("widget '" + name + "' not found"); // NOI18N
return false;
}
this.getInternalWidget(name).dispose();
this.remove(this.getInternalWidget(name));
this.internalWidgets.remove(name);
this.internalWidgetPositions.remove(name);
return true;
}
/**
* Shows an InternalWidget by sliding it into the mappingcomponent.
*
* @param name name of the internl component to show
* @param visible should the widget be visible after the animation?
* @param animationDuration duration of the animation
*
* @return {@code true} if the operation was successful, {@code false} otherwise
*/
public boolean showInternalWidget(final String name, final boolean visible, final int animationDuration) {
final JInternalFrame internalWidget = this.getInternalWidget(name);
if (internalWidget == null) {
return false;
}
final int positionX;
final int positionY;
final int widgetPosition = this.getInternalWidgetPosition(name);
final boolean isHigher = (getHeight() < (internalWidget.getHeight() + 2)) && (getHeight() > 0);
final boolean isWider = (getWidth() < (internalWidget.getWidth() + 2)) && (getWidth() > 0);
switch (widgetPosition) {
case POSITION_NORTHWEST: {
positionX = 1;
positionY = 1;
break;
}
case POSITION_SOUTHWEST: {
positionX = 1;
positionY = isHigher ? 1 : (getHeight() - internalWidget.getHeight() - 1);
break;
}
case POSITION_NORTHEAST: {
positionX = isWider ? 1 : (getWidth() - internalWidget.getWidth() - 1);
positionY = 1;
break;
}
case POSITION_SOUTHEAST: {
positionX = isWider ? 1 : (getWidth() - internalWidget.getWidth() - 1);
positionY = isHigher ? 1 : (getHeight() - internalWidget.getHeight() - 1);
break;
}
default: {
LOG.warn("unkown widget position?!"); // NOI18N
return false;
}
}
if (visible) {
final int toY;
if ((widgetPosition == POSITION_NORTHWEST) || (widgetPosition == POSITION_NORTHEAST)) {
if (isHigher) {
toY = getHeight() - 1;
} else {
toY = positionY - internalWidget.getHeight() - 1;
}
} else if (isHigher) {
toY = getHeight() + 1;
} else {
toY = positionY + internalWidget.getHeight() + 1;
}
internalWidget.setBounds(
positionX,
toY,
isWider ? (getWidth() - 2) : internalWidget.getWidth(),
isHigher ? (getHeight() - 2) : internalWidget.getHeight());
internalWidget.setVisible(true);
internalWidget.show();
animateComponent(internalWidget, positionX, positionY, animationDuration, false);
} else {
internalWidget.setBounds(positionX, positionY, internalWidget.getWidth(), internalWidget.getHeight());
int toY = positionY + internalWidget.getHeight() + 1;
if ((widgetPosition == POSITION_NORTHWEST) || (widgetPosition == POSITION_NORTHEAST)) {
toY = positionY - internalWidget.getHeight() - 1;
}
animateComponent(internalWidget, positionX, toY, animationDuration, true);
}
return true;
}
/**
* DOCUMENT ME!
*
* @param visible DOCUMENT ME!
* @param animationDuration DOCUMENT ME!
*/
@Deprecated
public void showInternalLayerWidget(final boolean visible, final int animationDuration) {
this.showInternalWidget(LAYERWIDGET, visible, animationDuration);
}
/**
* Returns a boolean, if the InternalLayerWidget is visible.
*
* @return true, if visible, else false
*/
@Deprecated
public boolean isInternalLayerWidgetVisible() {
return this.getInternalLayerWidget().isVisible();
}
/**
* Returns a boolean, if the InternalWidget is visible.
*
* @param name name of the widget
*
* @return true, if visible, else false
*/
public boolean isInternalWidgetVisible(final String name) {
final JInternalFrame widget = this.getInternalWidget(name);
if (widget != null) {
return widget.isVisible();
}
return false;
}
/**
* Moves the camera to the initial bounding box (e.g. if the home-button is pressed).
*/
public void gotoInitialBoundingBox() {
final double x1;
final double y1;
final double x2;
final double y2;
final double w;
final double h;
x1 = getWtst().getScreenX(mappingModel.getInitialBoundingBox().getX1());
y1 = getWtst().getScreenY(mappingModel.getInitialBoundingBox().getY1());
x2 = getWtst().getScreenX(mappingModel.getInitialBoundingBox().getX2());
y2 = getWtst().getScreenY(mappingModel.getInitialBoundingBox().getY2());
final Rectangle2D home = new Rectangle2D.Double();
home.setRect(x1, y2, x2 - x1, y1 - y2);
getCamera().animateViewToCenterBounds(home, true, animationDuration);
if (getCamera().getViewTransform().getScaleY() < 0) {
LOG.fatal("gotoInitialBoundingBox: Problem :-( mit getViewTransform"); // NOI18N
}
setNewViewBounds(home);
queryServices();
}
/**
* Refreshs all registered services.
*/
public void queryServices() {
if (newViewBounds != null) {
addToHistory(new PBoundsWithCleverToString(
new PBounds(newViewBounds),
wtst,
mappingModel.getSrs().getCode()));
queryServicesWithoutHistory();
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("queryServices()"); // NOI18N
}
}
rescaleStickyNodes();
}
}
/**
* Forces all services to refresh themselves.
*/
public void refresh() {
forceQueryServicesWithoutHistory();
}
/**
* Forces all services to refresh themselves.
*/
private void forceQueryServicesWithoutHistory() {
queryServicesWithoutHistory(true);
}
/**
* Refreshs all services, but not forced.
*/
private void queryServicesWithoutHistory() {
queryServicesWithoutHistory(false);
}
/**
* Waits until all animations are done, then iterates through all registered services and calls handleMapService()
* for each.
*
* @param forced forces the refresh
*/
private void queryServicesWithoutHistory(final boolean forced) {
if (forced && mainMappingComponent) {
CismapBroker.getInstance().fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_RESET, this));
}
if (!locked) {
final Runnable r = new Thread("MappingComponent queryServicesWithoutHistory()") {
@Override
public void run() {
while (getAnimating()) {
try {
Thread.currentThread().sleep(50);
} catch (final Exception doNothing) {
}
}
CismapBroker.getInstance().fireMapBoundsChanged();
if (MappingComponent.this.isBackgroundEnabled()) {
final TreeMap rs = mappingModel.getRasterServices();
final TreeMap fs = mappingModel.getFeatureServices();
for (final Iterator it = rs.keySet().iterator(); it.hasNext();) {
final Object key = it.next();
final int rsi = ((Integer)key).intValue();
final Object o = rs.get(key);
if (o instanceof MapService) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("queryServicesWithoutHistory (RasterServices): " + o); // NOI18N
}
}
handleMapService(rsi, (MapService)o, forced);
} else {
LOG.warn("service is not of type MapService:" + o); // NOI18N
}
}
for (final Iterator it = fs.keySet().iterator(); it.hasNext();) {
final Object key = it.next();
final int fsi = ((Integer)key).intValue();
final Object o = fs.get(key);
if (o instanceof MapService) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("queryServicesWithoutHistory (FeatureServices): " + o); // NOI18N
}
}
handleMapService(fsi, (MapService)o, forced);
} else {
LOG.warn("service is not of type MapService:" + o); // NOI18N
}
}
}
}
};
CismetThreadPool.execute(new Thread(r, "MappingComponent queryServicesWithoutHistory()"));
}
}
/**
* queryServicesIndependentFromMap.
*
* @param width DOCUMENT ME!
* @param height DOCUMENT ME!
* @param bb DOCUMENT ME!
* @param rl DOCUMENT ME!
*/
public void queryServicesIndependentFromMap(final int width,
final int height,
final BoundingBox bb,
final RetrievalListener rl) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("queryServicesIndependentFromMap (" + width + "x" + height + ")"); // NOI18N
}
}
final Runnable t = new Thread("Mappingcompoenent queryServicesIndependentFromMap()") {
@Override
public void run() {
while (getAnimating()) {
try {
Thread.currentThread().sleep(50);
} catch (final Exception doNothing) {
}
}
if (MappingComponent.this.isBackgroundEnabled()) {
final TreeMap rs = mappingModel.getRasterServices();
final TreeMap fs = mappingModel.getFeatureServices();
for (final Iterator it = rs.keySet().iterator(); it.hasNext();) {
final Object key = it.next();
final int rsi = ((Integer)key).intValue();
final Object o = rs.get(key);
if ((o instanceof AbstractRetrievalService) && (o instanceof ServiceLayer)
&& ((ServiceLayer)o).isEnabled()
&& (o instanceof RetrievalServiceLayer)
&& ((RetrievalServiceLayer)o).getPNode().getVisible()) {
try {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("queryServicesIndependentFromMap: cloning '"
+ o.getClass().getSimpleName() + "': '" + o + "'"); // NOI18N
}
}
AbstractRetrievalService r;
if (o instanceof WebFeatureService) {
final WebFeatureService wfsClone = (WebFeatureService)((WebFeatureService)o)
.clone();
wfsClone.removeAllListeners();
r = wfsClone;
} else {
r = ((AbstractRetrievalService)o).cloneWithoutRetrievalListeners();
}
r.addRetrievalListener(rl);
((ServiceLayer)r).setLayerPosition(rsi);
handleMapService(rsi, (MapService)r, width, height, bb, true);
} catch (final Exception t) {
LOG.error("could not clone service '" + o + "' for printing: " + t.getMessage(), t); // NOI18N
}
} else {
LOG.warn("ignoring service '" + o + "' for printing"); // NOI18N
}
}
for (final Iterator it = fs.keySet().iterator(); it.hasNext();) {
final Object key = it.next();
final int fsi = ((Integer)key).intValue();
final Object o = fs.get(key);
if (o instanceof AbstractRetrievalService) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("queryServicesIndependentFromMap: cloning '"
+ o.getClass().getSimpleName() + "': '" + o + "'"); // NOI18N
}
}
AbstractRetrievalService r;
if (o instanceof WebFeatureService) {
final WebFeatureService wfsClone = (WebFeatureService)((WebFeatureService)o)
.clone();
wfsClone.removeAllListeners();
r = (AbstractRetrievalService)o;
} else {
r = ((AbstractRetrievalService)o).cloneWithoutRetrievalListeners();
}
r.addRetrievalListener(rl);
((ServiceLayer)r).setLayerPosition(fsi);
handleMapService(fsi, (MapService)r, 0, 0, bb, true);
}
}
}
}
};
CismetThreadPool.execute(t);
}
/**
* former synchronized method.
*
* @param position DOCUMENT ME!
* @param service rs
* @param forced DOCUMENT ME!
*/
public void handleMapService(final int position, final MapService service, final boolean forced) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("in handleRasterService: " + service + "("
+ Integer.toHexString(System.identityHashCode(service)) + ")(" + service.hashCode() + ")"); // NOI18N
}
}
final PBounds bounds = getCamera().getViewBounds();
final BoundingBox bb = new BoundingBox();
final double x1 = getWtst().getWorldX(bounds.getMinX());
final double y1 = getWtst().getWorldY(bounds.getMaxY());
final double x2 = getWtst().getWorldX(bounds.getMaxX());
final double y2 = getWtst().getWorldY(bounds.getMinY());
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("Bounds=" + bounds); // NOI18N
}
}
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("handleRasterService BoundingBox(" + x1 + " " + y1 + "," + x2 + " " + y2 + ")"); // NOI18N
}
}
if (((ServiceLayer)service).getName().startsWith("prefetching")) { // NOI18N
bb.setX1(x1 - (x2 - x1));
bb.setY1(y1 - (y2 - y1));
bb.setX2(x2 + (x2 - x1));
bb.setY2(y2 + (y2 - y1));
} else {
bb.setX1(x1);
bb.setY1(y1);
bb.setX2(x2);
bb.setY2(y2);
}
if ((getWidth() > 0) && (getHeight() > 0)) {
// if width or height are negative or zero, a wms request makes no sense
handleMapService(position, service, getWidth(), getHeight(), bb, forced);
}
}
/**
* former synchronized method.
*
* @param position DOCUMENT ME!
* @param rs DOCUMENT ME!
* @param width DOCUMENT ME!
* @param height DOCUMENT ME!
* @param bb DOCUMENT ME!
* @param forced DOCUMENT ME!
*/
private void handleMapService(final int position,
final MapService rs,
final int width,
final int height,
final BoundingBox bb,
final boolean forced) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("handleMapService: " + rs); // NOI18N
}
}
rs.setSize(height, width);
if (((ServiceLayer)rs).isEnabled()) {
synchronized (serviceFuturesMap) {
final Future<?> sf = serviceFuturesMap.get(rs);
if ((sf == null) || sf.isDone()) {
final Runnable serviceCall = new Thread("handleMapService") {
@Override
public void run() {
try {
while (getAnimating()) {
try {
Thread.currentThread().sleep(50);
} catch (final Exception e) {
}
}
rs.setBoundingBox(bb);
if (rs instanceof FeatureAwareRasterService) {
((FeatureAwareRasterService)rs).setFeatureCollection(featureCollection);
}
rs.retrieve(forced);
} finally {
serviceFuturesMap.remove(rs);
}
}
};
synchronized (serviceFuturesMap) {
serviceFuturesMap.put(rs, CismetThreadPool.submit(serviceCall));
}
} else {
LOG.warn("The wms request of the service \"" + rs.toString()
+ "\" was ignored. This can lead to a wrong "
+ "service image in the map and should not happen. The ignored bbox was "
+ bb.toString());
}
}
} else {
rs.setBoundingBox(bb);
}
}
/**
* Creates a new WorldToScreenTransform for the current screensize (boundingbox) and returns it.
*
* @return new WorldToScreenTransform or null
*/
public WorldToScreenTransform getWtst() {
try {
if (wtst == null) {
final double y_real = mappingModel.getInitialBoundingBox().getY2()
- mappingModel.getInitialBoundingBox().getY1();
final double x_real = mappingModel.getInitialBoundingBox().getX2()
- mappingModel.getInitialBoundingBox().getX1();
double clip_height;
double clip_width;
double x_screen = getWidth();
double y_screen = getHeight();
if (x_screen == 0) {
x_screen = 100;
}
if (y_screen == 0) {
y_screen = 100;
}
if ((x_real / x_screen) >= (y_real / y_screen)) { // X ist Bestimmer d.h. x wird nicht verändert
clip_height = x_screen * y_real / x_real;
clip_width = x_screen;
clip_offset_y = 0; // (y_screen-clip_height)/2;
clip_offset_x = 0;
} else { // Y ist Bestimmer
clip_height = y_screen;
clip_width = y_screen * x_real / y_real;
clip_offset_y = 0;
clip_offset_x = 0; // (x_screen-clip_width)/2;
}
wtst = new WorldToScreenTransform(mappingModel.getInitialBoundingBox().getX1(),
mappingModel.getInitialBoundingBox().getY2());
}
return wtst;
} catch (final Exception t) {
LOG.error("Fehler in getWtst()", t); // NOI18N
return null;
}
}
/**
* Resets the current WorldToScreenTransformation.
*/
public void resetWtst() {
wtst = null;
}
/**
* Returns 0.
*
* @return DOCUMENT ME!
*/
public double getClip_offset_x() {
return 0; // clip_offset_x;
}
/**
* Assigns a new value to the x-clip-offset.
*
* @param clip_offset_x new clipoffset
*/
public void setClip_offset_x(final double clip_offset_x) {
this.clip_offset_x = clip_offset_x;
}
/**
* Returns 0.
*
* @return DOCUMENT ME!
*/
public double getClip_offset_y() {
return 0; // clip_offset_y;
}
/**
* Assigns a new value to the y-clip-offset.
*
* @param clip_offset_y new clipoffset
*/
public void setClip_offset_y(final double clip_offset_y) {
this.clip_offset_y = clip_offset_y;
}
/**
* Returns the rubberband-PLayer.
*
* @return DOCUMENT ME!
*/
public PLayer getRubberBandLayer() {
return rubberBandLayer;
}
/**
* Assigns a given PLayer to the variable rubberBandLayer.
*
* @param rubberBandLayer a PLayer
*/
public void setRubberBandLayer(final PLayer rubberBandLayer) {
this.rubberBandLayer = rubberBandLayer;
}
/**
* Sets new viewbounds.
*
* @param r2d Rectangle2D
*/
public void setNewViewBounds(final Rectangle2D r2d) {
newViewBounds = r2d;
}
/**
* DOCUMENT ME!
*
* @return the current view bounds
*/
public Rectangle2D getViewBounds() {
return newViewBounds;
}
/**
* Will be called if the selection of features changes. It selects the PFeatures connected to the selected features
* of the featurecollectionevent and moves them to the front. Also repaints handles at the end.
*
* @param fce featurecollectionevent with selected features
*/
@Override
public void featureSelectionChanged(final FeatureCollectionEvent fce) {
final Collection allChildren = featureLayer.getChildrenReference();
final ArrayList<PFeature> all = new ArrayList<PFeature>();
final SelectionListener sl = (SelectionListener)getInputEventListener().get(MappingComponent.SELECT);
boolean selectionChangedBySelectionListener = false;
if (sl != null) {
selectionChangedBySelectionListener = sl.isSelectionInProgress();
}
for (final Object o : allChildren) {
if (o instanceof PFeature) {
all.add((PFeature)o);
} else if (o instanceof PLayer) {
// Handling von Feature-Gruppen-Layer, welche als Kinder dem Feature Layer hinzugefügt wurden
all.addAll(((PLayer)o).getChildrenReference());
}
}
// final Collection<PFeature> all = featureLayer.getChildrenReference();
for (final PFeature f : all) {
f.setSelected(false);
if ((sl != null) && !selectionChangedBySelectionListener) {
sl.removeSelectedFeature(f);
}
}
Collection<Feature> c;
if (fce != null) {
c = fce.getFeatureCollection().getSelectedFeatures();
} else {
c = featureCollection.getSelectedFeatures();
}
////handle featuregroup select-delegation////
final Set<Feature> selectionResult = new HashSet<Feature>();
for (final Feature current : c) {
if (current instanceof FeatureGroup) {
selectionResult.addAll(FeatureGroups.expandToLeafs((FeatureGroup)current));
} else {
selectionResult.add(current);
}
}
c = selectionResult;
for (final Feature f : c) {
if (f != null) {
final PFeature feature = getPFeatureHM().get(f);
if (feature != null) {
if (feature.getParent() != null) {
feature.getParent().moveToFront();
}
feature.setSelected(true);
feature.moveToFront();
if ((sl != null) && !selectionChangedBySelectionListener) {
sl.addSelectedFeature(feature);
}
// Fuer den selectedObjectPresenter (Eigener PCanvas)
syncSelectedObjectPresenter(1000);
} else {
try {
handleLayer.removeAllChildren();
} catch (final Exception e) {
LOG.warn("Fehler bei removeAllCHildren", e); // NOI18N
}
}
}
}
showHandles(false);
}
/**
* Will be called if one or more features are changed somehow (handles moved/rotated). Calls reconsiderFeature() on
* each feature of the given featurecollectionevent. Repaints handles at the end.
*
* @param fce featurecollectionevent with changed features
*/
@Override
public void featuresChanged(final FeatureCollectionEvent fce) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("featuresChanged"); // NOI18N
}
}
final List<Feature> list = new ArrayList<Feature>();
list.addAll(fce.getEventFeatures());
for (final Feature elem : list) {
reconsiderFeature(elem);
}
showHandles(false);
}
/**
* Does a complete reconciliation of the PFeature assigned to a feature from the FeatureCollectionEvent. Calls
* following PFeature-methods: syncGeometry(), visualize(), resetInfoNodePosition() and refreshInfoNode()
*
* @param fce featurecollectionevent with features to reconsile
*/
@Override
public void featureReconsiderationRequested(final FeatureCollectionEvent fce) {
for (final Feature f : fce.getEventFeatures()) {
if (f != null) {
final PFeature node = pFeatureHM.get(f);
if (node != null) {
node.syncGeometry();
node.visualize();
node.refreshDesign(); // without this, sld styled points will not be shown properly
node.resetInfoNodePosition();
node.refreshInfoNode();
repaint();
}
}
}
}
/**
* Refresh the info nodes of all features.
*
* <p>The node names are possibly changed after adding or removing a feature. See <code>
* DefaultFeatureCollection.checkForAndCorrectDoubleNaming()</code></p>
*/
private void refreshAllInfoNodesRequested() {
EventQueue.invokeLater(new Thread("Refresh pfeature names") {
@Override
public void run() {
for (final PFeature f : new ArrayList<PFeature>(pFeatureHM.values())) {
if (f != null) {
f.refreshName();
}
}
repaint();
}
});
}
/**
* Method is deprecated and deactivated. Does nothing!!
*
* @param fce FeatureCollectionEvent with features to add
*/
@Override
@Deprecated
public void featuresAdded(final FeatureCollectionEvent fce) {
}
/**
* Method is deprecated and deactivated. Does nothing!!
*
* @deprecated DOCUMENT ME!
*/
@Override
@Deprecated
public void featureCollectionChanged() {
}
/**
* Clears the PFeatureHashmap and removes all PFeatures from the featurelayer. Does a
* checkFeatureSupportingRasterServiceAfterFeatureRemoval() on all features from the given FeatureCollectionEvent.
*
* @param fce FeatureCollectionEvent with features to check for a remaining supporting rasterservice
*/
@Override
public void allFeaturesRemoved(final FeatureCollectionEvent fce) {
for (final PFeature feature : pFeatureHM.values()) {
feature.cleanup();
}
stickyPNodes.clear();
pFeatureHM.clear();
featureLayer.removeAllChildren();
// Lösche alle Features in den Gruppen-Layer, aber füge den Gruppen-Layer wieder dem FeatureLayer hinzu
for (final PLayer layer : featureGrpLayerMap.values()) {
layer.removeAllChildren();
featureLayer.addChild(layer);
}
checkFeatureSupportingRasterServiceAfterFeatureRemoval(fce);
}
/**
* Removes all features of the given FeatureCollectionEvent from the mappingcomponent. Checks for remaining
* supporting rasterservices and paints handles at the end.
*
* @param fce FeatureCollectionEvent with features to remove
*/
@Override
public void featuresRemoved(final FeatureCollectionEvent fce) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("featuresRemoved"); // NOI18N
}
}
removeFeatures(fce.getEventFeatures());
checkFeatureSupportingRasterServiceAfterFeatureRemoval(fce);
showHandles(false);
refreshAllInfoNodesRequested();
EventQueue.invokeLater(new Thread("MappingComponent featuresRemoved()") {
@Override
public void run() {
memUndo.featuresRemoved(fce.getEventFeatures());
memRedo.featuresRemoved(fce.getEventFeatures());
}
});
}
/**
* Checks after removing one or more features from the mappingcomponent which rasterservices became unnecessary and
* which need a refresh.
*
* @param fce FeatureCollectionEvent with removed features
*/
private void checkFeatureSupportingRasterServiceAfterFeatureRemoval(final FeatureCollectionEvent fce) {
final HashSet<FeatureAwareRasterService> rasterServicesWhichShouldBeRemoved =
new HashSet<FeatureAwareRasterService>();
final HashSet<FeatureAwareRasterService> rasterServicesWhichShouldBeRefreshed =
new HashSet<FeatureAwareRasterService>();
final HashSet<FeatureAwareRasterService> rasterServices = new HashSet<FeatureAwareRasterService>();
for (final Feature f : getFeatureCollection().getAllFeatures()) {
if ((f instanceof RasterLayerSupportedFeature)
&& (((RasterLayerSupportedFeature)f).getSupportingRasterService() != null)) {
final FeatureAwareRasterService rs = ((RasterLayerSupportedFeature)f).getSupportingRasterService();
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("getAllFeatures() Feature:SupportingRasterService:" + f + ":" + rs); // NOI18N
}
}
rasterServices.add(rs); // DANGER
}
}
for (final Feature f : fce.getEventFeatures()) {
if ((f instanceof RasterLayerSupportedFeature)
&& (((RasterLayerSupportedFeature)f).getSupportingRasterService() != null)) {
final FeatureAwareRasterService rs = ((RasterLayerSupportedFeature)f).getSupportingRasterService();
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("getEventFeatures() Feature:SupportingRasterService:" + f + ":" + rs); // NOI18N
}
}
if (rasterServices.contains(rs)) {
for (final Object o : getMappingModel().getRasterServices().values()) {
final MapService r = (MapService)o;
if (r.equals(rs)) {
rasterServicesWhichShouldBeRefreshed.add((FeatureAwareRasterService)r);
}
}
} else {
for (final Object o : getMappingModel().getRasterServices().values()) {
final MapService r = (MapService)o;
if (r.equals(rs)) {
rasterServicesWhichShouldBeRemoved.add((FeatureAwareRasterService)r);
}
}
}
}
}
for (final FeatureAwareRasterService frs : rasterServicesWhichShouldBeRemoved) {
getMappingModel().removeLayer(frs);
}
for (final FeatureAwareRasterService frs : rasterServicesWhichShouldBeRefreshed) {
handleMapService(0, frs, true);
}
}
/**
* public void showFeatureCollection(Feature[] features) { com.vividsolutions.jts.geom.Envelope
* env=computeFeatureEnvelope(features); showFeatureCollection(features,env); } public void
* showFeatureCollection(Feature[] f,com.vividsolutions.jts.geom.Envelope featureEnvelope) { selectedFeature=null;
* handleLayer.removeAllChildren(); //setRasterServiceLayerImagesVisibility(false); Envelope eSquare=null;
* HashSet<Feature> featureSet=new HashSet<Feature>(); featureSet.addAll(holdFeatures);
* featureSet.addAll(java.util.Arrays.asList(f)); Feature[] features=featureSet.toArray(new Feature[0]);
* pFeatureHM.clear(); addFeaturesToMap(features); zoomToFullFeatureCollectionBounds(); }.
*
* @param groupId DOCUMENT ME!
* @param visible DOCUMENT ME!
*/
public void setGroupLayerVisibility(final String groupId, final boolean visible) {
final PLayer layer = this.featureGrpLayerMap.get(groupId);
if (layer != null) {
layer.setVisible(visible);
}
}
/**
* shows the given feature on the map (in the highlighting layer). The color of the feature is 40 percent darker as
* the style defines it.
*
* @param feature the feature that should be shown
* @param duration the feature will be shown for this duration (in ms)
*/
public void highlightFeature(final Feature feature, final int duration) {
final double local_clip_offset_y = clip_offset_y;
final double local_clip_offset_x = clip_offset_x;
final PFeature p = new PFeature(
feature,
getWtst(),
local_clip_offset_x,
local_clip_offset_y,
MappingComponent.this);
Paint paint = p.getPaint();
Color color = Color.BLACK;
if (paint == null) {
paint = p.getStrokePaint();
}
if (paint instanceof Color) {
color = toHighlightingColor((Color)paint);
}
highlightFeature(feature, duration, color);
}
/**
* shows the given feature on the map (in the highlighting layer).
*
* @param feature the feature that should be shown
* @param duration the feature will be shown for this duration (in ms)
* @param highlightColor the color of the highlighted feature
*/
public void highlightFeature(final Feature feature, final int duration, final Color highlightColor) {
final double local_clip_offset_y = clip_offset_y;
final double local_clip_offset_x = clip_offset_x;
final PFeature p = new PFeature(
feature,
getWtst(),
local_clip_offset_x,
local_clip_offset_y,
MappingComponent.this);
highlightingLayer.addChild(p);
if (highlightColor != null) {
if (p.getStrokePaint() != null) {
p.setStrokePaint(highlightColor);
}
if (p.getPaint() != null) {
p.setPaint(highlightColor);
}
}
p.moveToFront();
com.vividsolutions.jts.geom.Point centroid = feature.getGeometry().getCentroid();
centroid = CrsTransformer.transformToCurrentCrs(centroid);
currentCrosshairPoint = new Coordinate(centroid.getX(), centroid.getY());
crossHairPoint(currentCrosshairPoint, 2);
final Coordinate newCrosshairPoint = currentCrosshairPoint;
final Timer t = new Timer(duration, new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
highlightingLayer.removeChild(p);
if (newCrosshairPoint.equals(currentCrosshairPoint)) {
crossHairPoint((Coordinate)null);
}
}
});
t.setRepeats(false);
t.start();
}
/**
* makes to given color 40 percent darker.
*
* @param c DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private Color toHighlightingColor(final Color c) {
int red = (int)(c.getRed() - 70);
int green = (int)(c.getGreen() - 70);
int blue = (int)(c.getBlue() - 70);
if (red < 0) {
red = 0;
}
if (green < 0) {
green = 0;
}
if (blue < 0) {
blue = 0;
}
return new Color(red, green, blue);
}
/**
* is called when new feature is added to FeatureCollection.
*
* @param features DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Collection<PFeature> addFeaturesToMap(final Feature[] features) {
final double local_clip_offset_y = clip_offset_y;
final double local_clip_offset_x = clip_offset_x;
final ArrayList<PFeature> newPFeatures = new ArrayList<>();
/// Hier muss der layer bestimmt werdenn
for (int i = 0; i < features.length; ++i) {
final Feature feature = features[i];
final PFeature p = new PFeature(
feature,
getWtst(),
local_clip_offset_x,
local_clip_offset_y,
MappingComponent.this);
newPFeatures.add(p);
if (feature instanceof ChildNodesProvider) {
p.addChildren(((ChildNodesProvider)feature).provideChildren(p));
}
try {
if (feature instanceof StyledFeature) {
p.setTransparency(((StyledFeature)(feature)).getTransparency());
} else {
p.setTransparency(cismapPrefs.getLayersPrefs().getAppFeatureLayerTranslucency());
}
EventQueue.invokeLater(new Thread("MappingCompoenent addFeaturesToMap()") {
@Override
public void run() {
if (feature instanceof FeatureGroupMember) {
final FeatureGroupMember fgm = (FeatureGroupMember)feature;
final String groupId = fgm.getGroupId();
PLayer groupLayer = featureGrpLayerMap.get(groupId);
if (groupLayer == null) {
groupLayer = new PLayer();
featureLayer.addChild(groupLayer);
featureGrpLayerMap.put(groupId, groupLayer);
if (LOG.isDebugEnabled()) {
LOG.debug("created layer for group " + groupId);
}
}
groupLayer.addChild(p);
if (fgm.getGeometry() != null) {
pFeatureHM.put(fgm.getFeature(), p);
pFeatureHM.put(fgm, p);
}
if (LOG.isDebugEnabled()) {
LOG.debug("added feature to group " + groupId);
}
}
}
});
} catch (final Exception e) {
p.setTransparency(0.8f);
LOG.info("Fehler beim Setzen der Transparenzeinstellungen", e); // NOI18N
}
// So kann man es Piccolo überlassen (müsste nur noch ein transformation machen, die die y achse spiegelt)
if (!(feature instanceof FeatureGroupMember)) {
if (feature.getGeometry() != null) {
pFeatureHM.put(p.getFeature(), p);
final int ii = i;
EventQueue.invokeLater(new Thread("MappingComponent moveToFront after adding") {
@Override
public void run() {
featureLayer.addChild(p);
if (!(features[ii].getGeometry() instanceof com.vividsolutions.jts.geom.Point)) {
p.moveToFront();
}
}
});
}
}
}
refreshAllInfoNodesRequested();
EventQueue.invokeLater(new Thread("MappingComponent movetofront search feature") {
@Override
public void run() {
rescaleStickyNodes();
repaint();
fireFeaturesAddedToMap(Arrays.asList(features));
// SuchFeatures in den Vordergrund stellen
for (final Feature feature : new ArrayList<Feature>(featureCollection.getAllFeatures())) {
if (feature instanceof SearchFeature) {
final PFeature pFeature = pFeatureHM.get(feature);
pFeature.moveToFront();
}
}
}
});
// check whether the feature has a rasterSupportLayer or not
for (final Feature f : features) {
if ((f instanceof RasterLayerSupportedFeature)
&& (((RasterLayerSupportedFeature)f).getSupportingRasterService() != null)) {
final FeatureAwareRasterService rs = ((RasterLayerSupportedFeature)f).getSupportingRasterService();
if (!getMappingModel().getRasterServices().containsValue(rs)) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("FeatureAwareRasterServiceAdded"); // NOI18N
}
}
rs.setFeatureCollection(getFeatureCollection());
getMappingModel().addLayer(rs);
}
}
}
showHandles(false);
return newPFeatures;
}
/**
* DOCUMENT ME!
*
* @param cf DOCUMENT ME!
*/
private void fireFeaturesAddedToMap(final Collection<Feature> cf) {
for (final MapListener curMapListener : mapListeners) {
curMapListener.featuresAddedToMap(cf);
}
}
/**
* Creates an envelope around all features from the given array.
*
* @param features features to create the envelope around
*
* @return Envelope com.vividsolutions.jts.geom.Envelope
*/
private com.vividsolutions.jts.geom.Envelope computeFeatureEnvelope(final Feature[] features) {
final PNode root = new PNode();
for (int i = 0; i < features.length; ++i) {
final PNode p = PNodeFactory.createPFeature(features[i], this);
if (p != null) {
root.addChild(p);
}
}
final PBounds ext = root.getFullBounds();
final com.vividsolutions.jts.geom.Envelope env = new com.vividsolutions.jts.geom.Envelope(
ext.x,
ext.x
+ ext.width,
ext.y,
ext.y
+ ext.height);
return env;
}
/**
* Zooms in / out to match the bounds of the featurecollection.
*/
public void zoomToFullFeatureCollectionBounds() {
zoomToFeatureCollection();
}
/**
* Adds a new cursor to the cursor-hashmap.
*
* @param mode interactionmode as string
* @param cursor cursor-object
*/
public void putCursor(final String mode, final Cursor cursor) {
cursors.put(mode, cursor);
}
/**
* Returns the cursor assigned to the given mode.
*
* @param mode mode as String
*
* @return Cursor-object or null
*/
public Cursor getCursor(final String mode) {
return cursors.get(mode);
}
/**
* Adds a new PBasicInputEventHandler for a specific interactionmode.
*
* @param mode interactionmode as string
* @param listener new PBasicInputEventHandler
*/
public void addInputListener(final String mode, final PBasicInputEventHandler listener) {
inputEventListener.put(mode, listener);
}
/**
* Returns the PBasicInputEventHandler assigned to the committed interactionmode.
*
* @param mode interactionmode as string
*
* @return PBasicInputEventHandler-object or null
*/
public PInputEventListener getInputListener(final String mode) {
final Object o = inputEventListener.get(mode);
if (o instanceof PInputEventListener) {
return (PInputEventListener)o;
} else {
return null;
}
}
/**
* Returns whether the features are editable or not.
*
* @return DOCUMENT ME!
*/
public boolean isReadOnly() {
return readOnly;
}
/**
* Sets all Features ReadOnly use Feature.setEditable(boolean) instead.
*
* @param readOnly DOCUMENT ME!
*/
public void setReadOnly(final boolean readOnly) {
for (final Object f : featureCollection.getAllFeatures()) {
((Feature)f).setEditable(!readOnly);
}
this.readOnly = readOnly;
handleLayer.repaint();
try {
handleLayer.removeAllChildren();
} catch (final Exception e) {
LOG.warn("Fehler bei removeAllCHildren", e); // NOI18N
}
snapHandleLayer.removeAllChildren();
}
/**
* Returns the current HandleInteractionMode.
*
* @return DOCUMENT ME!
*/
public String getHandleInteractionMode() {
return handleInteractionMode;
}
/**
* Changes the HandleInteractionMode. Repaints handles.
*
* @param handleInteractionMode the new HandleInteractionMode
*/
public void setHandleInteractionMode(final String handleInteractionMode) {
this.handleInteractionMode = handleInteractionMode;
showHandles(false);
}
/**
* Returns whether the background is enabled or not.
*
* @return DOCUMENT ME!
*/
public boolean isBackgroundEnabled() {
return backgroundEnabled;
}
/**
* TODO.
*
* @param backgroundEnabled DOCUMENT ME!
*/
public void setBackgroundEnabled(final boolean backgroundEnabled) {
if ((backgroundEnabled == false) && (isBackgroundEnabled() == true)) {
featureServiceLayerVisible = featureServiceLayer.getVisible();
}
this.mapServicelayer.setVisible(backgroundEnabled);
this.featureServiceLayer.setVisible(backgroundEnabled && featureServiceLayerVisible);
for (int i = 0; i < featureServiceLayer.getChildrenCount(); ++i) {
featureServiceLayer.getChild(i).setVisible(backgroundEnabled && featureServiceLayerVisible);
}
if ((backgroundEnabled != isBackgroundEnabled()) && (isBackgroundEnabled() == false)) {
this.queryServices();
}
this.backgroundEnabled = backgroundEnabled;
}
/**
* Returns the featurelayer.
*
* @return DOCUMENT ME!
*/
public PLayer getFeatureLayer() {
return featureLayer;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Map<String, PLayer> getFeatureGroupLayers() {
return this.featureGrpLayerMap;
}
/**
* Adds a PFeature to the PFeatureHashmap.
*
* @param p PFeature to add
*/
public void refreshHM(final PFeature p) {
pFeatureHM.put(p.getFeature(), p);
}
/**
* Returns the selectedObjectPresenter (PCanvas).
*
* @return DOCUMENT ME!
*/
public PCanvas getSelectedObjectPresenter() {
return selectedObjectPresenter;
}
/**
* If f != null it calls the reconsiderFeature()-method of the featurecollection.
*
* @param f feature to reconcile
*/
public void reconsiderFeature(final Feature f) {
if (f != null) {
featureCollection.reconsiderFeature(f);
}
}
/**
* Removes all features of the collection from the hashmap.
*
* @param fc collection of features to remove
*/
public void removeFeatures(final Collection<Feature> fc) {
featureLayer.setVisible(false);
for (final Feature elem : fc) {
removeFromHM(elem);
}
featureLayer.setVisible(true);
}
/**
* Removes a Feature from the PFeatureHashmap. Uses the delivered feature as hashmap-key.
*
* @param f feature of the Pfeature that should be deleted
*/
public void removeFromHM(final Feature f) {
final PFeature pf = pFeatureHM.get(f);
if (pf != null) {
pf.cleanup();
pFeatureHM.remove(f);
stickyPNodes.remove(pf);
try {
LOG.info("Entferne Feature " + f); // NOI18N
featureLayer.removeChild(pf);
for (final PLayer grpLayer : this.featureGrpLayerMap.values()) {
if (grpLayer.removeChild(pf) != null) {
break;
}
}
} catch (Exception ex) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("Remove Child ging Schief. Ist beim Splitten aber normal.", ex); // NOI18N
}
}
}
} else {
LOG.warn("Feature war nicht in pFeatureHM"); // NOI18N
}
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("pFeatureHM" + pFeatureHM); // NOI18N
}
}
}
/**
* Zooms to the current selected node.
*
* @deprecated DOCUMENT ME!
*/
public void zoomToSelectedNode() {
zoomToSelection();
}
/**
* Zooms to the current selected features.
*/
public void zoomToSelection() {
final Collection<Feature> selection = featureCollection.getSelectedFeatures();
zoomToAFeatureCollection(selection, true, false);
}
/**
* Zooms to a specific featurecollection.
*
* @param collection the featurecolltion
* @param withHistory should the zoomaction be undoable
* @param fixedScale fixedScale
*/
public void zoomToAFeatureCollection(final Collection<? extends Feature> collection,
final boolean withHistory,
final boolean fixedScale) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("zoomToAFeatureCollection"); // NOI18N
}
}
try {
handleLayer.removeAllChildren();
} catch (final Exception e) {
LOG.warn("Fehler bei removeAllCHildren", e); // NOI18N
}
boolean first = true;
Geometry g = null;
for (final Feature f : collection) {
if (first) {
if (f.getGeometry() != null) {
g = CrsTransformer.transformToGivenCrs(f.getGeometry(), mappingModel.getSrs().getCode())
.getEnvelope();
if ((f instanceof Bufferable) && mappingModel.getSrs().isMetric()) {
g = g.buffer(((Bufferable)f).getBuffer() + 0.001);
}
first = false;
}
} else if (f.getGeometry() != null) {
Geometry geometry = CrsTransformer.transformToGivenCrs(f.getGeometry(),
mappingModel.getSrs().getCode()).getEnvelope();
if ((f instanceof Bufferable) && mappingModel.getSrs().isMetric()) {
geometry = geometry.buffer(((Bufferable)f).getBuffer() + 0.001);
}
g = g.getEnvelope().union(geometry);
}
}
if (g != null) {
// FIXME: we shouldn't only complain but do sth
if ((getHeight() == 0) || (getWidth() == 0)) {
LOG.warn("DIVISION BY ZERO"); // NOI18N
}
// dreisatz.de
final double hBuff = g.getEnvelopeInternal().getHeight() / ((double)getHeight()) * 10;
final double vBuff = g.getEnvelopeInternal().getWidth() / ((double)getWidth()) * 10;
double buff = 0;
if (hBuff > vBuff) {
buff = hBuff;
} else {
buff = vBuff;
}
if (buff == 0.0) {
if (mappingModel.getSrs().isMetric()) {
buff = 1.0;
} else {
buff = 0.01;
}
}
g = g.buffer(buff);
final BoundingBox bb = new BoundingBox(g);
final boolean onlyOnePoint = (collection.size() == 1)
&& (((Feature)(collection.toArray()[0])).getGeometry()
instanceof com.vividsolutions.jts.geom.Point);
gotoBoundingBox(bb, withHistory, !(fixedScale || (onlyOnePoint && (g.getArea() < 10))), animationDuration);
}
}
/**
* Deletes all present handles from the handlelayer. Tells all selected features in the featurecollection to create
* their handles and to add them to the handlelayer.
*
* @param waitTillAllAnimationsAreComplete wait until all animations are completed before create the handles
*/
public void showHandles(final boolean waitTillAllAnimationsAreComplete) {
// are there features selected?
if (featureCollection.getSelectedFeatures().size() > 0) {
// DANGER Mehrfachzeichnen von Handles durch parallelen Aufruf
final Runnable handle = new Thread("MappingComponent showHandles()") {
@Override
public void run() {
// alle bisherigen Handles entfernen
EventQueue.invokeLater(new Thread("MappingComponent showHandles(animated)") {
@Override
public void run() {
try {
handleLayer.removeAllChildren();
} catch (final Exception e) {
LOG.warn("Fehler bei removeAllCHildren", e); // NOI18N
}
}
});
while (getAnimating() && waitTillAllAnimationsAreComplete) {
try {
Thread.currentThread().sleep(10);
} catch (final Exception e) {
LOG.warn("Unterbrechung bei getAnimating()", e); // NOI18N
}
}
if (featureCollection.areFeaturesEditable()
&& (getInteractionMode().equals(SELECT)
|| getInteractionMode().equals(MOVE_POLYGON)
|| getInteractionMode().equals(PRINTING_AREA_SELECTION)
|| getInteractionMode().equals(LINEAR_REFERENCING)
|| getInteractionMode().equals(PAN)
|| getInteractionMode().equals(ZOOM)
|| getInteractionMode().equals(ALKIS_PRINT)
|| getInteractionMode().equals(SPLIT_POLYGON))) {
// Handles für alle selektierten Features der Collection hinzufügen
if (getHandleInteractionMode().equals(ROTATE_POLYGON)) {
final LinkedHashSet<Feature> copy = new LinkedHashSet(
featureCollection.getSelectedFeatures());
for (final Feature selectedFeature : copy) {
if ((selectedFeature instanceof Feature) && selectedFeature.isEditable()
&& !(selectedFeature instanceof RequestForHidingHandles)) {
// manipulates gui -> edt
EventQueue.invokeLater(new Thread("MappingComponent addRotationHandles") {
@Override
public void run() {
if ((pFeatureHM.get(selectedFeature) != null)
&& pFeatureHM.get(selectedFeature).getVisible()) {
pFeatureHM.get(selectedFeature).addRotationHandles(handleLayer);
} else {
LOG.warn("pFeatureHM.get(" + selectedFeature + ")==null"); // NOI18N
}
}
});
}
}
} else {
final LinkedHashSet<Feature> copy = new LinkedHashSet(
featureCollection.getSelectedFeatures());
for (final Feature selectedFeature : copy) {
if ((selectedFeature != null) && selectedFeature.isEditable()
&& !(selectedFeature instanceof RequestForHidingHandles)) {
if ((pFeatureHM.get(selectedFeature) != null)
&& pFeatureHM.get(selectedFeature).getVisible()) {
// manipulates gui -> edt
EventQueue.invokeLater(new Thread("MappingComponent addHandles") {
@Override
public void run() {
try {
pFeatureHM.get(selectedFeature).addHandles(handleLayer);
} catch (final Exception e) {
LOG.error("Error bei addHandles: ", e); // NOI18N
}
}
});
} else {
LOG.warn("pFeatureHM.get(" + selectedFeature + ")==null"); // NOI18N
}
// DANGER mit break werden nur die Handles EINES slektierten Features angezeigt
// wird break auskommentiert werden jedoch zu viele Handles angezeigt break;
}
}
}
}
}
};
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("showHandles", new CurrentStackTrace()); // NOI18N
}
}
CismetThreadPool.execute(new Thread(handle, "MappingCompoenent showHandles()"));
} else {
// alle bisherigen Handles entfernen
EventQueue.invokeLater(new Thread("MappingComponent removeAllChildren") {
@Override
public void run() {
try {
handleLayer.removeAllChildren();
} catch (final Exception e) {
LOG.warn("Fehler bei removeAllCHildren", e); // NOI18N
}
}
});
}
}
/**
* Will return a PureNewFeature if there is only one in the featurecollection else null.
*
* @return DOCUMENT ME!
*/
public PFeature getSolePureNewFeature() {
int counter = 0;
PFeature sole = null;
for (final Iterator it = featureLayer.getChildrenIterator(); it.hasNext();) {
final Object o = it.next();
if (o instanceof PFeature) {
if (((PFeature)o).getFeature() instanceof PureNewFeature) {
++counter;
sole = ((PFeature)o);
}
}
}
if (counter == 1) {
return sole;
} else {
return null;
}
}
/**
* Returns the temporary featurelayer.
*
* @return DOCUMENT ME!
*/
public PLayer getTmpFeatureLayer() {
return tmpFeatureLayer;
}
/**
* Assigns a new temporary featurelayer.
*
* @param tmpFeatureLayer PLayer
*/
public void setTmpFeatureLayer(final PLayer tmpFeatureLayer) {
this.tmpFeatureLayer = tmpFeatureLayer;
}
/**
* Returns whether the grid is enabled or not.
*
* @return DOCUMENT ME!
*/
public boolean isGridEnabled() {
return gridEnabled;
}
/**
* Enables or disables the grid.
*
* @param gridEnabled true, to enable the grid
*/
public void setGridEnabled(final boolean gridEnabled) {
this.gridEnabled = gridEnabled;
}
/**
* Returns a String from two double-values. Serves the visualization.
*
* @param x X-coordinate
* @param y Y-coordinate
*
* @return a String-object like "(X,Y)"
*/
public static String getCoordinateString(final double x, final double y) {
final DecimalFormat df = new DecimalFormat("0.00"); // NOI18N
final DecimalFormatSymbols dfs = new DecimalFormatSymbols();
dfs.setDecimalSeparator('.');
df.setDecimalFormatSymbols(dfs);
return "(" + df.format(x) + "," + df.format(y) + ")"; // NOI18N
}
/**
* DOCUMENT ME!
*
* @param event DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public com.vividsolutions.jts.geom.Point getPointGeometryFromPInputEvent(final PInputEvent event) {
final double xCoord = getWtst().getSourceX(event.getPosition().getX() - getClip_offset_x());
final double yCoord = getWtst().getSourceY(event.getPosition().getY() - getClip_offset_y());
final GeometryFactory gf = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING),
CrsTransformer.extractSridFromCrs(getMappingModel().getSrs().getCode()));
return gf.createPoint(new Coordinate(xCoord, yCoord));
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public PLayer getHandleLayer() {
return handleLayer;
}
/**
* DOCUMENT ME!
*
* @param handleLayer DOCUMENT ME!
*/
public void setHandleLayer(final PLayer handleLayer) {
this.handleLayer = handleLayer;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isVisualizeSnappingEnabled() {
return visualizeSnappingEnabled;
}
/**
* DOCUMENT ME!
*
* @param visualizeSnappingEnabled DOCUMENT ME!
*/
public void setVisualizeSnappingEnabled(final boolean visualizeSnappingEnabled) {
this.visualizeSnappingEnabled = visualizeSnappingEnabled;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isVisualizeSnappingRectEnabled() {
return visualizeSnappingRectEnabled;
}
/**
* DOCUMENT ME!
*
* @param visualizeSnappingRectEnabled DOCUMENT ME!
*/
public void setVisualizeSnappingRectEnabled(final boolean visualizeSnappingRectEnabled) {
this.visualizeSnappingRectEnabled = visualizeSnappingRectEnabled;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public int getSnappingRectSize() {
return snappingRectSize;
}
/**
* DOCUMENT ME!
*
* @param snappingRectSize DOCUMENT ME!
*/
public void setSnappingRectSize(final int snappingRectSize) {
this.snappingRectSize = snappingRectSize;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public PLayer getSnapHandleLayer() {
return snapHandleLayer;
}
/**
* DOCUMENT ME!
*
* @param snapHandleLayer DOCUMENT ME!
*/
public void setSnapHandleLayer(final PLayer snapHandleLayer) {
this.snapHandleLayer = snapHandleLayer;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isSnappingEnabled() {
return snappingEnabled;
}
/**
* DOCUMENT ME!
*
* @param snappingEnabled DOCUMENT ME!
*/
public void setSnappingEnabled(final boolean snappingEnabled) {
this.snappingEnabled = snappingEnabled;
setVisualizeSnappingEnabled(snappingEnabled);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isSnappingOnLineEnabled() {
return snappingOnLineEnabled;
}
/**
* DOCUMENT ME!
*
* @param snappingOnLineEnabled DOCUMENT ME!
*/
public void setSnappingOnLineEnabled(final boolean snappingOnLineEnabled) {
this.snappingOnLineEnabled = snappingOnLineEnabled;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public PLayer getFeatureServiceLayer() {
return featureServiceLayer;
}
/**
* DOCUMENT ME!
*
* @param featureServiceLayer DOCUMENT ME!
*/
public void setFeatureServiceLayer(final PLayer featureServiceLayer) {
this.featureServiceLayer = featureServiceLayer;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public int getAnimationDuration() {
return animationDuration;
}
/**
* DOCUMENT ME!
*
* @param animationDuration DOCUMENT ME!
*/
public void setAnimationDuration(final int animationDuration) {
this.animationDuration = animationDuration;
}
/**
* DOCUMENT ME!
*
* @param prefs DOCUMENT ME!
*/
@Deprecated
public void setPreferences(final CismapPreferences prefs) {
LOG.warn("involing deprecated operation setPreferences()"); // NOI18N
cismapPrefs = prefs;
final ActiveLayerModel mm = new ActiveLayerModel();
final LayersPreferences layersPrefs = prefs.getLayersPrefs();
final GlobalPreferences globalPrefs = prefs.getGlobalPrefs();
setSnappingRectSize(globalPrefs.getSnappingRectSize());
setSnappingEnabled(globalPrefs.isSnappingEnabled());
setVisualizeSnappingEnabled(globalPrefs.isSnappingPreviewEnabled());
setAnimationDuration(globalPrefs.getAnimationDuration());
setInteractionMode(globalPrefs.getStartMode());
mm.addHome(globalPrefs.getInitialBoundingBox());
final Crs crs = new Crs();
crs.setCode(globalPrefs.getInitialBoundingBox().getSrs());
crs.setName(globalPrefs.getInitialBoundingBox().getSrs());
crs.setShortname(globalPrefs.getInitialBoundingBox().getSrs());
mm.setSrs(crs);
final TreeMap raster = layersPrefs.getRasterServices();
if (raster != null) {
final Iterator it = raster.keySet().iterator();
while (it.hasNext()) {
final Object key = it.next();
final Object o = raster.get(key);
if (o instanceof MapService) {
mm.addLayer((RetrievalServiceLayer)o);
}
}
}
final TreeMap features = layersPrefs.getFeatureServices();
if (features != null) {
final Iterator it = features.keySet().iterator();
while (it.hasNext()) {
final Object key = it.next();
final Object o = features.get(key);
if (o instanceof MapService) {
// TODO
mm.addLayer((RetrievalServiceLayer)o);
}
}
}
setMappingModel(mm);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public CismapPreferences getCismapPrefs() {
return cismapPrefs;
}
/**
* DOCUMENT ME!
*
* @param duration DOCUMENT ME!
* @param animationDuration DOCUMENT ME!
* @param what DOCUMENT ME!
* @param number DOCUMENT ME!
*/
public void flash(final int duration, final int animationDuration, final int what, final int number) {
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public PLayer getDragPerformanceImproverLayer() {
return dragPerformanceImproverLayer;
}
/**
* DOCUMENT ME!
*
* @param dragPerformanceImproverLayer DOCUMENT ME!
*/
public void setDragPerformanceImproverLayer(final PLayer dragPerformanceImproverLayer) {
this.dragPerformanceImproverLayer = dragPerformanceImproverLayer;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
@Deprecated
public PLayer getRasterServiceLayer() {
return mapServicelayer;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public PLayer getMapServiceLayer() {
return mapServicelayer;
}
/**
* DOCUMENT ME!
*
* @param rasterServiceLayer DOCUMENT ME!
*/
public void setRasterServiceLayer(final PLayer rasterServiceLayer) {
this.mapServicelayer = rasterServiceLayer;
}
/**
* DOCUMENT ME!
*
* @param f DOCUMENT ME!
*/
public void showGeometryInfoPanel(final Feature f) {
}
/**
* Adds a PropertyChangeListener to the listener list.
*
* @param l The listener to add.
*/
@Override
public void addPropertyChangeListener(final PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
/**
* Removes a PropertyChangeListener from the listener list.
*
* @param l The listener to remove.
*/
@Override
public void removePropertyChangeListener(final PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
/**
* Setter for property taskCounter. former synchronized method
*/
public void fireActivityChanged() {
propertyChangeSupport.firePropertyChange("activityChanged", null, null); // NOI18N
}
/**
* Returns true, if there's still one layercontrol running. Else false; former synchronized method
*
* @return DOCUMENT ME!
*/
public boolean isRunning() {
for (final LayerControl lc : layerControls) {
if (lc.isRunning()) {
return true;
}
}
return false;
}
/**
* Sets the visibility of all infonodes.
*
* @param visible true, if infonodes should be visible
*/
public void setInfoNodesVisible(final boolean visible) {
infoNodesVisible = visible;
for (final Iterator it = featureLayer.getChildrenIterator(); it.hasNext();) {
final Object elem = it.next();
if (elem instanceof PFeature) {
((PFeature)elem).setInfoNodeVisible(visible);
}
}
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("setInfoNodesVisible()"); // NOI18N
}
}
rescaleStickyNodes();
}
/**
* Adds an object to the historymodel.
*
* @param o Object to add
*/
@Override
public void addToHistory(final Object o) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("addToHistory:" + o.toString()); // NOI18N
}
}
historyModel.addToHistory(o);
}
/**
* Removes a specific HistoryModelListener from the historymodel.
*
* @param hml HistoryModelListener
*/
@Override
public void removeHistoryModelListener(final de.cismet.tools.gui.historybutton.HistoryModelListener hml) {
historyModel.removeHistoryModelListener(hml);
}
/**
* Adds aHistoryModelListener to the historymodel.
*
* @param hml HistoryModelListener
*/
@Override
public void addHistoryModelListener(final de.cismet.tools.gui.historybutton.HistoryModelListener hml) {
historyModel.addHistoryModelListener(hml);
}
/**
* Sets the maximum value of saved historyactions.
*
* @param max new integer value
*/
@Override
public void setMaximumPossibilities(final int max) {
historyModel.setMaximumPossibilities(max);
}
/**
* Redos the last undone historyaction.
*
* @param external true, if fireHistoryChanged-action should be fired
*
* @return PBounds of the forward-action
*/
@Override
public Object forward(final boolean external) {
final PBounds fwd = (PBounds)historyModel.forward(external);
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("HistoryModel.forward():" + fwd); // NOI18N
}
}
if (external) {
this.gotoBoundsWithoutHistory(fwd);
}
return fwd;
}
/**
* Undos the last action.
*
* @param external true, if fireHistoryChanged-action should be fired
*
* @return PBounds of the back-action
*/
@Override
public Object back(final boolean external) {
final PBounds back = (PBounds)historyModel.back(external);
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("HistoryModel.back():" + back); // NOI18N
}
}
if (external) {
this.gotoBoundsWithoutHistory(back);
}
return back;
}
/**
* Returns true, if it's possible to redo an action.
*
* @return DOCUMENT ME!
*/
@Override
public boolean isForwardPossible() {
return historyModel.isForwardPossible();
}
/**
* Returns true, if it's possible to undo an action.
*
* @return DOCUMENT ME!
*/
@Override
public boolean isBackPossible() {
return historyModel.isBackPossible();
}
/**
* Returns a vector with all redo-possibilities.
*
* @return DOCUMENT ME!
*/
@Override
public Vector getForwardPossibilities() {
return historyModel.getForwardPossibilities();
}
/**
* Returns the current element of the historymodel.
*
* @return DOCUMENT ME!
*/
@Override
public Object getCurrentElement() {
return historyModel.getCurrentElement();
}
/**
* Returns a vector with all undo-possibilities.
*
* @return DOCUMENT ME!
*/
@Override
public Vector getBackPossibilities() {
return historyModel.getBackPossibilities();
}
/**
* Returns whether an internallayerwidget is available.
*
* @return DOCUMENT ME!
*/
@Deprecated
public boolean isInternalLayerWidgetAvailable() {
return this.getInternalWidget(LAYERWIDGET) != null;
}
/**
* Sets the variable, if an internallayerwidget is available or not.
*
* @param internalLayerWidgetAvailable true, if available
*/
@Deprecated
public void setInternalLayerWidgetAvailable(final boolean internalLayerWidgetAvailable) {
if (!internalLayerWidgetAvailable && (this.getInternalWidget(LAYERWIDGET) != null)) {
this.removeInternalWidget(LAYERWIDGET);
} else if (internalLayerWidgetAvailable && (this.getInternalWidget(LAYERWIDGET) == null)) {
final NewSimpleInternalLayerWidget simpleInternalLayerWidget = new NewSimpleInternalLayerWidget(
MappingComponent.this);
MappingComponent.this.addInternalWidget(
LAYERWIDGET,
MappingComponent.POSITION_SOUTHEAST,
simpleInternalLayerWidget);
}
}
/**
* DOCUMENT ME!
*
* @param mme DOCUMENT ME!
*/
@Override
public void mapServiceLayerStructureChanged(final de.cismet.cismap.commons.MappingModelEvent mme) {
}
/**
* Removes the mapservice from the rasterservicelayer.
*
* @param rasterService the removing mapservice
*/
@Override
public void mapServiceRemoved(final MapService rasterService) {
try {
mapServicelayer.removeChild(rasterService.getPNode());
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_REMOVED, rasterService));
}
if (rasterService instanceof FeatureAwareRasterService) {
final List<Feature> lf = new ArrayList<Feature>();
for (final Feature f : getFeatureCollection().getAllFeatures()) {
if (f instanceof RasterLayerSupportedFeature) {
final RasterLayerSupportedFeature rlsf = (RasterLayerSupportedFeature)f;
if ((rlsf.getSupportingRasterService() != null)
&& rlsf.getSupportingRasterService().equals(rasterService)) {
lf.add(f);
}
}
}
getFeatureCollection().removeFeatures(lf);
}
System.gc();
} catch (final Exception e) {
LOG.warn("Fehler bei mapServiceRemoved", e); // NOI18N
}
}
/**
* Adds the commited mapservice on the last position to the rasterservicelayer.
*
* @param mapService the new mapservice
*/
@Override
public void mapServiceAdded(final MapService mapService) {
addMapService(mapService, mapServicelayer.getChildrenCount());
if (mapService instanceof FeatureAwareRasterService) {
((FeatureAwareRasterService)mapService).setFeatureCollection(getFeatureCollection());
}
if ((mapService instanceof ServiceLayer) && ((ServiceLayer)mapService).isEnabled() && !locked) {
handleMapService(0, mapService, false);
}
}
/**
* Returns the current OGC scale.
*
* @return DOCUMENT ME!
*/
public double getCurrentOGCScale() {
// funktioniert nur bei metrischen SRS's
final double realWorldWidth = getCamera().getViewBounds().getWidth();
final double realWorldHeight = getCamera().getViewBounds().getHeight();
final double windowWidthInPixel = getWidth();
final double windowHeightInPixel = getHeight();
final double h = realWorldHeight / windowHeightInPixel;
final double w = realWorldWidth / windowWidthInPixel;
return Math.sqrt((h * h) + (w * w));
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
@Deprecated
public BoundingBox getCurrentBoundingBox() {
return getCurrentBoundingBoxFromCamera();
}
/**
* <p>Returns the current BoundingBox.</p>
*
* @return DOCUMENT ME!
*/
public BoundingBox getCurrentBoundingBoxFromCamera() {
if (fixedBoundingBox != null) {
return fixedBoundingBox;
} else {
try {
final PBounds bounds = getCamera().getViewBounds();
final double x1 = wtst.getWorldX(bounds.getX());
final double y1 = wtst.getWorldY(bounds.getY());
final double x2 = x1 + bounds.width;
final double y2 = y1 - bounds.height;
final Crs currentCrs = CismapBroker.getInstance().getSrs();
return new XBoundingBox(x1, y1, x2, y2, currentCrs.getCode(), isInMetricSRS());
} catch (final Exception e) {
LOG.error("cannot create bounding box from current view, return null", e); // NOI18N
return null;
}
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isInMetricSRS() {
final Crs currentCrs = CismapBroker.getInstance().getSrs();
// FIXME: this is a hack to overcome the "metric" issue for 4326 default srs
if (CrsTransformer.getCurrentSrid() == 4326) {
return false;
} else {
return currentCrs.isMetric();
}
}
/**
* Returns a BoundingBox with a fixed size.
*
* @return DOCUMENT ME!
*/
public BoundingBox getFixedBoundingBox() {
return fixedBoundingBox;
}
/**
* Assigns fixedBoundingBox a new value.
*
* @param fixedBoundingBox new boundingbox
*/
public void setFixedBoundingBox(final BoundingBox fixedBoundingBox) {
this.fixedBoundingBox = fixedBoundingBox;
}
/**
* Paints the outline of the forwarded BoundingBox.
*
* @param bb BoundingBox
*/
public void outlineArea(final BoundingBox bb) {
outlineArea(bb, null);
}
/**
* Paints the outline of the forwarded PBounds.
*
* @param b PBounds
*/
public void outlineArea(final PBounds b) {
outlineArea(b, null);
}
/**
* Paints a filled rectangle of the area of the forwarded BoundingBox.
*
* @param bb BoundingBox
* @param fillingPaint Color to fill the rectangle
*/
public void outlineArea(final BoundingBox bb, final Paint fillingPaint) {
PBounds pb = null;
if (bb != null) {
pb = new PBounds(wtst.getScreenX(bb.getX1()),
wtst.getScreenY(bb.getY2()),
bb.getX2()
- bb.getX1(),
bb.getY2()
- bb.getY1());
}
outlineArea(pb, fillingPaint);
}
/**
* Paints a filled rectangle of the area of the forwarded PBounds.
*
* @param b PBounds to paint
* @param fillingColor Color to fill the rectangle
*/
public void outlineArea(final PBounds b, final Paint fillingColor) {
if (b == null) {
if (highlightingLayer.getChildrenCount() > 0) {
highlightingLayer.removeAllChildren();
}
} else {
highlightingLayer.removeAllChildren();
highlightingLayer.setTransparency(1);
final PPath rectangle = new PPath();
rectangle.setPaint(fillingColor);
rectangle.setStroke(new FixedWidthStroke());
rectangle.setStrokePaint(new Color(100, 100, 100, 255));
rectangle.setPathTo(b);
highlightingLayer.addChild(rectangle);
}
}
/**
* Highlights the delivered BoundingBox. Calls highlightArea(PBounds b) internally.
*
* @param bb BoundingBox to highlight
*/
public void highlightArea(final BoundingBox bb) {
PBounds pb = null;
if (bb != null) {
pb = new PBounds(wtst.getScreenX(bb.getX1()),
wtst.getScreenY(bb.getY2()),
bb.getX2()
- bb.getX1(),
bb.getY2()
- bb.getY1());
}
highlightArea(pb);
}
/**
* Highlights the delivered PBounds by painting over with a transparent white.
*
* @param b PBounds to hightlight
*/
private void highlightArea(final PBounds b) {
if (b == null) {
if (highlightingLayer.getChildrenCount() > 0) {
}
highlightingLayer.animateToTransparency(0, animationDuration);
highlightingLayer.removeAllChildren();
} else {
highlightingLayer.removeAllChildren();
highlightingLayer.setTransparency(1);
final PPath rectangle = new PPath();
rectangle.setPaint(new Color(255, 255, 255, 100));
rectangle.setStroke(null);
rectangle.setPathTo(this.getCamera().getViewBounds());
highlightingLayer.addChild(rectangle);
rectangle.animateToBounds(b.x, b.y, b.width, b.height, this.animationDuration);
}
}
/**
* Paints a crosshair at the delivered coordinate. Calculates a Point from the coordinate and calls
* crossHairPoint(Point p) internally.
*
* @param c coordinate of the crosshair's venue
*/
public void crossHairPoint(final Coordinate c) {
crossHairPoint(c, 1);
}
/**
* Paints a crosshair at the delivered coordinate. Calculates a Point from the coordinate and calls
* crossHairPoint(Point p) internally.
*
* @param c coordinate of the crosshair's venue
* @param thickness DOCUMENT ME!
*/
public void crossHairPoint(final Coordinate c, final int thickness) {
Point p = null;
if (c != null) {
wtst = null;
p = new Point((int)getWtst().getScreenX(c.x), (int)getWtst().getScreenY(c.y));
}
crossHairPoint(p, thickness);
}
/**
* Paints a crosshair at the delivered point.
*
* @param p point of the crosshair's venue
*/
public void crossHairPoint(final Point p) {
crossHairPoint(p, 1);
}
/**
* Paints a crosshair at the delivered point.
*
* @param p point of the crosshair's venue
* @param thickness DOCUMENT ME!
*/
public void crossHairPoint(final Point p, final int thickness) {
if (p == null) {
if (crosshairLayer.getChildrenCount() > 0) {
crosshairLayer.removeAllChildren();
}
} else {
crosshairLayer.removeAllChildren();
crosshairLayer.setTransparency(1);
final PPath lineX = new PPath();
final PPath lineY = new PPath();
lineX.setStroke(new CustomFixedWidthStroke(thickness, this));
lineX.setStrokePaint(new Color(100, 100, 100, 255));
lineY.setStroke(new CustomFixedWidthStroke(thickness, this));
lineY.setStrokePaint(new Color(100, 100, 100, 255));
final PBounds current = getCamera().getViewBounds();
final PBounds x = new PBounds(current.x, p.y, current.width, 1);
final PBounds y = new PBounds(p.x, current.y, 1, current.height);
lineX.setPathTo(x);
crosshairLayer.addChild(lineX);
lineY.setPathTo(y);
crosshairLayer.addChild(lineY);
}
repaint();
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
@Override
public Element getConfiguration() {
if (LOG.isDebugEnabled()) {
LOG.debug("writing configuration <cismapMappingPreferences>"); // NOI18N
}
final Element ret = new Element("cismapMappingPreferences"); // NOI18N
ret.setAttribute("interactionMode", getInteractionMode()); // NOI18N
ret.setAttribute(
"creationMode",
((CreateNewGeometryListener)getInputListener(MappingComponent.NEW_POLYGON)).getMode()); // NOI18N
ret.setAttribute("handleInteractionMode", getHandleInteractionMode()); // NOI18N
ret.setAttribute("snapping", new Boolean(isSnappingEnabled()).toString()); // NOI18N
final Object inputListener = getInputListener(CREATE_SEARCH_POLYGON);
if (inputListener instanceof CreateSearchGeometryListener) {
final CreateSearchGeometryListener listener = (CreateSearchGeometryListener)inputListener;
ret.setAttribute("createSearchMode", listener.getMode());
}
// Position
final Element currentPosition = new Element("Position"); // NOI18N
currentPosition.addContent(getCurrentBoundingBoxFromCamera().getJDOMElement());
currentPosition.setAttribute("CRS", mappingModel.getSrs().getCode());
ret.addContent(currentPosition);
// Crs
final Element crsListElement = new Element("crsList");
for (final Crs tmp : crsList) {
crsListElement.addContent(tmp.getJDOMElement());
}
ret.addContent(crsListElement);
if (printingSettingsDialog != null) {
ret.addContent(printingSettingsDialog.getConfiguration());
}
if (CismapBroker.getInstance().getMinOpacityToStayEnabled() != null) {
final Element minOpacityToStayEnabled = new Element("minOpacityToStayEnabled");
minOpacityToStayEnabled.addContent(CismapBroker.getInstance().getMinOpacityToStayEnabled().toString());
ret.addContent(minOpacityToStayEnabled);
}
final Element multiFeaturePopupMenuEnabled = new Element("multiFeaturePopupMenuEnabled");
multiFeaturePopupMenuEnabled.addContent(Boolean.toString(
CismapBroker.getInstance().isMultiFeaturePopupMenuEnabled()));
ret.addContent(multiFeaturePopupMenuEnabled);
// save internal widgets status
final Element widgets = new Element("InternalWidgets"); // NOI18N
for (final String name : this.internalWidgets.keySet()) {
final Element widget = new Element("Widget"); // NOI18N
widget.setAttribute("name", name); // NOI18N
widget.setAttribute("position", String.valueOf(this.internalWidgetPositions.get(name))); // NOI18N
widget.setAttribute("visible", String.valueOf(this.getInternalWidget(name).isVisible())); // NOI18N
widgets.addContent(widget);
}
ret.addContent(widgets);
return ret;
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void masterConfigure(final Element e) {
final Element prefs = e.getChild("cismapMappingPreferences"); // NOI18N
// CRS List
try {
final List crsElements = prefs.getChild("crsList").getChildren("crs"); // NOI18N
boolean defaultCrsFound = false;
crsList.clear();
for (final Object elem : crsElements) {
if (elem instanceof Element) {
final Crs s = new Crs((Element)elem);
crsList.add(s);
if (s.isSelected() && (s.isMetric() || s.isDefaultCrs())) {
try {
if (defaultCrsFound) {
LOG.warn("More than one default CRS is set. "
+ "Please check your master configuration file."); // NOI18N
}
CismapBroker.getInstance().setDefaultCrs(s.getCode());
defaultCrsFound = true;
transformer = new CrsTransformer(s.getCode());
} catch (final Exception ex) {
LOG.error("Cannot create a GeoTransformer for the crs " + s.getCode(), ex);
}
}
}
}
} catch (final Exception skip) {
LOG.error("Error while reading the crs list", skip); // NOI18N
}
if (CismapBroker.getInstance().getDefaultCrs() == null) {
LOG.fatal("The default CRS is not set. This can lead to almost irreparable data errors. "
+ "Keep in mind: The default CRS must be metric"); // NOI18N
}
if (transformer == null) {
LOG.error("No metric default crs found. Use EPSG:31466 as default crs"); // NOI18N
try {
transformer = new CrsTransformer("EPSG:31466"); // NOI18N
CismapBroker.getInstance().setDefaultCrs("EPSG:31466"); // NOI18N
} catch (final Exception ex) {
LOG.error("Cannot create a GeoTransformer for the crs EPSG:31466", ex); // NOI18N
}
}
// HOME
try {
if (getMappingModel() instanceof ActiveLayerModel) {
final ActiveLayerModel alm = (ActiveLayerModel)getMappingModel();
final Iterator<Element> it = prefs.getChildren("home").iterator(); // NOI18N
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("Es gibt " + prefs.getChildren("home").size() + " Home Einstellungen"); // NOI18N
}
}
while (it.hasNext()) {
final Element elem = it.next();
final String srs = elem.getAttribute("srs").getValue(); // NOI18N
boolean metric = false;
try {
metric = elem.getAttribute("metric").getBooleanValue(); // NOI18N
} catch (DataConversionException dce) {
LOG.warn("Metric hat falschen Syntax", dce); // NOI18N
}
boolean defaultVal = false;
try {
defaultVal = elem.getAttribute("default").getBooleanValue(); // NOI18N
} catch (DataConversionException dce) {
LOG.warn("default hat falschen Syntax", dce); // NOI18N
}
final XBoundingBox xbox = new XBoundingBox(elem, srs, metric);
alm.addHome(xbox);
if (defaultVal) {
Crs crsObject = null;
for (final Crs tmp : crsList) {
if (tmp.getCode().equals(srs)) {
crsObject = tmp;
break;
}
}
if (crsObject == null) {
LOG.error("CRS " + srs + " from the default home is not found in the crs list");
crsObject = new Crs(srs, srs, srs, true, false);
crsList.add(crsObject);
}
alm.setSrs(crsObject);
alm.setDefaultHomeSrs(crsObject);
CismapBroker.getInstance().setSrs(crsObject);
wtst = null;
getWtst();
}
}
}
} catch (final Exception ex) {
LOG.error("Fehler beim MasterConfigure der MappingComponent", ex); // NOI18N
}
try {
final Element defaultCrs = prefs.getChild("defaultCrs");
final int defaultCrsInt = Integer.parseInt(defaultCrs.getAttributeValue("geometrySridAlias"));
CismapBroker.getInstance().setDefaultCrsAlias(defaultCrsInt);
} catch (final Exception ex) {
LOG.error("Error while reading the default crs alias from the master configuration file.", ex);
}
try {
final List scalesList = prefs.getChild("printing").getChildren("scale"); // NOI18N
scales.clear();
for (final Object elem : scalesList) {
if (elem instanceof Element) {
final Scale s = new Scale((Element)elem);
scales.add(s);
}
}
} catch (final Exception skip) {
LOG.error("Fehler beim Lesen von Scale", skip); // NOI18N
}
try {
final String minOpacity = prefs.getChildText("minOpacityToStayEnabled");
if (minOpacity != null) {
CismapBroker.getInstance().setMinOpacityToStayEnabled(Float.parseFloat(minOpacity));
}
} catch (NumberFormatException ex) {
LOG.error("The min opacity to stay enabled value is not a number.", ex); // NOI18N
}
try {
final String multiFeaturePopupMenuEnabled = prefs.getChildText("multiFeaturePopupMenuEnabled");
if (multiFeaturePopupMenuEnabled != null) {
CismapBroker.getInstance()
.setMultiFeaturePopupMenuEnabled(Boolean.parseBoolean(multiFeaturePopupMenuEnabled));
}
} catch (final NumberFormatException ex) {
LOG.error("The MultiFeaturePopupMenu stays disabled, value is not valid", ex); // NOI18N
}
// Und jetzt noch die PriningEinstellungen
initPrintingDialogs();
printingSettingsDialog.masterConfigure(prefs);
}
/**
* Configurates this MappingComponent.
*
* @param e JDOM-Element with configuration
*/
@Override
public void configure(final Element e) {
final Element prefs = e.getChild("cismapMappingPreferences"); // NOI18N
try {
final List crsElements = prefs.getChild("crsList").getChildren("crs"); // NOI18N
for (final Object elem : crsElements) {
if (elem instanceof Element) {
final Crs s = new Crs((Element)elem);
// the crs is equals to an other crs, if the code is equal.
// Only crs, which are not defined in the master configuration file will be added
if (!crsList.contains(s)) {
crsList.add(s);
}
}
}
} catch (final Exception skip) {
LOG.warn("Error while reading the crs list", skip); // NOI18N
}
// InteractionMode
try {
final String interactMode = prefs.getAttribute("interactionMode").getValue(); // NOI18N
setInteractionMode(interactMode);
if (interactMode.equals(MappingComponent.NEW_POLYGON)) {
try {
final String creationMode = prefs.getAttribute("creationMode").getValue(); // NOI18N
((CreateNewGeometryListener)getInputListener(MappingComponent.NEW_POLYGON)).setMode(creationMode);
} catch (final Exception ex) {
LOG.warn("Fehler beim Setzen des CreationInteractionMode", ex); // NOI18N
}
}
} catch (final Exception ex) {
LOG.warn("Fehler beim Setzen des InteractionMode", ex); // NOI18N
}
try {
final String createSearchMode = prefs.getAttribute("createSearchMode").getValue();
final Object inputListener = getInputListener(CREATE_SEARCH_POLYGON);
if ((inputListener instanceof CreateSearchGeometryListener) && (createSearchMode != null)) {
final CreateSearchGeometryListener listener = (CreateSearchGeometryListener)inputListener;
listener.setMode(createSearchMode);
}
} catch (final Exception ex) {
LOG.warn("Fehler beim Setzen des CreateSearchMode", ex); // NOI18N
}
try {
final String handleInterMode = prefs.getAttribute("handleInteractionMode").getValue(); // NOI18N
setHandleInteractionMode(handleInterMode);
} catch (final Exception ex) {
LOG.warn("Fehler beim Setzen des HandleInteractionMode", ex); // NOI18N
}
try {
final boolean snapping = prefs.getAttribute("snapping").getBooleanValue(); // NOI18N
LOG.info("snapping=" + snapping); // NOI18N
setSnappingEnabled(snapping);
setVisualizeSnappingEnabled(snapping);
setInGlueIdenticalPointsMode(snapping);
} catch (final Exception ex) {
LOG.warn("Fehler beim setzen von snapping und Konsorten", ex); // NOI18N
}
// aktuelle Position
try {
final Element pos = prefs.getChild("Position"); // NOI18N
final BoundingBox b = new BoundingBox(pos);
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("Position:" + b); // NOI18N
}
}
final PBounds pb = b.getPBounds(getWtst());
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("PositionPb:" + pb); // NOI18N
}
}
if (Double.isNaN(b.getX1())
|| Double.isNaN(b.getX2())
|| Double.isNaN(b.getY1())
|| Double.isNaN(b.getY2())) {
LOG.warn("BUGFINDER:Es war ein Wert in der BoundingBox NaN. Setze auf HOME"); // NOI18N
final String crsCode = ((pos.getAttribute("CRS") != null) ? pos.getAttribute("CRS").getValue() : null);
addToHistory(new PBoundsWithCleverToString(
new PBounds(getMappingModel().getInitialBoundingBox().getPBounds(wtst)),
wtst,
crsCode));
} else {
// set the current crs
final Attribute crsAtt = pos.getAttribute("CRS");
if (crsAtt != null) {
final String currentCrs = crsAtt.getValue();
Crs crsObject = null;
for (final Crs tmp : crsList) {
if (tmp.getCode().equals(currentCrs)) {
crsObject = tmp;
break;
}
}
if (crsObject == null) {
LOG.error("CRS " + currentCrs + " from the position element is not found in the crs list");
}
final ActiveLayerModel alm = (ActiveLayerModel)getMappingModel();
if (alm instanceof ActiveLayerModel) {
alm.setSrs(crsObject);
}
CismapBroker.getInstance().setSrs(crsObject);
wtst = null;
getWtst();
}
this.initialBoundingBox = b;
this.gotoBoundingBox(b, true, true, 0, false);
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.fatal("added to History" + b); // NOI18N
}
}
}
} catch (final Exception ex) {
LOG.warn("Fehler beim lesen der aktuellen Position", ex); // NOI18N
this.gotoBoundingBox(getMappingModel().getInitialBoundingBox(), true, true, 0, false);
}
if (printingSettingsDialog != null) {
printingSettingsDialog.configure(prefs);
}
try {
final Element widgets = prefs.getChild("InternalWidgets"); // NOI18N
if (widgets != null) {
for (final Object widget : widgets.getChildren()) {
final String name = ((Element)widget).getAttribute("name").getValue(); // NOI18N
final boolean visible = ((Element)widget).getAttribute("visible").getBooleanValue(); // NOI18N
this.showInternalWidget(name, visible, 0);
}
}
} catch (final Exception ex) {
LOG.warn("could not enable internal widgets: " + ex, ex); // NOI18N
}
try {
final String minOpacity = prefs.getChildText("minOpacityToStayEnabled");
if (minOpacity != null) {
CismapBroker.getInstance().setMinOpacityToStayEnabled(Float.parseFloat(minOpacity));
}
} catch (NumberFormatException ex) {
LOG.error("The min opacity to stay enabled value is not a number.", ex); // NOI18N
}
try {
final String multiFeaturePopupMenuEnabled = prefs.getChildText("multiFeaturePopupMenuEnabled");
if (multiFeaturePopupMenuEnabled != null) {
CismapBroker.getInstance()
.setMultiFeaturePopupMenuEnabled(Boolean.parseBoolean(multiFeaturePopupMenuEnabled));
}
} catch (final NumberFormatException ex) {
LOG.error("The MultiFeaturePopupMenu stays disabled, value is not valid", ex); // NOI18N
}
}
/**
* Zooms to all features of the mappingcomponents featurecollection. If fixedScale is true, the mappingcomponent
* will only pan to the featurecollection and not zoom.
*
* @param fixedScale true, if zoom is not allowed
*/
public void zoomToFeatureCollection(final boolean fixedScale) {
zoomToAFeatureCollection(featureCollection.getAllFeatures(), true, fixedScale);
}
/**
* Zooms to all features of the mappingcomponents featurecollection.
*/
public void zoomToFeatureCollection() {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("zoomToFeatureCollection"); // NOI18N
}
}
zoomToAFeatureCollection(featureCollection.getAllFeatures(), true, false);
}
/**
* Moves the view to the target Boundingbox.
*
* @param bb target BoundingBox
* @param history true, if the action sould be saved in the history
* @param scaleToFit true, to zoom
* @param animationDuration duration of the animation
*/
public void gotoBoundingBox(final BoundingBox bb,
final boolean history,
final boolean scaleToFit,
final int animationDuration) {
gotoBoundingBox(bb, history, scaleToFit, animationDuration, true);
}
/**
* Moves the view to the target Boundingbox.
*
* @param bb target BoundingBox
* @param history true, if the action sould be saved in the history
* @param scaleToFit true, to zoom
* @param animationDuration duration of the animation
* @param queryServices true, if the services should be refreshed after animation
*/
public void gotoBoundingBox(BoundingBox bb,
final boolean history,
final boolean scaleToFit,
final int animationDuration,
final boolean queryServices) {
if ((bb != null) && bb.isValid()) {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("gotoBoundingBox:" + bb, new CurrentStackTrace()); // NOI18N
}
}
try {
handleLayer.removeAllChildren();
} catch (final Exception e) {
LOG.warn("Fehler bei removeAllCHildren", e); // NOI18N
}
if (bb instanceof XBoundingBox) {
if (!((XBoundingBox)bb).getSrs().equals(mappingModel.getSrs().getCode())) {
try {
final CrsTransformer trans = new CrsTransformer(mappingModel.getSrs().getCode());
bb = trans.transformBoundingBox((XBoundingBox)bb);
} catch (final Exception e) {
LOG.warn("Cannot transform the bounding box", e);
}
}
}
final double x1 = getWtst().getScreenX(bb.getX1());
final double y1 = getWtst().getScreenY(bb.getY1());
final double x2 = getWtst().getScreenX(bb.getX2());
final double y2 = getWtst().getScreenY(bb.getY2());
final double w;
final double h;
final Rectangle2D pos = new Rectangle2D.Double();
pos.setRect(x1, y2, x2 - x1, y1 - y2);
getCamera().animateViewToCenterBounds(pos, (x1 != x2) && (y1 != y2) && scaleToFit, animationDuration);
if (getCamera().getViewTransform().getScaleY() < 0) {
LOG.warn("gotoBoundingBox: Problem :-( mit getViewTransform"); // NOI18N
}
showHandles(true);
final Runnable handle = new Thread("MappingComponent gotoBoundingBox()") {
@Override
public void run() {
while (getAnimating()) {
try {
Thread.currentThread().sleep(10);
} catch (final Exception e) {
LOG.warn("Unterbrechung bei getAnimating()", e); // NOI18N
}
}
if (history) {
if ((x1 == x2) || (y1 == y2) || !scaleToFit) {
setNewViewBounds(getCamera().getViewBounds());
} else {
setNewViewBounds(pos);
}
if (queryServices) {
queryServices();
}
} else if (queryServices) {
queryServicesWithoutHistory();
}
}
};
CismetThreadPool.execute(handle);
} else {
LOG.warn("Seltsam: die BoundingBox war " + ((bb == null) ? "null" : "invalid"), new CurrentStackTrace()); // NOI18N
}
}
/**
* Moves the view to the target Boundingbox without saving the action in the history.
*
* @param bb target BoundingBox
*/
public void gotoBoundingBoxWithoutHistory(final BoundingBox bb) {
gotoBoundingBoxWithoutHistory(bb, animationDuration);
}
/**
* Moves the view to the target Boundingbox without saving the action in the history.
*
* @param bb target BoundingBox
* @param animationDuration the animation duration
*/
public void gotoBoundingBoxWithoutHistory(final BoundingBox bb, final int animationDuration) {
gotoBoundingBox(bb, false, true, animationDuration);
}
/**
* Moves the view to the target Boundingbox and saves the action in the history.
*
* @param bb target BoundingBox
*/
public void gotoBoundingBoxWithHistory(final BoundingBox bb) {
gotoBoundingBox(bb, true, true, animationDuration);
}
/**
* Returns a BoundingBox of the current view in another scale.
*
* @param scaleDenominator specific target scale
*
* @return DOCUMENT ME!
*/
public BoundingBox getBoundingBoxFromScale(final double scaleDenominator) {
return getScaledBoundingBox(scaleDenominator, getCurrentBoundingBoxFromCamera());
}
/**
* Returns the BoundingBox of the delivered BoundingBox in another scale.
*
* @param scaleDenominator specific target scale
* @param bb source BoundingBox
*
* @return DOCUMENT ME!
*/
public BoundingBox getScaledBoundingBox(final double scaleDenominator, final BoundingBox bb) {
final double screenWidthInInch = getWidth() / screenResolution;
final double screenWidthInMeter = screenWidthInInch * 0.0254;
final double screenHeightInInch = getHeight() / screenResolution;
final double screenHeightInMeter = screenHeightInInch * 0.0254;
final double realWorldWidthInMeter = screenWidthInMeter * scaleDenominator;
final double realWorldHeightInMeter = screenHeightInMeter * scaleDenominator;
BoundingBox xbb = bb;
int metricSrid = 0;
if (!mappingModel.getSrs().isMetric()) {
try {
// transform the given bounding box to a metric coordinate system
final int srid = CrsTransformer.extractSridFromCrs(mappingModel.getSrs().getCode());
final Geometry g = CrsTransformer.transformToMetricCrs(bb.getGeometry(srid));
metricSrid = g.getSRID();
xbb = new BoundingBox(g);
} catch (final Exception e) {
LOG.error("Cannot transform the current bounding box.", e);
}
}
final double midX = xbb.getX1() + ((xbb.getX2() - xbb.getX1()) / 2);
final double midY = xbb.getY1() + ((xbb.getY2() - xbb.getY1()) / 2);
BoundingBox scaledBox = new BoundingBox(midX - (realWorldWidthInMeter / 2),
midY
- (realWorldHeightInMeter / 2),
midX
+ (realWorldWidthInMeter / 2),
midY
+ (realWorldHeightInMeter / 2));
if (!mappingModel.getSrs().isMetric()) {
try {
// transform the scaled bounding box to the current coordinate system
final CrsTransformer trans = new CrsTransformer(mappingModel.getSrs().getCode());
scaledBox = trans.transformBoundingBox(scaledBox, CrsTransformer.createCrsFromSrid(metricSrid));
} catch (final Exception e) {
LOG.error("Cannot transform the current bounding box.", e);
}
}
return scaledBox;
}
/**
* Calculate the current scaledenominator.
*
* @return DOCUMENT ME!
*/
public double getScaleDenominator() {
BoundingBox boundingBox = getCurrentBoundingBoxFromCamera();
final double screenWidthInInch = getWidth() / screenResolution;
final double screenWidthInMeter = screenWidthInInch * 0.0254;
final double screenHeightInInch = getHeight() / screenResolution;
final double screenHeightInMeter = screenHeightInInch * 0.0254;
if (!mappingModel.getSrs().isMetric()) {
try {
final Geometry g = CrsTransformer.transformToMetricCrs(boundingBox.getGeometry(
CrsTransformer.extractSridFromCrs(mappingModel.getSrs().getCode())));
boundingBox = new BoundingBox(g);
} catch (final Exception e) {
LOG.error("Cannot transform the current bounding box.", e);
}
}
final double realWorldWidthInMeter = boundingBox.getWidth();
return realWorldWidthInMeter / screenWidthInMeter;
}
/**
* Called when the drag operation has terminated with a drop on the operable part of the drop site for the <code>
* DropTarget</code> registered with this listener.
*
* <p>This method is responsible for undertaking the transfer of the data associated with the gesture. The <code>
* DropTargetDropEvent</code> provides a means to obtain a <code>Transferable</code> object that represents the data
* object(s) to be transfered.</p>
*
* <P>From this method, the <code>DropTargetListener</code> shall accept or reject the drop via the acceptDrop(int
* dropAction) or rejectDrop() methods of the <code>DropTargetDropEvent</code> parameter.</P>
*
* <P>Subsequent to acceptDrop(), but not before, <code>DropTargetDropEvent</code>'s getTransferable() method may be
* invoked, and data transfer may be performed via the returned <code>Transferable</code>'s getTransferData()
* method.</P>
*
* <P>At the completion of a drop, an implementation of this method is required to signal the success/failure of the
* drop by passing an appropriate <code>boolean</code> to the <code>DropTargetDropEvent</code>'s
* dropComplete(boolean success) method.</P>
*
* <P>Note: The data transfer should be completed before the call to the <code>DropTargetDropEvent</code>'s
* dropComplete(boolean success) method. After that, a call to the getTransferData() method of the <code>
* Transferable</code> returned by <code>DropTargetDropEvent.getTransferable()</code> is guaranteed to succeed only
* if the data transfer is local; that is, only if <code>DropTargetDropEvent.isLocalTransfer()</code> returns <code>
* true</code>. Otherwise, the behavior of the call is implementation-dependent.</P>
*
* @param dtde the <code>DropTargetDropEvent</code>
*/
@Override
public void drop(final DropTargetDropEvent dtde) {
if (isDropEnabled(dtde)) {
try {
final MapDnDEvent mde = new MapDnDEvent();
mde.setDte(dtde);
final Point p = dtde.getLocation();
getCamera().getViewTransform().inverseTransform(p, p);
mde.setXPos(getWtst().getWorldX(p.getX()));
mde.setYPos(getWtst().getWorldY(p.getY()));
CismapBroker.getInstance().fireDropOnMap(mde);
} catch (final Exception ex) {
LOG.error("Error in drop", ex); // NOI18N
}
}
}
/**
* DOCUMENT ME!
*
* @param dtde DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private boolean isDropEnabled(final DropTargetDropEvent dtde) {
if (ALKIS_PRINT.equals(getInteractionMode())) {
for (final DataFlavor flavour : dtde.getTransferable().getTransferDataFlavors()) {
// necessary evil, because we have no dependecy to DefaultMetaTreeNode frome here
if (String.valueOf(flavour.getRepresentationClass()).endsWith(".DefaultMetaTreeNode")) {
return false;
}
}
}
return true;
}
/**
* Called while a drag operation is ongoing, when the mouse pointer has exited the operable part of the drop site
* for the <code>DropTarget</code> registered with this listener.
*
* @param dte the <code>DropTargetEvent</code>
*/
@Override
public void dragExit(final DropTargetEvent dte) {
}
/**
* Called if the user has modified the current drop gesture.
*
* @param dtde the <code>DropTargetDragEvent</code>
*/
@Override
public void dropActionChanged(final DropTargetDragEvent dtde) {
}
/**
* Called when a drag operation is ongoing, while the mouse pointer is still over the operable part of the dro9p
* site for the <code>DropTarget</code> registered with this listener.
*
* @param dtde the <code>DropTargetDragEvent</code>
*/
@Override
public void dragOver(final DropTargetDragEvent dtde) {
try {
final MapDnDEvent mde = new MapDnDEvent();
mde.setDte(dtde);
// TODO: this seems to be buggy!
final Point p = dtde.getLocation();
getCamera().getViewTransform().inverseTransform(p, p);
mde.setXPos(getWtst().getWorldX(p.getX()));
mde.setYPos(getWtst().getWorldY(p.getY()));
CismapBroker.getInstance().fireDragOverMap(mde);
} catch (final Exception ex) {
LOG.error("Error in dragOver", ex); // NOI18N
}
}
/**
* Called while a drag operation is ongoing, when the mouse pointer enters the operable part of the drop site for
* the <code>DropTarget</code> registered with this listener.
*
* @param dtde the <code>DropTargetDragEvent</code>
*/
@Override
public void dragEnter(final DropTargetDragEvent dtde) {
}
/**
* Returns the PfeatureHashmap which assigns a Feature to a PFeature.
*
* @return DOCUMENT ME!
*/
public ConcurrentHashMap<Feature, PFeature> getPFeatureHM() {
return pFeatureHM;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isFixedMapExtent() {
return fixedMapExtent;
}
/**
* DOCUMENT ME!
*
* @param fixedMapExtent DOCUMENT ME!
*/
public void setFixedMapExtent(final boolean fixedMapExtent) {
this.fixedMapExtent = fixedMapExtent;
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(
StatusEvent.MAP_EXTEND_FIXED,
this.fixedMapExtent));
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isFixedMapScale() {
return fixedMapScale;
}
/**
* DOCUMENT ME!
*
* @param fixedMapScale DOCUMENT ME!
*/
public void setFixedMapScale(final boolean fixedMapScale) {
this.fixedMapScale = fixedMapScale;
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(
StatusEvent.MAP_SCALE_FIXED,
this.fixedMapScale));
}
}
/**
* DOCUMENT ME!
*
* @param one DOCUMENT ME!
*
* @deprecated DOCUMENT ME!
*/
public void selectPFeatureManually(final PFeature one) {
if (one != null) {
featureCollection.select(one.getFeature());
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @deprecated DOCUMENT ME!
*/
public PFeature getSelectedNode() {
// gehe mal davon aus dass das nur aufgerufen wird wenn sowieso nur ein node selected ist
// deshalb gebe ich mal nur das erste zur�ck
if (featureCollection.getSelectedFeatures().size() > 0) {
final Feature selF = (Feature)featureCollection.getSelectedFeatures().toArray()[0];
if (selF == null) {
return null;
}
return pFeatureHM.get(selF);
} else {
return null;
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isInfoNodesVisible() {
return infoNodesVisible;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public PrintingSettingsWidget getPrintingSettingsDialog() {
return printingSettingsDialog;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isInGlueIdenticalPointsMode() {
return inGlueIdenticalPointsMode;
}
/**
* DOCUMENT ME!
*
* @param inGlueIdenticalPointsMode DOCUMENT ME!
*/
public void setInGlueIdenticalPointsMode(final boolean inGlueIdenticalPointsMode) {
this.inGlueIdenticalPointsMode = inGlueIdenticalPointsMode;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public PLayer getHighlightingLayer() {
return highlightingLayer;
}
/**
* DOCUMENT ME!
*
* @param anno DOCUMENT ME!
*/
public void setPointerAnnotation(final PNode anno) {
((SimpleMoveListener)getInputListener(MOTION)).setPointerAnnotation(anno);
}
/**
* DOCUMENT ME!
*
* @param visib DOCUMENT ME!
*/
public void setPointerAnnotationVisibility(final boolean visib) {
if (getInputListener(MOTION) != null) {
((SimpleMoveListener)getInputListener(MOTION)).setAnnotationNodeVisible(visib);
}
}
/**
* Returns a boolean whether the annotationnode is visible or not. Returns false if the interactionmode doesn't
* equal MOTION.
*
* @return DOCUMENT ME!
*/
public boolean isPointerAnnotationVisible() {
if (getInputListener(MOTION) != null) {
return ((SimpleMoveListener)getInputListener(MOTION)).isAnnotationNodeVisible();
} else {
return false;
}
}
/**
* Returns a vector with different scales.
*
* @return DOCUMENT ME!
*/
public List<Scale> getScales() {
return scales;
}
/**
* Returns a list with different crs.
*
* @return DOCUMENT ME!
*/
public List<Crs> getCrsList() {
return crsList;
}
/**
* DOCUMENT ME!
*
* @return a transformer with the default crs as destination crs. The default crs is the first crs in the
* configuration file that has set the selected attribut on true. This crs is possiby not metric.
*/
public CrsTransformer getMetricTransformer() {
return transformer;
}
/**
* Locks the MappingComponent.
*/
public void lock() {
locked = true;
}
/**
* Unlocks the MappingComponent.
*/
public void unlock() {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("unlock"); // NOI18N
}
}
locked = false;
// if (DEBUG) {
// if (LOG.isDebugEnabled()) {
// LOG.debug("currentBoundingBox:" + currentBoundingBox); // NOI18N
// }
// }
gotoBoundingBoxWithHistory(getInitialBoundingBox());
}
/**
* Unlocks the MappingComponent.
*/
public void unlockWithoutReload() {
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("unlock"); // NOI18N
}
}
locked = false;
}
/**
* Returns whether the MappingComponent is locked or not.
*
* @return DOCUMENT ME!
*/
public boolean isLocked() {
return locked;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isMainMappingComponent() {
return mainMappingComponent;
}
/**
* Returns the MementoInterface for redo-actions.
*
* @return DOCUMENT ME!
*/
public MementoInterface getMemRedo() {
return memRedo;
}
/**
* Returns the MementoInterface for undo-actions.
*
* @return DOCUMENT ME!
*/
public MementoInterface getMemUndo() {
return memUndo;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Map<String, PBasicInputEventHandler> getInputEventListener() {
return inputEventListener;
}
/**
* DOCUMENT ME!
*
* @param inputEventListener DOCUMENT ME!
*/
public void setInputEventListener(final HashMap<String, PBasicInputEventHandler> inputEventListener) {
this.inputEventListener.clear();
this.inputEventListener.putAll(inputEventListener);
}
/**
* DOCUMENT ME!
*
* @param l DOCUMENT ME!
*/
public void addGetFeatureInfoListener(final GetFeatureInfoListener l) {
((GetFeatureInfoMultiGeomListener)inputEventListener.get(FEATURE_INFO_MULTI_GEOM)).addGetFeatureInfoListener(l);
}
/**
* DOCUMENT ME!
*
* @param l DOCUMENT ME!
*/
public void removeGetFeatureInfoListener(final GetFeatureInfoListener l) {
((GetFeatureInfoMultiGeomListener)inputEventListener.get(FEATURE_INFO_MULTI_GEOM)).removeGetFeatureInfoListener(
l);
}
/**
* DOCUMENT ME!
*
* @param event DOCUMENT ME!
*/
@Override
public synchronized void crsChanged(final CrsChangedEvent event) {
if ((event.getFormerCrs() != null) && (fixedBoundingBox == null) && !resetCrs) {
if (locked) {
return;
}
if (crsChangedWaitingDialog == null) {
crsChangedWaitingDialog = new WaitDialog(StaticSwingTools.getParentFrame(MappingComponent.this),
false,
NbBundle.getMessage(
MappingComponent.class,
"MappingComponent.crsChanged(CrsChangedEvent).wait"),
null);
}
final Runnable r = new Thread("MappingComponent crsChanged()") {
@Override
public void run() {
final BoundingBox formerBBox = getCurrentBoundingBoxFromCamera();
if (formerBBox instanceof XBoundingBox) {
((XBoundingBox)formerBBox).setSrs(event.getFormerCrs().getCode());
}
try {
StaticSwingTools.showDialog(crsChangedWaitingDialog);
// the wtst object should not be null, so the getWtst method will be invoked
final WorldToScreenTransform oldWtst = getWtst();
final BoundingBox bbox = getCurrentBoundingBoxFromCamera(); // getCurrentBoundingBox();
final CrsTransformer crsTransformer = new CrsTransformer(event.getCurrentCrs().getCode());
final BoundingBox newBbox = crsTransformer.transformBoundingBox(
bbox,
event.getFormerCrs().getCode());
if (!newBbox.isValid()) {
throw new Exception("Transformation failed");
}
if (getMappingModel() instanceof ActiveLayerModel) {
final ActiveLayerModel alm = (ActiveLayerModel)getMappingModel();
alm.setSrs(event.getCurrentCrs());
}
wtst = null;
getWtst();
gotoBoundingBoxWithoutHistory(newBbox, 0);
final ArrayList<Feature> list = new ArrayList<Feature>(featureCollection.getAllFeatures());
// remove all PrintTemplateFeatures
for (final Feature f : new ArrayList<Feature>(list)) {
if (f instanceof PrintTemplateFeature) {
featureCollection.unholdFeature(f);
list.remove(f);
}
}
featureCollection.removeAllFeatures();
featureCollection.addFeatures(list);
if (LOG.isDebugEnabled()) {
LOG.debug("debug features added: " + list.size());
}
// refresh all wfs layer
if (getMappingModel() instanceof ActiveLayerModel) {
final ActiveLayerModel alm = (ActiveLayerModel)getMappingModel();
alm.refreshWebFeatureServices();
alm.refreshShapeFileLayer();
}
// transform the highlighting layer
for (int i = 0; i < highlightingLayer.getChildrenCount(); ++i) {
final PNode node = highlightingLayer.getChild(i);
CrsTransformer.transformPNodeToGivenCrs(
node,
event.getFormerCrs().getCode(),
event.getCurrentCrs().getCode(),
oldWtst,
getWtst());
if (node instanceof PSticky) {
rescaleStickyNode((PSticky)node);
}
}
} catch (final Exception e) {
LOG.error(
"Cannot transform the current bounding box to the CRS "
+ event.getCurrentCrs(),
e);
JOptionPane.showMessageDialog(
StaticSwingTools.getParentFrame(MappingComponent.this),
org.openide.util.NbBundle.getMessage(
MappingComponent.class,
"MappingComponent.crsChanged(CrsChangedEvent).JOptionPane.message"),
org.openide.util.NbBundle.getMessage(
MappingComponent.class,
"MappingComponent.crsChanged(CrsChangedEvent).JOptionPane.title"),
JOptionPane.ERROR_MESSAGE);
EventQueue.invokeLater(new Thread("crsReset") {
@Override
public void run() {
resetCrs = true;
final ActiveLayerModel alm = (ActiveLayerModel)getMappingModel();
alm.setSrs(event.getFormerCrs());
CismapBroker.getInstance().setSrs(event.getFormerCrs());
wtst = null;
getWtst();
gotoBoundingBoxWithoutHistory(formerBBox, 0);
}
});
} finally {
if (crsChangedWaitingDialog != null) {
crsChangedWaitingDialog.setVisible(false);
crsChangedWaitingDialog.dispose();
} else {
LOG.error("crsChangedWaitingDialog == null");
}
}
}
};
if (EventQueue.isDispatchThread()) {
r.run();
} else {
EventQueue.invokeLater(r);
}
}
;
{
resetCrs = false;
}
}
/**
* DOCUMENT ME!
*
* @param name DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public JInternalFrame getInternalWidget(final String name) {
if (this.internalWidgets.containsKey(name)) {
return this.internalWidgets.get(name);
} else {
LOG.warn("unknown internal widget '" + name + "'"); // NOI18N
return null;
}
}
/**
* DOCUMENT ME!
*
* @param name DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public int getInternalWidgetPosition(final String name) {
if (this.internalWidgetPositions.containsKey(name)) {
return this.internalWidgetPositions.get(name);
} else {
LOG.warn("unknown position for '" + name + "'"); // NOI18N
return -1;
}
}
/**
* DOCUMENT ME!
*
* @param repaintListener DOCUMENT ME!
*/
public void addRepaintListener(final RepaintListener repaintListener) {
synchronized (repaintListeners) {
repaintListeners.add(repaintListener);
}
}
/**
* DOCUMENT ME!
*
* @param repaintListener DOCUMENT ME!
*/
public void removeRepaintListener(final RepaintListener repaintListener) {
synchronized (repaintListeners) {
repaintListeners.remove(repaintListener);
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
public void fireRepaintStart(final RepaintEvent e) {
synchronized (repaintListeners) {
for (final RepaintListener repaintListener : (ArrayList<RepaintListener>)repaintListeners.clone()) {
repaintListener.repaintStart(e);
}
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
public void fireRepaintComplete(final RepaintEvent e) {
synchronized (repaintListeners) {
for (final RepaintListener repaintListener : (ArrayList<RepaintListener>)repaintListeners.clone()) {
repaintListener.repaintComplete(e);
}
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
public void fireRepaintError(final RepaintEvent e) {
synchronized (repaintListeners) {
for (final RepaintListener repaintListener : (ArrayList<RepaintListener>)repaintListeners.clone()) {
repaintListener.repaintError(e);
}
}
}
/**
* DOCUMENT ME!
*/
private synchronized void increaseRetrievalCompleteInProgressCount() {
retrievalCompleteInProgressCount++;
rescaleStickyNodesEnabled = false;
}
/**
* DOCUMENT ME!
*/
private synchronized void decreaseRetrievalCompleteInProgressCount() {
retrievalCompleteInProgressCount--;
if (retrievalCompleteInProgressCount == 0) {
rescaleStickyNodesEnabled = true;
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public double getFeaturePrintingDpi() {
return featurePrintingDpi;
}
/**
* DOCUMENT ME!
*
* @param featurePrintingDpi DOCUMENT ME!
*/
public void setFeaturePrintingDpi(final double featurePrintingDpi) {
this.featurePrintingDpi = featurePrintingDpi;
}
//~ Inner Classes ----------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private class MappingComponentRasterServiceListener implements RetrievalListener {
//~ Instance fields ----------------------------------------------------
private final transient Logger log = Logger.getLogger(this.getClass());
private final transient ServiceLayer rasterService;
private final XPImage pi;
private int position = -1;
//~ Constructors -------------------------------------------------------
/**
* Creates a new MappingComponentRasterServiceListener object.
*
* @param position DOCUMENT ME!
* @param pn DOCUMENT ME!
* @param rasterService DOCUMENT ME!
*/
public MappingComponentRasterServiceListener(final int position,
final PNode pn,
final ServiceLayer rasterService) {
this.position = position;
this.rasterService = rasterService;
if (pn instanceof XPImage) {
this.pi = (XPImage)pn;
} else {
this.pi = null;
}
}
//~ Methods ------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalStarted(final RetrievalEvent e) {
fireActivityChanged();
fireRepaintStart(new RepaintEvent(e));
if (DEBUG) {
if (this.log.isDebugEnabled()) {
this.log.debug(rasterService + ": TaskCounter:" + taskCounter); // NOI18N
}
}
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_STARTED, rasterService));
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalProgress(final RetrievalEvent e) {
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalError(final RetrievalEvent e) {
this.log.error(rasterService + ": Fehler beim Laden des Bildes! " + e.getErrorType() // NOI18N
+ " Errors: " // NOI18N
+ e.getErrors() + " Cause: " + e.getRetrievedObject()); // NOI18N
fireActivityChanged();
fireRepaintError(new RepaintEvent(e));
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug(rasterService + ": TaskCounter:" + taskCounter); // NOI18N
}
}
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_ERROR, rasterService));
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalComplete(final RetrievalEvent e) {
final Point2D localOrigin = getCamera().getViewBounds().getOrigin();
final double localScale = getCamera().getViewScale();
final PBounds localBounds = getCamera().getViewBounds();
final Object o = e.getRetrievedObject();
if (DEBUG) {
if (this.log.isDebugEnabled()) {
this.log.debug(rasterService + ": TaskCounter:" + taskCounter); // NOI18N
}
}
final Runnable paintImageOnMap = new Thread("Mappingcompopnent retrievalComplete()") {
@Override
public void run() {
fireActivityChanged();
if ((o instanceof Image) && (e.isHasErrors() == false)) {
// TODO Hier ist noch ein Fehler die Sichtbarkeit muss vom Layer erfragt werden
if (isBackgroundEnabled()) {
final Image i = (Image)o;
if (rasterService.getName().startsWith("prefetching")) { // NOI18N
final double x = localOrigin.getX() - localBounds.getWidth();
final double y = localOrigin.getY() - localBounds.getHeight();
pi.setImage(i, 0);
pi.setScale(3 / localScale);
pi.setOffset(x, y);
} else {
pi.setImage(i, animationDuration * 2);
pi.setScale(1 / localScale);
pi.setOffset(localOrigin);
MappingComponent.this.repaint();
}
}
fireRepaintComplete(new RepaintEvent(e));
} else {
fireRepaintError(new RepaintEvent(e));
}
}
};
if (EventQueue.isDispatchThread()) {
paintImageOnMap.run();
} else {
EventQueue.invokeLater(paintImageOnMap);
}
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_COMPLETED, rasterService));
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalAborted(final RetrievalEvent e) {
this.log.warn(rasterService + ": retrievalAborted: " + e.getRequestIdentifier()); // NOI18N
fireRepaintError(new RepaintEvent(e));
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_ABORTED, rasterService));
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public int getPosition() {
return position;
}
/**
* DOCUMENT ME!
*
* @param position DOCUMENT ME!
*/
public void setPosition(final int position) {
this.position = position;
}
}
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private class DocumentProgressListener implements RetrievalListener {
//~ Instance fields ----------------------------------------------------
private final transient Logger log = Logger.getLogger(this.getClass());
/** Displays the loading progress of Documents, e.g. SHP Files */
private final transient DocumentProgressWidget documentProgressWidget;
private transient long requestId = -1;
//~ Constructors -------------------------------------------------------
/**
* Creates a new DocumentProgressListener object.
*/
public DocumentProgressListener() {
documentProgressWidget = new DocumentProgressWidget();
documentProgressWidget.setVisible(false);
if (MappingComponent.this.getInternalWidget(MappingComponent.PROGRESSWIDGET) == null) {
MappingComponent.this.addInternalWidget(
MappingComponent.PROGRESSWIDGET,
MappingComponent.POSITION_SOUTHWEST,
documentProgressWidget);
}
}
//~ Methods ------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalStarted(final RetrievalEvent e) {
if (!e.isInitialisationEvent()) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalStarted aborted, no initialisation event"); // NOI18N
return;
}
if (this.requestId != -1) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalStarted: another initialisation thread is still running: " + requestId); // NOI18N
}
this.requestId = e.getRequestIdentifier();
this.documentProgressWidget.setServiceName(e.getRetrievalService().toString());
this.documentProgressWidget.setProgress(-1);
MappingComponent.this.showInternalWidget(MappingComponent.PROGRESSWIDGET, true, 100);
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalProgress(final RetrievalEvent e) {
if (!e.isInitialisationEvent()) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalProgress, no initialisation event"); // NOI18N
return;
}
if (this.requestId != e.getRequestIdentifier()) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalProgress: another initialisation thread is still running: " + requestId); // NOI18N
}
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: initialisation progress: " + e.getPercentageDone()); // NOI18N
}
}
this.documentProgressWidget.setProgress(e.getPercentageDone());
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalComplete(final RetrievalEvent e) {
if (!e.isInitialisationEvent()) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalComplete, no initialisation event"); // NOI18N
return;
}
if (this.requestId != e.getRequestIdentifier()) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalComplete: another initialisation thread is still running: " + requestId); // NOI18N
}
e.getRetrievalService().removeRetrievalListener(this);
this.requestId = -1;
this.documentProgressWidget.setProgress(100);
MappingComponent.this.showInternalWidget(MappingComponent.PROGRESSWIDGET, false, 200);
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalAborted(final RetrievalEvent e) {
if (!e.isInitialisationEvent()) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalAborted aborted, no initialisation event"); // NOI18N
return;
}
if (this.requestId != e.getRequestIdentifier()) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalAborted: another initialisation thread is still running: " + requestId); // NOI18N
}
this.requestId = -1;
this.documentProgressWidget.setProgress(0);
MappingComponent.this.showInternalWidget(MappingComponent.PROGRESSWIDGET, false, 25);
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalError(final RetrievalEvent e) {
if (!e.isInitialisationEvent()) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalError aborted, no initialisation event"); // NOI18N
return;
}
if (this.requestId != e.getRequestIdentifier()) {
log.warn(e.getRetrievalService() + "[" + e.getRequestIdentifier()
+ "]: retrievalError: another initialisation thread is still running: " + requestId); // NOI18N
}
this.requestId = -1;
e.getRetrievalService().removeRetrievalListener(this);
this.documentProgressWidget.setProgress(0);
MappingComponent.this.showInternalWidget(MappingComponent.PROGRESSWIDGET, false, 25);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public long getRequestId() {
return this.requestId;
}
}
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private class MappingComponentFeatureServiceListener implements RetrievalListener {
//~ Instance fields ----------------------------------------------------
private final transient Logger log = Logger.getLogger(this.getClass());
private final transient ServiceLayer featureService;
private final transient PLayer parent;
private volatile long requestIdentifier;
private Thread completionThread;
//~ Constructors -------------------------------------------------------
/**
* Creates a new MappingComponentFeatureServiceListener.
*
* @param featureService the featureretrievalservice
* @param parent the featurelayer (PNode) connected with the servicelayer
*/
public MappingComponentFeatureServiceListener(final ServiceLayer featureService, final PLayer parent) {
this.featureService = featureService;
this.parent = parent;
}
//~ Methods ------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalStarted(final RetrievalEvent e) {
if (!e.isInitialisationEvent()) {
requestIdentifier = e.getRequestIdentifier();
}
if (DEBUG) {
if (this.log.isDebugEnabled()) {
this.log.debug(featureService + "[" + e.getRequestIdentifier() + " (" + requestIdentifier
+ ")]: " + (e.isInitialisationEvent() ? "initialisation" : "retrieval") + " started"); // NOI18N
}
}
fireActivityChanged();
fireRepaintStart(new RepaintEvent(e));
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_STARTED, featureService));
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalProgress(final RetrievalEvent e) {
if (DEBUG) {
if (this.log.isDebugEnabled()) {
this.log.debug(featureService + "[" + e.getRequestIdentifier() + " (" + this.requestIdentifier
+ ")]: " + (e.isInitialisationEvent() ? "initialisation" : "retrieval") + " Progress: "
+ e.getPercentageDone() + " (" + ((RetrievalServiceLayer)featureService).getProgress()
+ ")"); // NOI18N
}
}
fireActivityChanged();
// TODO Hier besteht auch die Möglichkeit jedes einzelne Polygon hinzuzufügen. ausprobieren, ob das
// flüssiger ist
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalError(final RetrievalEvent e) {
this.log.error(featureService + "[" + e.getRequestIdentifier() + " (" + this.requestIdentifier + ")]: "
+ (e.isInitialisationEvent() ? "initialisation" : "retrieval") + " error"); // NOI18N
fireActivityChanged();
fireRepaintError(new RepaintEvent(e));
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_ERROR, featureService));
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalComplete(final RetrievalEvent e) {
if (DEBUG) {
if (this.log.isDebugEnabled()) {
this.log.debug(featureService + "[" + e.getRequestIdentifier() + " (" + this.requestIdentifier
+ ")]: " + (e.isInitialisationEvent() ? "initialisation" : "retrieval") + " complete"); // NOI18N
}
}
if (e.isInitialisationEvent()) {
this.log.info(featureService + "[" + e.getRequestIdentifier() + " (" + this.requestIdentifier
+ ")]: initialisation complete"); // NOI18N
fireActivityChanged();
fireRepaintError(new RepaintEvent(e));
return;
}
if ((completionThread != null) && completionThread.isAlive() && !completionThread.isInterrupted()) {
this.log.warn(featureService + "[" + e.getRequestIdentifier() + " (" + this.requestIdentifier
+ ")]: retrievalComplete: old completion thread still running, trying to interrupt thread"); // NOI18N
if (e.getRequestIdentifier() != this.requestIdentifier) {
return;
} else {
completionThread.interrupt();
}
}
if (e.getRequestIdentifier() < requestIdentifier) {
this.log.warn(featureService + "[" + e.getRequestIdentifier() + " (" + requestIdentifier
+ ")]: retrievalComplete: another retrieval process is still running, aborting retrievalComplete"); // NOI18N
// ((RetrievalServiceLayer)featureService).setProgress(-1);
// fireActivityChanged();
// fireRepaintError(new RepaintEvent(e));
return;
}
int initialCapacity = parent.getChildrenReference().size();
if (initialCapacity < 100) {
initialCapacity = 100;
}
final List newFeatures = new ArrayList(initialCapacity);
((RetrievalServiceLayer)featureService).setProgress(-1);
parent.setVisible(isBackgroundEnabled() && featureService.isEnabled() && parent.getVisible());
// clear all old data to delete twins
final List deletionCandidates = new ArrayList(parent.getChildrenReference().size());
// if it's a refresh, add all old features which should be deleted in the
// newly acquired featurecollection
if (!e.isRefreshExisting()) {
deletionCandidates.addAll(parent.getChildrenReference());
}
if (DEBUG) {
if (this.log.isDebugEnabled()) {
this.log.debug(featureService + "[" + e.getRequestIdentifier() + " (" + this.requestIdentifier
+ ")]: deletionCandidates (" + deletionCandidates.size() + ")"); // + deletionCandidates);//NOI18N
}
}
// only start parsing the features if there are no errors and a correct collection
if ((e.isHasErrors() == false) && (e.getRetrievedObject() instanceof Collection)) {
completionThread = new Thread("completition") {
@Override
public void run() {
// this is the collection with the retrieved features
increaseRetrievalCompleteInProgressCount();
final List features = new ArrayList((Collection)e.getRetrievedObject());
final int size = features.size();
int counter = 0;
final Iterator it = features.iterator();
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(featureService + "[" + e.getRequestIdentifier() + " ("
+ requestIdentifier + ")]: Anzahl Features: " + size); // NOI18N
}
}
// Neue Suche
final Feature[] deletionCandidatesFeature = new Feature[deletionCandidates.size()];
final Map<Feature, PFeature> featureMap = new HashMap<Feature, PFeature>(
deletionCandidates.size()
* (101 / 75));
for (int i = 0; i < deletionCandidates.size(); ++i) {
final PFeature pf = (PFeature)deletionCandidates.get(i);
deletionCandidatesFeature[i] = pf.getFeature();
featureMap.put(pf.getFeature(), pf);
}
final PFeatureComparable comp = new PFeatureComparable();
Arrays.sort(deletionCandidatesFeature, comp);
while ((requestIdentifier == e.getRequestIdentifier()) && !isInterrupted()
&& it.hasNext()) {
counter++;
final Object o = it.next();
if (o instanceof Feature) {
final int index = Arrays.binarySearch(deletionCandidatesFeature, (Feature)o, comp);
if (index >= 0) {
final PFeature noCand = featureMap.get(deletionCandidatesFeature[index]);
if (noCand.hasSameGeometry(((Feature)o).getGeometry())) {
noCand.setFeature((Feature)o);
noCand.refreshDesign();
deletionCandidates.remove(noCand);
} else {
final PFeature p = new PFeature((Feature)o,
wtst,
clip_offset_x,
clip_offset_y,
MappingComponent.this);
newFeatures.add(p);
}
} else { // else add the PFeature to the new features
final PFeature p = new PFeature((Feature)o,
wtst,
clip_offset_x,
clip_offset_y,
MappingComponent.this);
newFeatures.add(p);
}
// calculate the advance of the progressbar
// fire event only wheen needed
final int currentProgress = (int)((double)counter / (double)size * 100d);
if ((((RetrievalServiceLayer)featureService).getProgress() != currentProgress)
&& (currentProgress >= 10)
&& ((currentProgress % 10) == 0)) {
((RetrievalServiceLayer)featureService).setProgress(currentProgress);
fireActivityChanged();
}
}
}
decreaseRetrievalCompleteInProgressCount();
if ((requestIdentifier == e.getRequestIdentifier()) && !isInterrupted()) {
// after all features are computed do stuff on the EDT
EventQueue.invokeLater(new Thread("MappingComponent retrievalComplete") {
@Override
public void run() {
try {
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(
featureService
+ "["
+ e.getRequestIdentifier()
+ " ("
+ requestIdentifier
+ ")]: MappingComponentFeaturelistener.retrievalComplete()"); // NOI18N
}
}
if (requestIdentifier != e.getRequestIdentifier()) {
((RetrievalServiceLayer)featureService).setProgress(100);
fireActivityChanged();
return;
}
// if it's a refresh, delete all previous features
if (e.isRefreshExisting()) {
parent.removeAllChildren();
}
for (final Object o : newFeatures) {
parent.addChild((PNode)o);
}
// set the prograssbar to full
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(
featureService
+ "["
+ e.getRequestIdentifier()
+ " ("
+ requestIdentifier
+ ")]: set progress to 100"); // NOI18N
}
}
((RetrievalServiceLayer)featureService).setProgress(100);
fireActivityChanged();
// repaint the featurelayer
parent.repaint();
// remove stickyNode from all deletionCandidates and add
// each to the new deletefeature-collection
for (final Object o : deletionCandidates) {
if (o instanceof PFeature) {
final PNode p = ((PFeature)o).getPrimaryAnnotationNode();
if (p != null) {
if (p instanceof PSticky) {
removeStickyNode((PSticky)p);
}
}
((PFeature)o).releaseResources();
}
}
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(
featureService
+ "["
+ e.getRequestIdentifier()
+ " ("
+ requestIdentifier
+ ")]: parentCount before:"
+ parent.getChildrenCount()); // NOI18N
}
}
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(
featureService
+ "["
+ e.getRequestIdentifier()
+ " ("
+ requestIdentifier
+ ")]: deleteFeatures="
+ deletionCandidates.size()); // + " :" +
// deleteFeatures);//NOI18N
}
}
parent.removeChildren(deletionCandidates);
deletionCandidates.clear();
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(
featureService
+ "["
+ e.getRequestIdentifier()
+ " ("
+ requestIdentifier
+ ")]: parentCount after:"
+ parent.getChildrenCount()); // NOI18N
}
}
if (LOG.isInfoEnabled()) {
LOG.info(
featureService
+ "["
+ e.getRequestIdentifier()
+ " ("
+ requestIdentifier
+ ")]: "
+ parent.getChildrenCount()
+ " features retrieved or updated"); // NOI18N
}
rescaleStickyNodes();
fireRepaintComplete(new RepaintEvent(e));
} catch (final Exception exception) {
log.warn(
featureService
+ "["
+ e.getRequestIdentifier()
+ " ("
+ requestIdentifier
+ ")]: Fehler beim Aufr\u00E4umen",
exception); // NOI18N
fireRepaintError(new RepaintEvent(e));
}
}
});
} else {
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(featureService + "[" + e.getRequestIdentifier() + " ("
+ requestIdentifier
+ ")]: completion thread Interrupted or synchronisation lost"); // NOI18N
}
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
((RetrievalServiceLayer)featureService).setProgress(100);
fireActivityChanged();
fireRepaintError(new RepaintEvent(e));
// fireRepaintComplete(new RepaintEvent(e));
}
});
// if (requestIdentifier == e.getRequestIdentifier()) {
// fireRepaintError(new RepaintEvent(e));
// }
}
}
};
completionThread.setPriority(Thread.NORM_PRIORITY);
if (requestIdentifier == e.getRequestIdentifier()) {
completionThread.start();
} else {
if (DEBUG) {
if (this.log.isDebugEnabled()) {
this.log.debug(featureService + "[" + e.getRequestIdentifier() + " (" + requestIdentifier
+ ")]: completion thread Interrupted or synchronisation lost"); // NOI18N
}
}
fireRepaintError(new RepaintEvent(e));
}
}
fireActivityChanged();
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_COMPLETED, featureService));
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
@Override
public void retrievalAborted(final RetrievalEvent e) {
this.log.warn(featureService + "[" + e.getRequestIdentifier() + " (" + requestIdentifier
+ ")]: aborted, TaskCounter:" + taskCounter); // NOI18N
if (completionThread != null) {
completionThread.interrupt();
}
if (e.getRequestIdentifier() < requestIdentifier) {
if (DEBUG) {
if (this.log.isDebugEnabled()) {
this.log.debug(featureService + "[" + e.getRequestIdentifier() + " (" + requestIdentifier
+ ")]: another retrieval process is still running, setting the retrieval progress to indeterminate"); // NOI18N
}
}
((RetrievalServiceLayer)featureService).setProgress(-1);
} else {
if (DEBUG) {
if (this.log.isDebugEnabled()) {
this.log.debug(featureService + "[" + e.getRequestIdentifier() + " (" + requestIdentifier
+ ")]: this is the last retrieval process, settign the retrieval progress to 0 (aborted)"); // NOI18N
}
}
((RetrievalServiceLayer)featureService).setProgress(0);
}
fireActivityChanged();
if (mainMappingComponent) {
CismapBroker.getInstance()
.fireStatusValueChanged(new StatusEvent(StatusEvent.RETRIEVAL_ABORTED, featureService));
}
}
}
}
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
class ImageSelection implements Transferable {
//~ Instance fields --------------------------------------------------------
private Image image;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new ImageSelection object.
*
* @param image DOCUMENT ME!
*/
public ImageSelection(final Image image) {
this.image = image;
}
//~ Methods ----------------------------------------------------------------
/**
* Returns supported flavors.
*
* @return DOCUMENT ME!
*/
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] { DataFlavor.imageFlavor };
}
/**
* Returns true if flavor is supported.
*
* @param flavor DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
@Override
public boolean isDataFlavorSupported(final DataFlavor flavor) {
return DataFlavor.imageFlavor.equals(flavor);
}
/**
* Returns image.
*
* @param flavor DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws UnsupportedFlavorException DOCUMENT ME!
* @throws IOException DOCUMENT ME!
*/
@Override
public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (!DataFlavor.imageFlavor.equals(flavor)) {
throw new UnsupportedFlavorException(flavor);
}
return image;
}
}