/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ package de.cismet.cismap.commons.gui.piccolo.eventlistener; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.PrecisionModel; import edu.umd.cs.piccolo.event.PInputEvent; import edu.umd.cs.piccolox.event.PNotificationCenter; import org.apache.commons.collections.MultiHashMap; import org.jdesktop.swingx.JXErrorPane; import org.jdesktop.swingx.error.ErrorInfo; import org.openide.util.Lookup; import org.openide.util.NbBundle; import java.awt.Color; import java.awt.Component; import java.awt.PopupMenu; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.text.DecimalFormat; import java.util.*; import java.util.logging.Level; import javax.swing.Action; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JSeparator; import de.cismet.cismap.commons.CrsTransformer; import de.cismet.cismap.commons.WorldToScreenTransform; import de.cismet.cismap.commons.features.AbstractNewFeature; import de.cismet.cismap.commons.features.CommonFeatureAction; import de.cismet.cismap.commons.features.CommonFeaturePreciseAction; import de.cismet.cismap.commons.features.DefaultFeatureCollection; import de.cismet.cismap.commons.features.DoubleClickableFeature; import de.cismet.cismap.commons.features.Feature; import de.cismet.cismap.commons.features.FeatureNameProvider; import de.cismet.cismap.commons.features.FeaturesProvider; import de.cismet.cismap.commons.features.PureNewFeature; import de.cismet.cismap.commons.features.SelectFeature; import de.cismet.cismap.commons.gui.MapPopupAction; import de.cismet.cismap.commons.gui.MappingComponent; import de.cismet.cismap.commons.gui.piccolo.PFeature; import de.cismet.cismap.commons.interaction.CismapBroker; import de.cismet.cismap.commons.tools.PFeatureTools; import de.cismet.tools.gui.ActionsProvider; /** * DOCUMENT ME! * * @author thorsten.hell@cismet.de * @version $Revision$, $Date$ */ public class SelectionListener extends CreateGeometryListener { //~ Static fields/initializers --------------------------------------------- public static final String SELECTION_CHANGED_NOTIFICATION = "SELECTION_CHANGED_NOTIFICATION"; // NOI18N public static final String DOUBLECLICK_POINT_NOTIFICATION = "DOUBLECLICK_POINT_NOTIFICATION"; // NOI18N // Now some property change event types. // We need to synchronize the mode and the last feature between AbstractCreateSelectGeometryListeners. public static final String PROPERTY_LAST_FEATURE = "PROPERTY_LAST_FEATURE"; public static final String PROPERTY_MODE = "PROPERTY_MODE"; //~ Instance fields -------------------------------------------------------- Point doubleclickPoint = null; PFeature sel = null; Collection<PFeature> pfVector = new ArrayList<>(); ArrayList<? extends CommonFeatureAction> allCommonFeatureActions = null; private final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(this.getClass()); private int clickCount = 0; private Map<Feature, PFeature> selectedFeatures = Collections.synchronizedMap(new HashMap<Feature, PFeature>()); private boolean selectMultipleFeatures = false; private boolean featuresFromServicesSelectable = false; private boolean selectionInProgress = false; private boolean featureAdded = false; private List<Feature> lastUnselectedFeatures; private boolean holdGeometries = false; private SelectFeature lastFeature; private SelectFeature selectFeature; private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); //~ Constructors ----------------------------------------------------------- /** * Creates a new SelectionListener object. */ public SelectionListener() { final Lookup.Result<CommonFeatureAction> result = Lookup.getDefault().lookupResult(CommonFeatureAction.class); allCommonFeatureActions = new ArrayList<>(result.allInstances()); Collections.sort(allCommonFeatureActions, new Comparator<CommonFeatureAction>() { @Override public int compare(final CommonFeatureAction o1, final CommonFeatureAction o2) { return Integer.valueOf(o1.getSorter()).compareTo(Integer.valueOf(o2.getSorter())); } }); setGeometryFeatureClass(PureNewFeature.class); setMode(RECTANGLE); } //~ Methods ---------------------------------------------------------------- @Override public void mouseMoved(final PInputEvent pInputEvent) { setMappingComponent(pInputEvent); super.mouseMoved(pInputEvent); } @Override public void mousePressed(final PInputEvent pInputEvent) { setMappingComponent(pInputEvent); super.mousePressed(pInputEvent); } /** * DOCUMENT ME! * * @param pInputEvent DOCUMENT ME! */ private void handleRightClick(final PInputEvent pInputEvent) { if (log.isDebugEnabled()) { log.debug("right mouseclick"); // NOI18N } boolean clickOnSelection = false; final boolean multiFeaturePopupEnabled = CismapBroker.getInstance().isMultiFeaturePopupMenuEnabled(); final PFeature clickedPFeature = (PFeature)PFeatureTools.getFirstValidObjectUnderPointer( pInputEvent, new Class[] { PFeature.class }); // COLLECT ALL PFEATURES UNDER THE POINTER final Collection<PFeature> allClickedPFeatures = (List)PFeatureTools.getAllValidObjectsUnderPointer( pInputEvent, new Class[] { PFeature.class }); // COLLECT ALL SELECTED PFEATURES that are SelectableServiceFeatures final Collection<PFeature> selectedPFeatures = new ArrayList<>(selectedFeatures.size()); for (final Feature selectedFeature : selectedFeatures.keySet()) { final PFeature selectedPFeature = selectedFeatures.get(selectedFeature); if (allClickedPFeatures.contains(selectedPFeature)) { clickOnSelection = true; } selectedPFeatures.add(selectedPFeature); } // COLLECT ALL SELECTED PFEATURES from the DefaultFeatureCollectipon final DefaultFeatureCollection dfc = ((DefaultFeatureCollection)mappingComponent.getFeatureCollection()); for (final Feature selectedFeature : ((LinkedHashSet<Feature>)dfc.getSelectedFeatures())) { final PFeature selectedPFeature = mappingComponent.getPFeatureHM().get(selectedFeature); if (selectedPFeature != null) { if (allClickedPFeatures.contains(selectedPFeature)) { clickOnSelection = true; } selectedPFeatures.add(selectedPFeature); } } final List<PFeature> pFeatures = new ArrayList<>(); // IS ONE OF THE SELECTED PFEATURES UNDER THE POINTER ? if (clickOnSelection) { pFeatures.addAll(selectedPFeatures); } else if (multiFeaturePopupEnabled) { pFeatures.addAll(allClickedPFeatures); } else if (clickedPFeature != null) { pFeatures.add((PFeature)clickedPFeature); } // we build a popup menu from all the registered generic point actions final Point point = createPointFromInput(pInputEvent); final Collection<? extends MapPopupAction> lookupResult = Lookup.getDefault().lookupAll(MapPopupAction.class); final ArrayList<MapPopupAction> allPopupActions = new ArrayList<>(lookupResult); Collections.sort(allPopupActions); //// final MultiHashMap actionProviderMap = new MultiHashMap(); final MultiHashMap commonFeatureActionsMap = new MultiHashMap(); final MultiHashMap popupActionMap = new MultiHashMap(); final MultiHashMap multipleCommonFeatureActionProvider = new MultiHashMap(); for (final PFeature pFeature : pFeatures) { if ((pFeature instanceof ActionsProvider) && (multiFeaturePopupEnabled || pFeature.equals(clickedPFeature))) { final Collection<? extends Action> actions = ((ActionsProvider)pFeature.getFeature()).getActions(); actionProviderMap.putAll(pFeature, actions); } if (allCommonFeatureActions != null) { for (final CommonFeatureAction cfaTemplate : allCommonFeatureActions) { final CommonFeatureAction cfa; try { cfa = (cfaTemplate instanceof FeaturesProvider) ? cfaTemplate : cfaTemplate.getClass().newInstance(); } catch (final Exception ex) { break; } // if ((cfa != null) && (pFeature != null)) { cfa.setSourceFeature(pFeature.getFeature()); // } if (cfa.isActive()) { if (cfa instanceof CommonFeaturePreciseAction) { final Point2D pos = pInputEvent.getPosition(); final WorldToScreenTransform wtst = getMappingComponent().getWtst(); final Coordinate coord = new Coordinate(wtst.getSourceX(pos.getX()), wtst.getSourceY(pos.getY())); final Collection<Feature> allFeatures = new ArrayList(); for (final PFeature feature : (Collection<PFeature>)pFeatures) { allFeatures.add(feature.getFeature()); } ((CommonFeaturePreciseAction)cfa).setActionCoordinate(coord); ((CommonFeaturePreciseAction)cfa).setAllSourceFeatures(allFeatures); } if (cfa instanceof FeaturesProvider) { if (((FeaturesProvider)cfa).isResponsibleFor(pFeature.getFeature())) { multipleCommonFeatureActionProvider.put(cfa, pFeature.getFeature()); } } else if (multiFeaturePopupEnabled || pFeature.equals(clickedPFeature)) { commonFeatureActionsMap.put(pFeature, cfa); } } } } for (final MapPopupAction popupAction : allPopupActions) { popupAction.setPoint(point); if (popupAction.isActive(pFeature instanceof PFeature) && (multiFeaturePopupEnabled || pFeature.equals(clickedPFeature))) { final JMenu submenu = popupAction.getSubmenu(); popupActionMap.put(pFeature, (submenu != null) ? submenu : popupAction); } } } final MultiHashMap menuMap = new MultiHashMap(); for (final PFeature pFeature : pFeatures) { final Collection<Action> actionProviders = actionProviderMap.getCollection(pFeature); final Collection<CommonFeatureAction> commonFeatureActions = commonFeatureActionsMap.getCollection( pFeature); final Collection<Object> popupActions = popupActionMap.getCollection(pFeature); if (actionProviders != null) { if (menuMap.getCollection(pFeature) != null) { menuMap.put(pFeature, new JSeparator()); } menuMap.putAll(pFeature, actionProviders); } if (commonFeatureActions != null) { if (menuMap.getCollection(pFeature) != null) { menuMap.put(pFeature, new JSeparator()); } menuMap.putAll(pFeature, commonFeatureActions); } if ((popupActions != null) && (popupActions.size() > 0)) { if (menuMap.getCollection(pFeature) != null) { menuMap.put(pFeature, new JSeparator()); } menuMap.putAll(pFeature, popupActions); } } final JPopupMenu popup = new JPopupMenu("MapPopup"); final Collection<PFeature> menuMapPFeatures = (Set<PFeature>)menuMap.keySet(); if (menuMapPFeatures.size() > 1) { for (final PFeature pFeature : menuMapPFeatures) { final String featureName; if ((pFeature.getFeature() instanceof FeatureNameProvider) && (((FeatureNameProvider)pFeature.getFeature()).getName() != null)) { featureName = ((FeatureNameProvider)pFeature.getFeature()).getName(); } else { featureName = java.util.ResourceBundle.getBundle( "de/cismet/cismap/commons/gui/piccolo/eventlistener/Bundle") .getString("SelectionListener.unknown_featureName"); } final JMenu featurePopup = new JMenu(featureName + " | " + new DecimalFormat("#.##").format( pFeature.getFeature().getGeometry().getArea()) + " m²"); featurePopup.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(final MouseEvent e) { ((DefaultFeatureCollection)mappingComponent.getFeatureCollection()).unselectAll(); ((DefaultFeatureCollection)mappingComponent.getFeatureCollection()).addToSelection( pFeature.getFeature()); } }); for (final Object menuItemComponent : menuMap.getCollection(pFeature)) { addItemToMenu(menuItemComponent, featurePopup); } if (featurePopup.getMenuComponentCount() > 0) { popup.add(featurePopup); } else { final JMenuItem mi = new JMenuItem(featurePopup.getText()); mi.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { ((DefaultFeatureCollection)mappingComponent.getFeatureCollection()).unselectAll(); ((DefaultFeatureCollection)mappingComponent.getFeatureCollection()).addToSelection( pFeature.getFeature()); } }); popup.add(mi); } } } else if (menuMapPFeatures.size() > 0) { final Object menuMapPFeature = menuMapPFeatures.iterator().next(); for (final Object menuItemComponent : menuMap.getCollection(menuMapPFeature)) { addItemToMenu(menuItemComponent, popup); } } if (!multipleCommonFeatureActionProvider.isEmpty() && (popup.getComponentCount() > 0)) { popup.add(new JSeparator()); } for (final FeaturesProvider action : (Collection<FeaturesProvider>)multipleCommonFeatureActionProvider.keySet()) { final Collection<Feature> multipleCommonFeature = multipleCommonFeatureActionProvider.getCollection(action); if (!multipleCommonFeature.isEmpty()) { action.setSourceFeatures(new ArrayList<>(multipleCommonFeature)); addItemToMenu(action, popup); } } if (popup.getComponentCount() > 0) { popup.show( mappingComponent, (int)pInputEvent.getCanvasPosition().getX(), (int)pInputEvent.getCanvasPosition().getY()); } } /** * Selektiere einen PNode. * * @param pInputEvent DOCUMENT ME! */ @Override public void mouseClicked(final PInputEvent pInputEvent) { setMappingComponent(pInputEvent); super.mouseClicked(pInputEvent); if (pInputEvent.isRightMouseButton()) { if (!isInProgress()) { try { handleRightClick(pInputEvent); } catch (RuntimeException e) { log.error("Problem while creating context menu", e); final ErrorInfo errorInfo = new ErrorInfo( NbBundle.getMessage(SelectionListener.class, "SelectionListener.mouseClicked().title"), NbBundle.getMessage(SelectionListener.class, "SelectionListener.mouseClicked().message"), null, null, e, Level.ALL, null); JXErrorPane.showDialog(CismapBroker.getInstance().getMappingComponent(), errorInfo); } } } else if (mode.equals(RECTANGLE) || mode.equals(ELLIPSE)) { selectionInProgress = true; try { if (log.isDebugEnabled()) { log.debug("mouseClicked():" + pInputEvent.getPickedNode()); // NOI18N } clickCount = pInputEvent.getClickCount(); if ((clickCount == 2) && pInputEvent.isLeftMouseButton()) { doubleclickPoint = createPointFromInput(pInputEvent); final PNotificationCenter pn = PNotificationCenter.defaultCenter(); pn.postNotification(SelectionListener.DOUBLECLICK_POINT_NOTIFICATION, this); } if (pInputEvent.getComponent() instanceof MappingComponent) { mappingComponent = (MappingComponent)pInputEvent.getComponent(); } final PFeature clickedPFeature = (PFeature)PFeatureTools.getFirstValidObjectUnderPointer( pInputEvent, new Class[] { PFeature.class }); if (clickedPFeature != null) { sel = clickedPFeature; try { Point2D point = null; if (mappingComponent.isSnappingEnabled()) { final boolean vertexRequired = mappingComponent.isSnappingOnLineEnabled(); point = PFeatureTools.getNearestPointInArea( mappingComponent, pInputEvent.getCanvasPosition(), vertexRequired, true); } if (point == null) { point = pInputEvent.getPosition(); } final AbstractNewFeature.geomTypes geomType = AbstractNewFeature.geomTypes.POINT; final int currentSrid = CrsTransformer.extractSridFromCrs(CismapBroker.getInstance().getSrs() .getCode()); final AbstractNewFeature newFeature = new PureNewFeature(point, mappingComponent.getWtst()); newFeature.setGeometryType(geomType); newFeature.getGeometry().setSRID(currentSrid); final Geometry geom = CrsTransformer.transformToGivenCrs(newFeature.getGeometry(), mappingComponent.getMappingModel().getSrs().getCode()); newFeature.setGeometry(geom); finishingEvent = pInputEvent; finishGeometry(newFeature); } catch (Throwable throwable) { log.error("Error during the creation of the geometry", throwable); // NOI18N } if (clickCount == 2) { final Feature feature = sel.getFeature(); if (feature instanceof DoubleClickableFeature) { if (pInputEvent.isLeftMouseButton()) { ((DoubleClickableFeature)feature).doubleClickPerformed(this); } } } } else { if (mappingComponent.getFeatureCollection() instanceof DefaultFeatureCollection) { ((DefaultFeatureCollection)mappingComponent.getFeatureCollection()).unselectAll(); } unselectAll(); } } finally { selectionInProgress = false; } } } @Override public MappingComponent getMappingComponent() { return mappingComponent; } /** * DOCUMENT ME! * * @param menuItemComponent DOCUMENT ME! * @param menuOrPopup DOCUMENT ME! */ private static void addItemToMenu(final Object menuItemComponent, final Object menuOrPopup) { if (menuOrPopup instanceof JMenu) { final JMenu menu = (JMenu)menuOrPopup; if (menuItemComponent instanceof Action) { menu.add((Action)menuItemComponent); } else if (menuItemComponent instanceof Component) { menu.add((Component)menuItemComponent); } else if (menuItemComponent instanceof JMenuItem) { menu.add((JMenuItem)menuItemComponent); } else if (menuItemComponent instanceof PopupMenu) { menu.add((PopupMenu)menuItemComponent); } else if (menuItemComponent instanceof String) { menu.add((String)menuItemComponent); } } else if (menuOrPopup instanceof JPopupMenu) { final JPopupMenu popup = (JPopupMenu)menuOrPopup; if (menuItemComponent instanceof Action) { popup.add((Action)menuItemComponent); } else if (menuItemComponent instanceof Component) { popup.add((Component)menuItemComponent); } else if (menuItemComponent instanceof JMenuItem) { popup.add((JMenuItem)menuItemComponent); } else if (menuItemComponent instanceof PopupMenu) { popup.add((PopupMenu)menuItemComponent); } else if (menuItemComponent instanceof String) { popup.add((String)menuItemComponent); } } } /** * unselect all currently selected features. If featuresFromServicesSelectable = false, this method does nothing */ private void unselectAll() { final List<Feature> allKeys = new ArrayList(selectedFeatures.keySet()); for (final Feature f : allKeys) { if (featuresFromServicesSelectable || (f instanceof SelectableServiceFeature)) { final PFeature pf = selectedFeatures.remove(f); if (pf != null) { pf.setSelected(false); } } } } /** * changes the selection of the given pfeature If featuresFromServicesSelectable = false, this method does nothing. * * @param f the feature that should be change its selection */ private void changeSelection(final PFeature f) { if (featuresFromServicesSelectable || ((f != null) && (f.getFeature() instanceof SelectableServiceFeature))) { f.setSelected(!isSelected(f)); if (f.isSelected()) { selectedFeatures.put(f.getFeature(), f); } else { selectedFeatures.remove(f.getFeature()); } } } /** * checks, if the given feature is currently selected. * * @param f the feature to check * * @return true, if the given feature is currently selected */ private boolean isSelected(final PFeature f) { return selectedFeatures.get(f.getFeature()) != null; } /** * Adds the given feature to the selected features. The select flag of the pfeature will not be changed from this * method. * * @param pf the feature to add */ public void addSelectedFeature(final PFeature pf) { if (featuresFromServicesSelectable || ((pf != null) && (pf.getFeature() instanceof SelectableServiceFeature))) { selectedFeatures.put(pf.getFeature(), pf); } } /** * Removes the given feature from the selected features. The select flag of the pfeature will not be changed from * this method. * * @param pf the feature to remove */ public void removeSelectedFeature(final PFeature pf) { if (featuresFromServicesSelectable || ((pf != null) && (pf.getFeature() instanceof SelectableServiceFeature))) { selectedFeatures.remove(pf.getFeature()); } } /** * DOCUMENT ME! * * @param featuresFromServicesSelectable DOCUMENT ME! */ public void setFeaturesFromServicesSelectable(final boolean featuresFromServicesSelectable) { this.featuresFromServicesSelectable = featuresFromServicesSelectable; } /** * DOCUMENT ME! * * @param event DOCUMENT ME! * * @return DOCUMENT ME! */ private Point createPointFromInput(final PInputEvent event) { final Point2D pos = event.getPosition(); final WorldToScreenTransform wtst = getMappingComponent().getWtst(); final Coordinate coord = new Coordinate(wtst.getSourceX(pos.getX()), wtst.getSourceY(pos.getY())); final GeometryFactory gf = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING), CrsTransformer.getCurrentSrid()); return gf.createPoint(coord); } @Override public void mouseDragged(final PInputEvent e) { setMappingComponent(e); super.mouseDragged(e); // To change body of generated methods, choose Tools | Templates. clickCount = e.getClickCount(); } /** * Wird gefeuert, wenn die Maustaste nach dem Ziehen des Markiervierecks losgelassen wird. * * @param event das Mouseevent (als PInputEvent) */ @Override public void mouseReleased(final PInputEvent event) { setMappingComponent(event); super.mouseReleased(event); } /** * DOCUMENT ME! * * @param listener DOCUMENT ME! */ public void addPropertyChangeListener(final PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener(listener); } /** * DOCUMENT ME! * * @param listener DOCUMENT ME! */ public void removePropertyChangeListener(final PropertyChangeListener listener) { propertyChangeSupport.removePropertyChangeListener(listener); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public Color getSelectColor() { return getFillingColor(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public float getSelectTransparency() { return getFillingColor().getTransparency(); } @Override protected Color getFillingColor() { return new Color(20, 20, 20, 20); } /** * DOCUMENT ME! */ public void redoLastSelect() { select(lastFeature); } /** * DOCUMENT ME! */ public void showLastFeature() { showFeature(lastFeature); getMappingComponent().getFeatureCollection().holdFeature(lastFeature); } /** * DOCUMENT ME! * * @param feature DOCUMENT ME! */ protected void showFeature(final SelectFeature feature) { if (feature != null) { feature.setEditable(feature.getGeometryType() != AbstractNewFeature.geomTypes.MULTIPOLYGON); getMappingComponent().getFeatureCollection().addFeature(feature); if (isHoldingGeometries()) { getMappingComponent().getFeatureCollection().holdFeature(feature); } } } /** * DOCUMENT ME! * * @param newValue DOCUMENT ME! */ protected void setLastFeature(final SelectFeature newValue) { final SelectFeature oldValue = this.lastFeature; this.lastFeature = newValue; // Notify other AbstractCreateSelectGeometryListeners about the change. propertyChangeSupport.firePropertyChange(PROPERTY_LAST_FEATURE, oldValue, newValue); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public SelectFeature getLastSelectFeature() { return lastFeature; } /** * DOCUMENT ME! * * @param selectFeature DOCUMENT ME! */ public void select(final SelectFeature selectFeature) { if (selectFeature != null) { setSelectFeature(selectFeature); final boolean selectExecuted = performSelect(selectFeature); if (selectExecuted) { setLastFeature(selectFeature); showFeature(selectFeature); cleanup(selectFeature); } } } /** * DOCUMENT ME! * * @param feature DOCUMENT ME! */ protected void cleanup(final SelectFeature feature) { final PFeature pFeature = (PFeature)getMappingComponent().getPFeatureHM().get(feature); if (isHoldingGeometries()) { pFeature.moveToFront(); // funktioniert nicht?! feature.setEditable(true); getMappingComponent().getFeatureCollection().holdFeature(feature); } else { getMappingComponent().getTmpFeatureLayer().addChild(pFeature); // Transparenz animieren pFeature.animateToTransparency(0, 2500); // warten bis Animation zu Ende ist um Feature aus Liste zu entfernen new Thread(new Runnable() { @Override public void run() { while (pFeature.getTransparency() > 0) { try { Thread.sleep(100); } catch (InterruptedException ex) { } } getMappingComponent().getFeatureCollection().removeFeature(feature); } }).start(); } } @Override public void setMode(final String newValue) throws IllegalArgumentException { final String oldValue = getMode(); super.setMode(newValue); propertyChangeSupport.firePropertyChange(PROPERTY_MODE, oldValue, newValue); } /** * DOCUMENT ME! * * @param selectFeature DOCUMENT ME! * * @return DOCUMENT ME! */ protected boolean performSelect(final SelectFeature selectFeature) { final Geometry geom = selectFeature.getGeometry(); mappingComponent.getHandleLayer().removeAllChildren(); if ((geom != null)) { if (log.isDebugEnabled()) { // Hole alle PFeatures die das Markierviereck schneiden // und Hinzuf\u00FCgen dieser PFeatures zur Selektion log.debug("Markiergeometrie = " + geom.toText()); // NOI18N } if (!finishingEvent.isControlDown()) { ((DefaultFeatureCollection)mappingComponent.getFeatureCollection()).unselectAll(); unselectAll(); featureAdded = false; } else { featureAdded = true; } final PFeature[] pfArr; if (geom.getGeometryType().equalsIgnoreCase("point")) { // getAllValidObjectsUnderPointer: Uses the pnodes to check, if a PFeature intersects the given // point if (isSelectMultipleFeatures()) { pfArr = (PFeature[])PFeatureTools.getAllValidObjectsUnderPointer( finishingEvent, new Class[] { PFeature.class }).toArray(new PFeature[0]); } else { final Object o = PFeatureTools.getFirstValidObjectUnderPointer( finishingEvent, new Class[] { PFeature.class }); pfArr = new PFeature[] { (PFeature)o }; } } else { // getPFeaturesInArea: Uses the geometry of the underlying features to check, if a PFeature // intersects the given area. So it is almost impossible to match a point feature. Even if it is // displayed by a big symbol. For this reason, getPFeaturesInArea should only be used, if geom is an // area and not just a point. pfArr = PFeatureTools.getPFeaturesInArea( mappingComponent, geom); } final List<Feature> toBeSelected = new ArrayList<>(); final List<Feature> toBeUnselected = new ArrayList<>(); for (final PFeature pf : pfArr) { if (pf.getFeature().canBeSelected()) { if (mappingComponent.getFeatureCollection() instanceof DefaultFeatureCollection) { if ( !((DefaultFeatureCollection)mappingComponent.getFeatureCollection()).isSelected( pf.getFeature())) { if (log.isDebugEnabled()) { log.debug("Feature markiert: " + pf); // NOI18N } toBeSelected.add(pf.getFeature()); } else { toBeUnselected.add(pf.getFeature()); } changeSelection(pf); } } else { if (log.isDebugEnabled()) { log.debug("Feature cannot be selected"); // NOI18N } if (mappingComponent.getFeatureCollection() instanceof DefaultFeatureCollection) { toBeUnselected.add(pf.getFeature()); } } } // Hier passierts ((DefaultFeatureCollection)mappingComponent.getFeatureCollection()).addToSelection(toBeSelected); lastUnselectedFeatures = toBeUnselected; ((DefaultFeatureCollection)mappingComponent.getFeatureCollection()).unselect(toBeUnselected); pfVector = new ArrayList(((DefaultFeatureCollection)mappingComponent.getFeatureCollection()) .getSelectedFeatures()); postSelectionChanged(); } setLastFeature(selectFeature); return true; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean isHoldingGeometries() { return holdGeometries; } /** * DOCUMENT ME! * * @param newValue DOCUMENT ME! */ public void setHoldGeometries(final boolean newValue) { this.holdGeometries = newValue; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public SelectFeature getSelectFeature() { return selectFeature; } /** * DOCUMENT ME! * * @param selectFeature DOCUMENT ME! */ protected void setSelectFeature(final SelectFeature selectFeature) { this.selectFeature = selectFeature; } @Override protected void finishGeometry(final AbstractNewFeature feature) { super.finishGeometry(feature); selectionInProgress = true; try { final Geometry geom = feature.getGeometry(); performSelect(new SelectFeature(geom, MappingComponent.SELECT)); } finally { selectionInProgress = false; } } /** * DOCUMENT ME! * * @param pInputEvent DOCUMENT ME! */ private void setMappingComponent(final PInputEvent pInputEvent) { if (getMappingComponent() == null) { super.setMappingComponent((MappingComponent)pInputEvent.getComponent()); } } /** * DOCUMENT ME! */ private void postSelectionChanged() { if (log.isDebugEnabled()) { log.debug("postSelectionChanged"); // NOI18N } final PNotificationCenter pn = PNotificationCenter.defaultCenter(); pn.postNotification(SelectionListener.SELECTION_CHANGED_NOTIFICATION, this); } /** * DOCUMENT ME! * * @return all currently selected PFeature object */ public List<PFeature> getAllSelectedPFeatures() { final List<PFeature> featureList = new ArrayList<>(); featureList.addAll(selectedFeatures.values()); return featureList; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public PFeature getAffectedPFeature() { return sel; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public int getClickCount() { return clickCount; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public Point getDoubleclickPoint() { return doubleclickPoint; } /** * DOCUMENT ME! * * @return the selectionInProgress */ public boolean isSelectionInProgress() { return selectionInProgress; } /** * DOCUMENT ME! * * @param selectionInProgress the selectionInProgress to set */ public void setSelectionInProgress(final boolean selectionInProgress) { this.selectionInProgress = selectionInProgress; } /** * DOCUMENT ME! * * @return the selectMultipleFeatures */ public boolean isSelectMultipleFeatures() { return selectMultipleFeatures; } /** * If this is false, a simgle click on a feature selects only the first feature. * * @param selectMultipleFeatures the selectMultipleFeatures to set */ public void setSelectMultipleFeatures(final boolean selectMultipleFeatures) { this.selectMultipleFeatures = selectMultipleFeatures; } /** * DOCUMENT ME! * * @return the featureAdded */ public boolean isFeatureAdded() { return featureAdded; } /** * DOCUMENT ME! * * @param featureAdded the featureAdded to set */ public void setFeatureAdded(final boolean featureAdded) { this.featureAdded = featureAdded; } /** * DOCUMENT ME! * * @return the lastUnselectedFeatures */ public List<Feature> getLastUnselectedFeatures() { return lastUnselectedFeatures; } }