/**
  * First checks if the user clicked the right mouse button, and if they did then rotate the
  * selected image referencing tool.
  *
  * <p>Otherwise it returns true if the combination of buttons and modifiers are legal with a
  * left-mouse-click.
  *
  * @param e
  * @return
  */
 protected boolean validModifierButtonCombo(MapMouseEvent e) {
   if (e.buttons == MapMouseEvent.BUTTON3) {
     GeoReferenceUtils.rotateToNextTool(MoveMarkersTool.TOOLID);
     return false;
   }
   return e.buttons == MapMouseEvent.BUTTON1 && !(e.modifiersDown());
 }
  @Override
  public void mousePressed(MapMouseEvent e) {

    // valid button = left click.
    if (!(e.button == MapMouseEvent.BUTTON1)) {
      return;
    }

    Point point = e.getPoint();
    broadcastCoordinate(point, InputEvent.MOUSE_DOWN);
  }
  public void mouseReleased(MapMouseEvent e) {
    if (getContext().getMapLayers().size() == 0) return;
    FeatureIterator<SimpleFeature> reader = null;
    try {

      ILayer layer = getContext().getEditManager().getSelectedLayer();
      if (layer == null) layer = getContext().getMapLayers().get(0);

      if (layer == null) throw new Exception("No layers in map"); // $NON-NLS-1$

      Envelope env = getContext().getBoundingBox(e.getPoint(), 6);
      FeatureCollection<SimpleFeatureType, SimpleFeature> results =
          getContext().getFeaturesInBbox(layer, env);

      reader = results.features();

      final boolean found = !reader.hasNext();
      getContext()
          .updateUI(
              new Runnable() {
                public void run() {
                  if (getContext().getActionBars() == null) return;
                  IStatusLineManager bar = getContext().getActionBars().getStatusLineManager();
                  if (bar != null) {
                    if (found) bar.setErrorMessage(Messages.DeleteTool_warning);
                    else bar.setErrorMessage(null);
                  }
                }
              });

      if (found) return;

      SimpleFeature feature = reader.next();

      MapCommand deleteFeatureCommand =
          getContext().getEditFactory().createDeleteFeature(feature, layer);
      getContext().sendASyncCommand(deleteFeatureCommand);

      getContext().getViewportPane().repaint();
    } catch (Exception e1) {
      EditPlugin.log(null, e1);
    } finally {
      try {
        if (reader != null) reader.close();
      } catch (Exception e2) {
        EditPlugin.log(null, e2);
      }
      draw.setValid(false); // get us off the draw stack for context.getViewportPane().repaint();
      getContext().getViewportPane().repaint();
    }
  }
  /**
   * Gets a feature iterator on the results of a BBox query. BBox is used because intersects
   * occasionally throws a Side-conflict error so it is not a good query.
   *
   * <p>However maybe a better way is to try intersects then if that fails do a bbox? For now we do
   * bbox and test it with intersects
   *
   * @return Pair of an option containing the first feature if it exists, and an iterator with the
   *     rest
   */
  private FeatureIterator<SimpleFeature> getFeatureIterator() throws IOException {
    ILayer editLayer = parameters.handler.getEditLayer();
    FeatureStore<SimpleFeatureType, SimpleFeature> store = getResource(editLayer);

    // transforms the bbox to the layer crs
    ReferencedEnvelope bbox = handler.getContext().getBoundingBox(event.getPoint(), SEARCH_SIZE);
    try {
      bbox = bbox.transform(parameters.handler.getEditLayer().getCRS(), true);
    } catch (TransformException e) {
      logTransformationWarning(e);
    } catch (FactoryException e) {
      logTransformationWarning(e);
    }
    // creates a bbox filter using the bbox in the layer crs and grabs the features present in this
    // bbox
    Filter createBBoxFilter = createBBoxFilter(bbox, editLayer, filterType);
    FeatureCollection<SimpleFeatureType, SimpleFeature> collection =
        store.getFeatures(createBBoxFilter);

    FeatureIterator<SimpleFeature> reader =
        new IntersectTestingIterator(bbox, collection.features());

    return reader;
  }
  /**
   * @see
   *     net.refractions.udig.project.ui.tool.AbstractTool#mousePressed(net.refractions.udig.project.render.displayAdapter.MapMouseEvent)
   */
  public void mousePressed(MapMouseEvent e) {
    // validate the mouse click (only left mouse clicks should work for dragging)
    if (!validModifierButtonCombo(e)) {
      return;
    }

    // set the active objects and also force a redraw of
    // the composed map image before panning so that we can
    // remove the placemarker being dragged
    List<ILayer> mapLayers = getContext().getMap().getMapLayers();
    Iterator<ILayer> iterator = mapLayers.iterator();
    while (iterator.hasNext()) {
      ILayer layer = iterator.next();
      GeoReferenceMapGraphic mapGraphic;
      try {
        mapGraphic = layer.getResource(GeoReferenceMapGraphic.class, null);
        if (mapGraphic != null) {
          activeMapGraphic = mapGraphic;
          GlassPane glass = getContext().getViewportPane().getGlass();
          if (glass instanceof GeoReferenceGlassPane) {
            activeGlassPane = (GeoReferenceGlassPane) glass;
          }
          layer.refresh(null); // refresh to ensure the selected graphic disappears
          break;
        }
      } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
      }
    }

    // determine if the user clicked on a placemarker or not. If multiple
    // placemarkers are clicked on, choose the closest one to the click
    draggingPlaceMarker = null;
    if (activeMapGraphic != null) {
      Point point = e.getPoint();
      List<PlaceMarker> imageMarkers = activeMapGraphic.getImageMarkers();
      List<PlaceMarker> basemapMarkers = activeMapGraphic.getBasemapMarkers();
      if (imageMarkers == null || imageMarkers.size() < 1) {
        return;
      }
      double currentdistance = PlaceMarker.DRAWING_SIZE + 1;
      for (PlaceMarker marker : imageMarkers) {
        Point markerPoint = marker.getPoint();
        if (markerPoint != null) {
          double distance = point.distance(markerPoint.x, markerPoint.y);
          if (distance <= PlaceMarker.DRAWING_SIZE && distance < currentdistance) {
            draggingPlaceMarker = marker;
            currentdistance = distance;
          }
        }
      }

      // check basemap markers if we haven't matched one yet
      if (draggingPlaceMarker == null && basemapMarkers != null) {
        for (PlaceMarker marker : basemapMarkers) {
          // compare the map coordinate not the screen point since
          // the screen point could be out of whack if the user
          // panned/zoomed the map
          Coordinate markerCoord = marker.getCoord();
          if (markerCoord != null) {
            Point markerPoint = getContext().worldToPixel(markerCoord);
            if (markerPoint != null) {
              double distance = point.distance(markerPoint.x, markerPoint.y);
              if (distance <= PlaceMarker.DRAWING_SIZE && distance < currentdistance) {
                draggingPlaceMarker = marker;
                currentdistance = distance;
              }
            }
          }
        }
      }
    }

    // did we find a marker?
    if (draggingPlaceMarker == null) {
      return;
    }

    // marker found, set dragging vars
    dragging = true;
    draggingPlaceMarker.setDragging(true);
    mouseStart = e.getPoint();
    if (activeGlassPane != null && draggingPlaceMarker != null) {
      Point point = null;
      if (draggingPlaceMarker.isBasemapMarker() && draggingPlaceMarker.getCoord() != null) {
        point = getContext().worldToPixel(draggingPlaceMarker.getCoord());
      } else {
        point = draggingPlaceMarker.getPoint();
      }
      activeGlassPane.startDraggingMarker(draggingPlaceMarker, point.x, point.y);
    }
  }
  @Override
  public void mouseMoved(MapMouseEvent e) {

    Point point = e.getPoint();
    broadcastCoordinate(point, InputEvent.MOUSE_DRAG);
  }