/*
   * (non-Javadoc)
   *
   * @see es.axios.udig.ui.georeferencing.internal.ui.MarkPresenter#draw()
   */
  public void draw() {

    assert this.context != null;

    if (hide) return;

    ViewportGraphics graphics = context.getGraphics();

    graphics.setColor(createColor(getMarkModel().hashCode()));

    if (point != null) {
      final int halfsize = EXTENT_SIZE / 2;

      this.extent =
          new Rectangle(
              (int) (point.getX() - halfsize),
              (int) (point.getY() - halfsize),
              EXTENT_SIZE,
              EXTENT_SIZE);

      graphics.fillOval(extent.x, extent.y, extent.width, extent.height);
      Rectangle2D stringBounds = graphics.getStringBounds(String.valueOf(getMarkModel().getID()));
      graphics.drawString(
          String.valueOf(getMarkModel().getID()),
          (int) point.getX(),
          (int) (point.getY() + stringBounds.getHeight()),
          ViewportGraphics.ALIGN_MIDDLE,
          ViewportGraphics.ALIGN_BOTTOM);
    }
  }
 /**
  * Calculate appropriate square size.
  *
  * @param context
  * @param min
  * @return
  */
 private double size(MapGraphicContext context, Unit<?> unit, int min) {
   // Get scale
   double scale = context.getMap().getViewportModel().getScaleDenominator();
   // 1 km square?
   if (scale < 100000) return 1000.0;
   // 10 km square?
   if (scale < 1000000) return 10000.0;
   // 100 km square?
   if (scale < 10000000) return 100000.0;
   // 1000 km square?
   if (scale < 100000000) return 1000000.0;
   // 10000 km square
   return 100000000.0;
 }
  @Override
  public void draw(MapGraphicContext context) {

    // Initialize
    ILayer graticule = context.getLayer();
    GraticuleStyle style = GraticuleStyle.getStyle(graticule);

    // Ensure CRS?
    if (graticule instanceof Layer) {
      // Initialize CRS?
      if (style.isInitCRS()) {
        // Only initialize once
        style.setInitCRS(false);
        // Apply CRS from context
        GraticuleCRSConfigurator.apply((Layer) graticule, context.getCRS());
      } else if (mismatch(graticule, style)) {
        // Apply CRS from
        GraticuleCRSConfigurator.apply((Layer) graticule, style.getCRS());
      }
    }

    // Sanity checks
    if (MAX_SCALE < context.getMap().getViewportModel().getScaleDenominator()) {
      graticule.setStatus(ILayer.ERROR);
      graticule.setStatusMessage(Messages.GraticuleGraphic_Maximum_Scale + MAX_SCALE);
      return;
    }
    Unit<?> unit = CRSUtilities.getUnit(graticule.getCRS().getCoordinateSystem());
    if (!SI.METER.equals(unit)) {
      graticule.setStatus(ILayer.ERROR);
      graticule.setStatusMessage(Messages.GraticuleGraphic_Illegal_CRS);
      return;
    }
    final IWorkbench workbench = PlatformUI.getWorkbench();
    if (workbench == null) return;

    // Start working on layer
    graticule.setStatus(ILayer.WORKING);
    graticule.setStatusMessage(null);

    // Get display to work on
    final Display display = workbench.getDisplay();

    // Set styles
    Font plain = GraticuleStyle.getFontStyle(context).getFont();
    Font bold = plain.deriveFont(Font.BOLD);

    // Initialize the graphics handle
    ViewportGraphics g = context.getGraphics();

    // Set font size
    g.setFont(bold);

    // Get bounds of viewport
    ReferencedEnvelope bounds = context.getViewportModel().getBounds();

    try {

      // Get square size limited to minimum size of 100 pixels
      double size = size(context, unit, 100);

      // Sanity check
      if (size < 100) return;

      // Convert square size to pixels
      int sx = (int) (size / context.getViewportModel().getPixelSize().x);
      int sy = (int) (size / context.getViewportModel().getPixelSize().y);

      // Make transform from Graticule to map CRS
      MathTransform transform = CRS.findMathTransform(graticule.getCRS(), context.getCRS(), false);

      // Transform bounds into Graticule CRS
      bounds = bounds.transform(graticule.getCRS(), true);

      // Get squares inside bounds
      SimpleFeatureIterator it = squares(bounds, size);

      // Draw one squares at the time (only top and left lines are drawn)
      while (it.hasNext()) {

        // Initialize states
        int i = 0;
        Point current = null;

        // Initialize lines
        List<Line> lines = new ArrayList<Line>(2);
        List<Label> labels = new ArrayList<Label>(2);

        // Get next geometry
        Geometry geom = (Geometry) it.next().getDefaultGeometry();

        // Get coordinates in graticule CRS
        Coordinate[] coords = geom.getCoordinates();

        // Get x-coordinate label from upper left corner
        String tx = getLabel(coords[0].x, size, unit, style);

        // Get y-coordinate label from lower left corner
        String ty = getLabel(coords[2].y, size, unit, style);

        // Insert gap with label?
        boolean vgap = isGap(tx, unit, style);
        boolean hgap = isGap(ty, unit, style);

        // Transform coordinates into Map CRS
        coords = JTS.transform(geom, transform).getCoordinates();

        // Create lines and labels for this square
        for (Coordinate c : coords) {

          // Build paths
          switch (i) {
            case 1:

              // -----------------------
              // Vertical line
              // -----------------------

              // Create line path
              current =
                  vert(
                      display,
                      g,
                      sy,
                      style.getLineWidth(),
                      current,
                      context.worldToPixel(c),
                      hgap,
                      vgap,
                      lines);

              // Add xx label?
              if (hgap) {
                labels.add(new Label(current, tx, vgap ? bold : plain));
                current = context.worldToPixel(c);
              }

              break;
            case 2:

              // -----------------------
              // Horizontal line
              // -----------------------

              // Create line path
              current =
                  horz(
                      display,
                      g,
                      sx,
                      style.getLineWidth(),
                      current,
                      context.worldToPixel(c),
                      vgap,
                      hgap,
                      lines);

              // Add yy label?
              if (vgap) {
                labels.add(new Label(current, ty, hgap ? bold : plain));
                current = context.worldToPixel(c);
              }

              break;

            default:
              current = context.worldToPixel(c);
              break;
          }
          i++;
        }

        // Draw lines
        for (Line line : lines) line.draw(g, style);

        // Draw labels?
        if (style.isShowLabels()) for (Label label : labels) label.draw(g, style);
      }

      // // Get lower left corner coordinates
      // int x = llc.x;
      // int y = llc.y;
      //
      // // Print borders
      // g.setColor(lc);
      // g.setStroke(ViewportGraphics.LINE_SOLID, 5);
      //
      // // Inner rectangle
      // g.drawRect(x + d + l, y + d + l, w - 2 * (d + l), h - 2 * (d + l));
      //
      // // Make white border
      // g.setColor(Color.WHITE);
      //
      // // Left
      // g.drawRect(x, y, d, h);
      // g.fillRect(x, y, d, h);
      //
      // // Bottom
      // g.drawRect(x, y, w, d);
      // g.fillRect(x, y, w, d);
      //
      // // Right
      // g.drawRect(x + w - d, y, d, h);
      // g.fillRect(x + w - d, y, d, h);
      //
      // // Top
      // g.drawRect(x, y + h - d, w, d);
      // g.fillRect(x, y + h - d, w, d);

    } catch (IOException ex) {
      MapGraphicPlugin.log(Messages.GraticuleGraphic_Error, ex);
    } catch (FactoryException ex) {
      MapGraphicPlugin.log(Messages.GraticuleGraphic_Error, ex);
    } catch (MismatchedDimensionException ex) {
      MapGraphicPlugin.log(Messages.GraticuleGraphic_Error, ex);
    } catch (TransformException ex) {
      MapGraphicPlugin.log(Messages.GraticuleGraphic_Error, ex);
    }

    // Finished working on layer
    graticule.setStatus(ILayer.DONE);
  }
  public void draw(MapGraphicContext context) {

    boolean showLabels = true;
    Color gridColor = Color.black;
    Font font = new Font("Times", Font.PLAIN, 8);

    Envelope bounds = context.getViewportModel().getBounds();
    List<Double>[] gridLines = chooseGridLines(bounds);

    ViewportGraphics graphics = context.getGraphics();
    int mapPixelWidth = context.getMapDisplay().getWidth();
    int mapPixelHeight = context.getMapDisplay().getHeight();
    graphics.setColor(gridColor);

    List<Double> xCoords = gridLines[0];
    List<Double> yCoords = gridLines[1];

    // draw vert lines
    for (int i = 0; i < xCoords.size(); i++) {
      double x = xCoords.get(i).doubleValue();

      for (int j = 0; j < yCoords.size() - 1; j++) {

        double y1 = yCoords.get(j).doubleValue();
        Coordinate lastCoord = new Coordinate(x, y1);
        double y2 = yCoords.get(j + 1).doubleValue();
        Coordinate thisCoord = new Coordinate(x, y2);

        Point lastPixel = context.worldToPixel(lastCoord);
        Point thisPixel = context.worldToPixel(thisCoord);

        graphics.drawLine(lastPixel.x, lastPixel.y, thisPixel.x, thisPixel.y);
      }
    }

    // draw horiz lines

    for (int i = 0; i < yCoords.size(); i++) {
      double y = yCoords.get(i).doubleValue();
      for (int j = 0; j < xCoords.size() - 1; j++) {

        double x1 = xCoords.get(j).doubleValue();
        Coordinate lastCoord = new Coordinate(x1, y);
        double x2 = xCoords.get(j + 1).doubleValue();
        Coordinate thisCoord = new Coordinate(x2, y);

        Point lastPixel = context.worldToPixel(lastCoord);
        Point thisPixel = context.worldToPixel(thisCoord);

        graphics.drawLine(lastPixel.x, lastPixel.y, thisPixel.x, thisPixel.y);
      }
    }

    // cover the right side and bottom of map with thin strips
    final int RIGHT_STRIP_WIDTH = (int) (mapPixelWidth * 0.05);
    final int BOTTOM_STRIP_HEIGHT = (int) (mapPixelHeight * 0.05);
    final int GRID_LINE_EXTENSION = (int) (RIGHT_STRIP_WIDTH * 0.1);
    graphics.setColor(Color.white);
    graphics.setBackground(Color.white);

    graphics.clearRect(mapPixelWidth - RIGHT_STRIP_WIDTH, 0, RIGHT_STRIP_WIDTH, mapPixelHeight);
    graphics.clearRect(0, mapPixelHeight - BOTTOM_STRIP_HEIGHT, mapPixelWidth, BOTTOM_STRIP_HEIGHT);

    // outline the map
    graphics.setColor(Color.BLACK);
    graphics.drawRect(
        0, 0, mapPixelWidth - RIGHT_STRIP_WIDTH - 1, mapPixelHeight - BOTTOM_STRIP_HEIGHT - 1);

    // draw labels
    graphics.setFont(font);
    if (showLabels) {
      graphics.setColor(gridColor);
      for (int i = 1; i < yCoords.size() - 1; i++) {
        double y = yCoords.get(i).doubleValue();
        double x = xCoords.get(xCoords.size() - 1).doubleValue();
        Point pixel = context.worldToPixel(new Coordinate(x, y));
        // line is covered by white overlay
        if (pixel.y > mapPixelHeight - BOTTOM_STRIP_HEIGHT) break;
        graphics.drawString(
            (int) (y) + "",
            mapPixelWidth - RIGHT_STRIP_WIDTH + GRID_LINE_EXTENSION,
            pixel.y,
            ViewportGraphics.ALIGN_LEFT,
            ViewportGraphics.ALIGN_MIDDLE);
      }
      for (int i = 1; i < xCoords.size() - 1; i++) {
        double x = xCoords.get(i).doubleValue();
        double y = yCoords.get(yCoords.size() - 1).doubleValue();
        Point pixel = context.worldToPixel(new Coordinate(x, y));
        // line is covered by white overlay
        if (pixel.x > mapPixelWidth - RIGHT_STRIP_WIDTH) break;
        graphics.drawString(
            (int) (x) + "",
            pixel.x,
            mapPixelHeight - BOTTOM_STRIP_HEIGHT + GRID_LINE_EXTENSION,
            ViewportGraphics.ALIGN_MIDDLE,
            ViewportGraphics.ALIGN_TOP);
      }
    } // showlabels
  }
  /**
   * Draws grid similarly to the "world" version, but with some changes: - Center the grid on the
   * screen - label the grid lines in CRS units - outline the grid
   *
   * @param context
   * @param showLabels is true, the bottom and right edges of the map are covered with white strips,
   *     and labels for the grid lines are placed in the white strips.
   */
  private void drawGrid(MapGraphicContext context, boolean showLabels) {

    GridStyle style = getStyle(context.getLayer());
    double[] gridSize = style.getGridSize();

    try {
      MathTransform mt = CRS.findMathTransform(DefaultGeographicCRS.WGS84, context.getCRS(), true);

      if (!mt.isIdentity()) {
        double x = gridSize[0] / 2.0;
        double y = gridSize[1] / 2.0;
        double[] toTransform = new double[] {-x, -y, x, y};
        double[] dest = new double[4];
        mt.transform(toTransform, 0, dest, 0, 2);
        gridSize = new double[] {Math.abs(dest[2] - dest[0]), Math.abs(dest[3] - dest[1])};
      }
    } catch (Exception e) {
      MapGraphicPlugin.log("", e); // $NON-NLS-1$
    }

    Envelope bounds = context.getViewportModel().getBounds();

    Coordinate centerCoord = bounds.centre();
    gridSize = style.getGridSize();
    Coordinate topLeftCenterCoord =
        new Coordinate(centerCoord.x - gridSize[0] / 2, centerCoord.y + gridSize[1] / 2);
    Coordinate topLeftMostCoord = new Coordinate(topLeftCenterCoord);
    while (topLeftMostCoord.x - gridSize[0] > bounds.getMinX()) {
      topLeftMostCoord.x -= gridSize[0];
    }
    while (topLeftMostCoord.y + gridSize[1] < bounds.getMaxY()) {
      topLeftMostCoord.y += gridSize[1];
    }
    Coordinate coord = topLeftMostCoord;

    ViewportGraphics graphics = context.getGraphics();
    int mapPixelWidth = context.getMapDisplay().getWidth();
    int mapPixelHeight = context.getMapDisplay().getHeight();

    // cover the right side and bottom of map with thin strips
    final int RIGHT_STRIP_WIDTH = (int) (mapPixelWidth * 0.05);
    final int BOTTOM_STRIP_HEIGHT = (int) (mapPixelHeight * 0.03);
    final int GRID_LINE_EXTENSION = (int) (RIGHT_STRIP_WIDTH * 0.1);
    graphics.setColor(Color.white);
    graphics.fillRect(mapPixelWidth - RIGHT_STRIP_WIDTH, 0, RIGHT_STRIP_WIDTH, mapPixelHeight);
    graphics.fillRect(0, mapPixelHeight - BOTTOM_STRIP_HEIGHT, mapPixelWidth, BOTTOM_STRIP_HEIGHT);

    // draw grid lines
    graphics.setColor(style.getColor());
    Point pixel = null;
    while (true) {
      pixel = context.worldToPixel(coord);
      coord.x += gridSize[0];
      coord.y -= gridSize[1];
      Point next = context.worldToPixel(coord);
      if (next.x - pixel.x < 2 || next.y - pixel.y < 2) {
        context.getLayer().setStatus(ILayer.WARNING);
        context.getLayer().setStatusMessage(Messages.GridMapGraphic_grids_too_close);
        break;
      }
      if ((pixel.x >= mapPixelWidth && pixel.y >= mapPixelHeight)) break;

      // draw vertical lines and labels
      if (pixel.x < mapPixelWidth)
        graphics.drawLine(
            pixel.x, 0, pixel.x, mapPixelHeight - BOTTOM_STRIP_HEIGHT + GRID_LINE_EXTENSION);
      if (showLabels) {
        graphics.drawString(
            (int) (coord.y) + "",
            pixel.x,
            mapPixelHeight - BOTTOM_STRIP_HEIGHT + GRID_LINE_EXTENSION,
            ViewportGraphics.ALIGN_MIDDLE,
            ViewportGraphics.ALIGN_TOP);
      }

      // draw horizontal lines and labels
      if (pixel.y < mapPixelHeight)
        graphics.drawLine(
            0, pixel.y, mapPixelWidth - RIGHT_STRIP_WIDTH + GRID_LINE_EXTENSION, pixel.y);
      if (showLabels) {
        graphics.drawString(
            (int) (coord.x) + "",
            mapPixelWidth - RIGHT_STRIP_WIDTH + GRID_LINE_EXTENSION,
            pixel.y,
            ViewportGraphics.ALIGN_LEFT,
            ViewportGraphics.ALIGN_MIDDLE);
      }
      pixel = next;
    }

    // outline the map
    graphics.drawRect(
        0, 0, mapPixelWidth - RIGHT_STRIP_WIDTH, mapPixelHeight - BOTTOM_STRIP_HEIGHT);
  }