public void setNorthCentered(boolean nc) {
   northCentered = nc;
   if (northCentered != Global.getPref().northCenteredGoto) {
     Global.getPref().northCenteredGoto = northCentered;
     Global.getPref().savePreferences();
   }
   refresh();
 }
 public Exporter() {
   profile = Global.getProfile();
   pref = Global.getPref();
   cacheDB = profile.cacheDB;
   howManyParams = LAT_LON;
   expName = this.getClass().getName();
   // remove package
   expName = expName.substring(expName.indexOf(".") + 1);
 }
  public boolean isVisible(Hashtable overallRoles) {

    if (roles.size() == 0) {
      return false;
    }

    Enumeration keys = roles.keys();

    while (keys.hasMoreElements()) {
      String nextKey = (String) keys.nextElement();

      Boolean thisElement = (Boolean) roles.get(nextKey);
      if (!overallRoles.containsKey(nextKey)) {
        Global.getPref().log("Lookup role " + nextKey + " not possible", null);
        return false;
      }

      Role overallElement = (Role) overallRoles.get(nextKey);
      if (thisElement.booleanValue() != overallElement.getState()) {
        return false;
      }
    }

    return true;
  }
  private void drawWayPointData(Graphics g) {
    String strTemp = MyLocale.getMsg(1512, "Waypoint");
    g.setColor(Color.DarkBlue);
    g.fillRect(0, 0, fm.getTextWidth(strTemp) + 4, lineHeight);
    g.setColor(Color.White);
    g.drawText(strTemp, 2, 0);

    g.setColor(Color.Black);

    int metricSystem = Global.getPref().metricSystem;
    Double tmp = new Double();
    strTemp = "";
    double newDistance = 0;
    int bigUnit = -1;
    int smallUnit = -1;
    double threshold = -1;
    // Allow for different metric systems
    if (metricSystem == Metrics.IMPERIAL) {
      // Why these values? See: http://tinyurl.com/b4nn9m
      bigUnit = Metrics.MILES;
      smallUnit = Metrics.FEET;
      threshold = 0.1;
      newDistance = Metrics.convertUnit(distance, Metrics.KILOMETER, Metrics.MILES);
    } else {
      bigUnit = Metrics.KILOMETER;
      smallUnit = Metrics.METER;
      threshold = 1.0;
      newDistance = distance;
    }
    if (newDistance >= 0.0f) {
      tmp.set(newDistance);
      if (tmp.value >= threshold) {
        strTemp = MyLocale.formatDouble(tmp, "0.000") + " " + Metrics.getUnit(bigUnit);
      } else {
        tmp.set(Metrics.convertUnit(tmp.value, bigUnit, smallUnit));
        strTemp = tmp.toString(3, 0, 0) + " " + Metrics.getUnit(smallUnit);
      }
    } else strTemp = "--- " + Metrics.getUnit(bigUnit);
    g.drawText(strTemp, 2, lineHeight);

    tmp.set(gotoDir);
    if ((tmp.value <= 360) && (tmp.value >= -360))
      strTemp = tmp.toString(0, 0, 0) + " " + MyLocale.getMsg(1502, "deg");
    else strTemp = "---" + " " + MyLocale.getMsg(1502, "deg");
    g.drawText(strTemp, 2, 2 * lineHeight);
  }
  private void drawGpsData(Graphics g) {
    g.setColor(RED);

    String strHeadline = MyLocale.getMsg(1501, "Current");

    Double tmp = new Double();

    String strSpeed = null;
    String unit = null;

    // Allow for different metric systems
    if (Global.getPref().metricSystem == Metrics.IMPERIAL) {
      tmp.set(Metrics.convertUnit(m_speed, Metrics.KILOMETER, Metrics.MILES));
      unit = " mph";
      strSpeed = "- mph";
    } else {
      tmp.set(m_speed);
      unit = " km/h";
      strSpeed = "- km/h";
    }
    if (tmp.value >= 0) {
      if (tmp.value >= 100) {
        strSpeed = MyLocale.formatDouble(tmp, "0") + unit;
      } else {
        strSpeed = MyLocale.formatDouble(tmp, "0.0") + unit;
      }
    }

    tmp.set(moveDir);
    String strMoveDir = "---" + " " + MyLocale.getMsg(1502, "deg");
    if ((tmp.value <= 360) && (tmp.value >= -360))
      strMoveDir = tmp.toString(0, 0, 0) + " " + MyLocale.getMsg(1502, "deg");

    int textWidth = java.lang.Math.max(fm.getTextWidth(strSpeed), fm.getTextWidth(strMoveDir));
    textWidth = java.lang.Math.max(textWidth, fm.getTextWidth(strHeadline));

    int startX = location.width - (textWidth + 4);
    g.fillRect(startX, 0, location.width - startX, lineHeight);

    g.setColor(Color.Black);
    g.drawText(strHeadline, startX + 2, 0);
    g.drawText(strSpeed, startX + 2, lineHeight);
    g.drawText(strMoveDir, startX + 2, 2 * lineHeight);
  }
/** class for displaying the compass rose including goto, sun and moving direction */
class GotoRose extends AniImage {
  float gotoDir = -361;
  float sunDir = -361;
  float moveDir = -361;
  float distance = -1;

  int m_fix = -1;
  int m_sats = -1;
  int m_satsInView = 0;
  double m_hdop = -1;
  float m_speed = -1;

  String m_Luminary = MyLocale.getMsg(6100, "Sun");

  Font mainFont;
  FontMetrics fm;
  int lineHeight;

  int roseRadius;

  boolean northCentered = Global.getPref().northCenteredGoto;

  static final Color RED = new Color(255, 0, 0);
  static final Color YELLOW = new Color(255, 255, 0);
  static final Color GREEN = new Color(0, 255, 0);
  static final Color BLUE = new Color(0, 0, 255);
  static final Color ORANGE = new Color(255, 128, 0);
  static final Color DARKGREEN = new Color(0, 192, 0);
  static final Color CYAN = new Color(0, 255, 255);
  static final Color MAGENTA = new Color(255, 0, 255);

  /**
   * @param gd goto direction
   * @param sd sun direction
   * @param md moving direction
   */
  public GotoRose(String fn) {
    super(fn);
  }

  public GotoRose() {
    super();
  }

  public void setWaypointDirectionDist(float wd, float dist) {
    gotoDir = wd;
    distance = dist;
  }

  public void setSunMoveDirections(float sd, float md, float speed) {
    sunDir = sd;
    moveDir = md;
    m_speed = speed;
    refresh();
  }

  public void setGpsStatus(int fix, int sats, int satsInView, double hdop) {
    m_fix = fix;
    m_sats = sats;
    m_satsInView = satsInView;
    m_hdop = hdop;
    refresh();
  }

  public void setLuminaryName(String Luminary) {
    m_Luminary = Luminary;
    refresh();
  }

  /**
   * draw arrows for the directions of movement and destination waypoint
   *
   * @param ctrl the control to paint on
   * @param moveDir degrees of movement
   * @param destDir degrees of destination waypoint
   */
  public void doDraw(Graphics g, int options) {
    g.setColor(Color.White);
    g.fillRect(0, 0, location.width, location.height);

    int fontSize = location.width / 17;
    mainFont = GetCorrectedFont(g, "Verdana", Font.BOLD, fontSize);
    g.setFont(mainFont);
    fm = g.getFontMetrics(mainFont);
    lineHeight = fm.getHeight() + 1;
    roseRadius = java.lang.Math.min((location.width * 3) / 4, location.height) / 2;

    if (northCentered) {
      // scale(location.width, location.height, null, 0);
      // super.doDraw(g, options);
      drawFullRose(
          g,
          0,
          new Color(255, 255, 255),
          new Color(200, 200, 200),
          new Color(255, 255, 255),
          new Color(200, 200, 200),
          new Color(150, 150, 150),
          new Color(75, 75, 75),
          1.0f,
          true,
          true);
    } else {
      int radius = (int) (roseRadius * 0.75f);

      g.setPen(new Pen(new Color(150, 150, 150), Pen.SOLID, 3));
      g.drawEllipse(
          location.width / 2 - radius, location.height / 2 - radius, 2 * radius, 2 * radius);
    }

    drawArrows(g);
    drawWayPointData(g);
    drawGpsData(g);
    drawLuminaryData(g);
    drawGpsStatus(g);
  }

  private void drawWayPointData(Graphics g) {
    String strTemp = MyLocale.getMsg(1512, "Waypoint");
    g.setColor(Color.DarkBlue);
    g.fillRect(0, 0, fm.getTextWidth(strTemp) + 4, lineHeight);
    g.setColor(Color.White);
    g.drawText(strTemp, 2, 0);

    g.setColor(Color.Black);

    int metricSystem = Global.getPref().metricSystem;
    Double tmp = new Double();
    strTemp = "";
    double newDistance = 0;
    int bigUnit = -1;
    int smallUnit = -1;
    double threshold = -1;
    // Allow for different metric systems
    if (metricSystem == Metrics.IMPERIAL) {
      // Why these values? See: http://tinyurl.com/b4nn9m
      bigUnit = Metrics.MILES;
      smallUnit = Metrics.FEET;
      threshold = 0.1;
      newDistance = Metrics.convertUnit(distance, Metrics.KILOMETER, Metrics.MILES);
    } else {
      bigUnit = Metrics.KILOMETER;
      smallUnit = Metrics.METER;
      threshold = 1.0;
      newDistance = distance;
    }
    if (newDistance >= 0.0f) {
      tmp.set(newDistance);
      if (tmp.value >= threshold) {
        strTemp = MyLocale.formatDouble(tmp, "0.000") + " " + Metrics.getUnit(bigUnit);
      } else {
        tmp.set(Metrics.convertUnit(tmp.value, bigUnit, smallUnit));
        strTemp = tmp.toString(3, 0, 0) + " " + Metrics.getUnit(smallUnit);
      }
    } else strTemp = "--- " + Metrics.getUnit(bigUnit);
    g.drawText(strTemp, 2, lineHeight);

    tmp.set(gotoDir);
    if ((tmp.value <= 360) && (tmp.value >= -360))
      strTemp = tmp.toString(0, 0, 0) + " " + MyLocale.getMsg(1502, "deg");
    else strTemp = "---" + " " + MyLocale.getMsg(1502, "deg");
    g.drawText(strTemp, 2, 2 * lineHeight);
  }

  private void drawGpsData(Graphics g) {
    g.setColor(RED);

    String strHeadline = MyLocale.getMsg(1501, "Current");

    Double tmp = new Double();

    String strSpeed = null;
    String unit = null;

    // Allow for different metric systems
    if (Global.getPref().metricSystem == Metrics.IMPERIAL) {
      tmp.set(Metrics.convertUnit(m_speed, Metrics.KILOMETER, Metrics.MILES));
      unit = " mph";
      strSpeed = "- mph";
    } else {
      tmp.set(m_speed);
      unit = " km/h";
      strSpeed = "- km/h";
    }
    if (tmp.value >= 0) {
      if (tmp.value >= 100) {
        strSpeed = MyLocale.formatDouble(tmp, "0") + unit;
      } else {
        strSpeed = MyLocale.formatDouble(tmp, "0.0") + unit;
      }
    }

    tmp.set(moveDir);
    String strMoveDir = "---" + " " + MyLocale.getMsg(1502, "deg");
    if ((tmp.value <= 360) && (tmp.value >= -360))
      strMoveDir = tmp.toString(0, 0, 0) + " " + MyLocale.getMsg(1502, "deg");

    int textWidth = java.lang.Math.max(fm.getTextWidth(strSpeed), fm.getTextWidth(strMoveDir));
    textWidth = java.lang.Math.max(textWidth, fm.getTextWidth(strHeadline));

    int startX = location.width - (textWidth + 4);
    g.fillRect(startX, 0, location.width - startX, lineHeight);

    g.setColor(Color.Black);
    g.drawText(strHeadline, startX + 2, 0);
    g.drawText(strSpeed, startX + 2, lineHeight);
    g.drawText(strMoveDir, startX + 2, 2 * lineHeight);
  }

  private void drawLuminaryData(Graphics g) {
    g.setColor(YELLOW);

    String strSunDir = "---" + " " + MyLocale.getMsg(1502, "deg");
    if (sunDir < 360 && sunDir > -360) {
      Double tmp = new Double();
      tmp.set(sunDir);
      strSunDir = tmp.toString(0, 0, 0) + " " + MyLocale.getMsg(1502, "deg");
    }

    int textWidth = java.lang.Math.max(fm.getTextWidth(m_Luminary), fm.getTextWidth(strSunDir));
    int startY = location.height - 2 * lineHeight;
    g.fillRect(0, startY, textWidth + 4, location.height - startY);

    g.setColor(Color.Black);
    g.drawText(m_Luminary, 2, startY);
    g.drawText(strSunDir, 2, startY + lineHeight);
  }

  private void drawGpsStatus(Graphics g) {
    if ((m_fix > 0) && (m_sats >= 0)) {
      // Set background to signal quality
      g.setColor(GREEN);
    } else
    // receiving data, but signal ist not good
    if ((m_fix == 0) && (m_sats >= 0)) {
      g.setColor(YELLOW);
    } else {
      g.setColor(RED);
    }

    String strSats = "Sats: -";
    if (m_sats >= 0) {
      strSats = "Sats: " + Convert.toString(m_sats) + "/" + Convert.toString(m_satsInView);
    }
    String strHdop = "HDOP: -";
    if (m_hdop >= 0) strHdop = "HDOP: " + Convert.toString(m_hdop);

    int textWidth = java.lang.Math.max(fm.getTextWidth(strSats), fm.getTextWidth(strHdop));
    int startX = location.width - (textWidth + 4);
    int startY = location.height - 2 * lineHeight;
    g.fillRect(startX, startY, location.width - startX, location.height - startY);

    g.setColor(Color.Black);
    g.drawText(strSats, startX + 2, startY);
    g.drawText(strHdop, startX + 2, startY + lineHeight);
  }

  private void drawArrows(Graphics g) {
    if (g != null) {
      // select moveDirColor according to difference to gotoDir
      Color moveDirColor = RED;

      if (gotoDir < 360 && gotoDir > -360 && moveDir < 360 && moveDir > -360) {
        float diff = java.lang.Math.abs(moveDir - gotoDir);
        while (diff > 360) {
          diff -= 360.0f;
        }
        if (diff > 180.0f) {
          diff = 360.0f - diff;
        }

        if (diff <= 12.25f) {
          moveDirColor = GREEN;
        } else if (diff <= 22.5f) {
          moveDirColor = CYAN;
        } else if (diff <= 45.0f) {
          moveDirColor = ORANGE;
        } else if (diff <= 90.0f) {
          moveDirColor = MAGENTA;
        }
      }

      // draw only valid arrows
      if (northCentered) {
        if (gotoDir < 360 && gotoDir > -360) drawThickArrow(g, gotoDir, Color.DarkBlue, 1.0f);
        if (moveDir < 360 && moveDir > -360) drawThinArrow(g, moveDir, RED, moveDirColor, 1.0f);
        if (sunDir < 360 && sunDir > -360) drawSunArrow(g, sunDir, YELLOW, 0.75f);
      } else {
        // moveDir centered
        if (moveDir < 360 && moveDir > -360) {
          // drawDoubleArrow(g, 360 - moveDir, BLUE, new Color(175,0,0), 1.0f);
          // drawRose(g, 360 - moveDir, new Color(100,100,100), new Color(200,200,200), 1.0f);
          drawFullRose(
              g,
              360 - moveDir,
              new Color(255, 255, 255),
              new Color(200, 200, 200),
              new Color(150, 150, 150),
              new Color(200, 200, 200),
              new Color(200, 200, 200),
              new Color(75, 75, 75),
              1.0f,
              false,
              false);

          int radius = (int) (roseRadius * 0.75f);
          g.setPen(new Pen(RED, Pen.SOLID, 3));
          g.drawLine(
              location.width / 2,
              location.height / 2 - radius,
              location.width / 2,
              location.height / 2 + radius);

          if (gotoDir < 360 && gotoDir > -360)
            drawThinArrow(g, gotoDir - moveDir, Color.DarkBlue, moveDirColor, 1.0f);
          if (sunDir < 360 && sunDir > -360) drawSunArrow(g, sunDir - moveDir, YELLOW, 0.75f);
        }
      }
    }
  }

  private void drawSunArrow(Graphics g, float angle, Color col, float scale) {
    float angleRad = (angle) * (float) java.lang.Math.PI / 180;
    int centerX = location.width / 2, centerY = location.height / 2;
    float arrowLength = roseRadius * scale;
    float halfArrowWidth = arrowLength * 0.08f;
    float circlePos = arrowLength * 0.7f;
    int circleRadius = (int) (arrowLength * 0.1f);

    int circleX = centerX + new Float(circlePos * java.lang.Math.sin(angleRad)).intValue();
    int circleY = centerY - new Float(circlePos * java.lang.Math.cos(angleRad)).intValue();

    int[] pointsX = new int[4];
    int[] pointsY = new int[4];

    pointsX[0] = centerX + new Float(arrowLength * java.lang.Math.sin(angleRad)).intValue();
    pointsY[0] = centerY - new Float(arrowLength * java.lang.Math.cos(angleRad)).intValue();
    pointsX[1] =
        centerX
            + new Float(halfArrowWidth * java.lang.Math.sin(angleRad + java.lang.Math.PI / 2.0))
                .intValue();
    pointsY[1] =
        centerY
            - new Float(halfArrowWidth * java.lang.Math.cos(angleRad + java.lang.Math.PI / 2.0))
                .intValue();
    pointsX[2] =
        centerX
            + new Float(halfArrowWidth * java.lang.Math.sin(angleRad + java.lang.Math.PI))
                .intValue();
    pointsY[2] =
        centerY
            - new Float(halfArrowWidth * java.lang.Math.cos(angleRad + java.lang.Math.PI))
                .intValue();
    pointsX[3] =
        centerX
            + new Float(halfArrowWidth * java.lang.Math.sin(angleRad - java.lang.Math.PI / 2.0))
                .intValue();
    pointsY[3] =
        centerY
            - new Float(halfArrowWidth * java.lang.Math.cos(angleRad - java.lang.Math.PI / 2.0))
                .intValue();

    // g.setPen(new Pen(col,Pen.SOLID,3));
    // g.drawLine(centerX,centerY,pointX,pointY);

    g.setPen(new Pen(Color.Black, Pen.SOLID, 1));
    g.setBrush(new Brush(col, Brush.SOLID));
    g.fillPolygon(pointsX, pointsY, 4);
    g.fillEllipse(
        circleX - circleRadius, circleY - circleRadius, 2 * circleRadius, 2 * circleRadius);
  }

  private void drawThinArrow(Graphics g, float angle, Color col, Color colPoint, float scale) {
    float angleRad = (angle) * (float) java.lang.Math.PI / 180;
    int centerX = location.width / 2, centerY = location.height / 2;
    float arrowLength = roseRadius * scale;
    float halfOpeningAngle = (float) (java.lang.Math.PI * 0.03);
    float sideLineLength = arrowLength * 0.75f;

    int[] pointsX = new int[4];
    int[] pointsY = new int[4];

    pointsX[0] =
        centerX
            + new Float(sideLineLength * java.lang.Math.sin(angleRad - halfOpeningAngle))
                .intValue();
    pointsY[0] =
        centerY
            - new Float(sideLineLength * java.lang.Math.cos(angleRad - halfOpeningAngle))
                .intValue();
    pointsX[1] = centerX + new Float(arrowLength * java.lang.Math.sin(angleRad)).intValue();
    pointsY[1] = centerY - new Float(arrowLength * java.lang.Math.cos(angleRad)).intValue();
    pointsX[2] =
        centerX
            + new Float(sideLineLength * java.lang.Math.sin(angleRad + halfOpeningAngle))
                .intValue();
    pointsY[2] =
        centerY
            - new Float(sideLineLength * java.lang.Math.cos(angleRad + halfOpeningAngle))
                .intValue();
    pointsX[3] = centerX;
    pointsY[3] = centerY;

    g.setPen(new Pen(Color.Black, Pen.SOLID, 1));
    g.setBrush(new Brush(col, Brush.SOLID));
    g.fillPolygon(pointsX, pointsY, 4);
    if (colPoint != null) {
      g.setBrush(new Brush(colPoint, Brush.SOLID));
      g.fillPolygon(pointsX, pointsY, 3);
    }
  }

  private void drawFullRose(
      Graphics g,
      float angle,
      Color colLeft,
      Color colRight,
      Color colNorthLeft,
      Color colNorthRight,
      Color colBorder,
      Color colText,
      float scale,
      boolean bDrawText,
      boolean bDrawEightArrows) {
    float subScale1 = 1.0f;
    float subScale2 = 0.9f;
    float innerScale = 0.15f;
    if (bDrawEightArrows) {
      innerScale = 0.12f;
      drawRosePart(
          g,
          45 + angle,
          colLeft,
          colRight,
          colBorder,
          colText,
          scale * subScale2,
          innerScale,
          "NE",
          bDrawText);
      drawRosePart(
          g,
          135 + angle,
          colLeft,
          colRight,
          colBorder,
          colText,
          scale * subScale2,
          innerScale,
          "SE",
          bDrawText);
      drawRosePart(
          g,
          225 + angle,
          colLeft,
          colRight,
          colBorder,
          colText,
          scale * subScale2,
          innerScale,
          "SW",
          bDrawText);
      drawRosePart(
          g,
          315 + angle,
          colLeft,
          colRight,
          colBorder,
          colText,
          scale * subScale2,
          innerScale,
          "NW",
          bDrawText);
    }

    drawRosePart(
        g,
        0 + angle,
        colNorthLeft,
        colNorthRight,
        colBorder,
        colText,
        scale * subScale1,
        innerScale,
        "N",
        bDrawText);
    drawRosePart(
        g,
        90 + angle,
        colLeft,
        colRight,
        colBorder,
        colText,
        scale * subScale1,
        innerScale,
        "E",
        bDrawText);
    drawRosePart(
        g,
        180 + angle,
        colLeft,
        colRight,
        colBorder,
        colText,
        scale * subScale1,
        innerScale,
        "S",
        bDrawText);
    drawRosePart(
        g,
        270 + angle,
        colLeft,
        colRight,
        colBorder,
        colText,
        scale * subScale1,
        innerScale,
        "W",
        bDrawText);
  }

  private void drawRosePart(
      Graphics g,
      float angle,
      Color colLeft,
      Color colRight,
      Color colBorder,
      Color colText,
      float scale,
      float innerScale,
      String strDir,
      boolean bDrawText) {
    float angleRad = angle * (float) java.lang.Math.PI / 180;
    float angleRadText = (angle + 7.5f) * (float) java.lang.Math.PI / 180;
    int centerX = location.width / 2, centerY = location.height / 2;

    float arrowLength = roseRadius * scale;
    float halfArrowWidth = arrowLength * innerScale;

    int[] pointsX = new int[3];
    int[] pointsY = new int[3];

    pointsX[0] = centerX;
    pointsY[0] = centerY;
    pointsX[1] = centerX + new Float(arrowLength * java.lang.Math.sin(angleRad)).intValue();
    pointsY[1] = centerY - new Float(arrowLength * java.lang.Math.cos(angleRad)).intValue();
    pointsX[2] =
        centerX
            + new Float(halfArrowWidth * java.lang.Math.sin(angleRad - java.lang.Math.PI / 4.0))
                .intValue();
    pointsY[2] =
        centerY
            - new Float(halfArrowWidth * java.lang.Math.cos(angleRad - java.lang.Math.PI / 4.0))
                .intValue();

    g.setPen(new Pen(colBorder, Pen.SOLID, 1));
    g.setBrush(new Brush(colLeft, Brush.SOLID));
    g.fillPolygon(pointsX, pointsY, 3);

    pointsX[2] =
        centerX
            + new Float(halfArrowWidth * java.lang.Math.sin(angleRad + java.lang.Math.PI / 4.0))
                .intValue();
    pointsY[2] =
        centerY
            - new Float(halfArrowWidth * java.lang.Math.cos(angleRad + java.lang.Math.PI / 4.0))
                .intValue();

    g.setBrush(new Brush(colRight, Brush.SOLID));
    g.fillPolygon(pointsX, pointsY, 3);

    if (bDrawText) {
      int tempFontSize = new Float(scale * mainFont.getSize()).intValue();
      Font tempFont = new Font(mainFont.getName(), Font.BOLD, tempFontSize);
      g.setFont(tempFont);
      FontMetrics tempFm = g.getFontMetrics(tempFont);
      float stringHeight = tempFm.getHeight();
      float stringWidth = tempFm.getTextWidth(strDir);
      float stringGap =
          (float) java.lang.Math.sqrt(stringHeight * stringHeight + stringWidth * stringWidth);

      float stringPosition = arrowLength - stringGap / 2.0f;
      g.setColor(colText);
      g.drawText(
          strDir,
          centerX
              + new Float(stringPosition * java.lang.Math.sin(angleRadText) - stringWidth / 2.0f)
                  .intValue(),
          centerY
              - new Float(stringPosition * java.lang.Math.cos(angleRadText) + stringHeight / 2.0f)
                  .intValue());

      g.setFont(mainFont);
    }
  }

  private void drawThickArrow(Graphics g, float angle, Color col, float scale) {
    float angleRad = (angle) * (float) java.lang.Math.PI / 180;
    int centerX = location.width / 2, centerY = location.height / 2;
    float arrowLength = roseRadius * scale;
    float halfArrowWidth = arrowLength * 0.1f;

    int[] pointsX = new int[4];
    int[] pointsY = new int[4];

    pointsX[0] = centerX + new Float(arrowLength * java.lang.Math.sin(angleRad)).intValue();
    pointsY[0] = centerY - new Float(arrowLength * java.lang.Math.cos(angleRad)).intValue();
    pointsX[1] =
        centerX
            + new Float(halfArrowWidth * java.lang.Math.sin(angleRad + java.lang.Math.PI / 2.0))
                .intValue();
    pointsY[1] =
        centerY
            - new Float(halfArrowWidth * java.lang.Math.cos(angleRad + java.lang.Math.PI / 2.0))
                .intValue();
    pointsX[2] =
        centerX
            + new Float(halfArrowWidth * java.lang.Math.sin(angleRad + java.lang.Math.PI))
                .intValue();
    pointsY[2] =
        centerY
            - new Float(halfArrowWidth * java.lang.Math.cos(angleRad + java.lang.Math.PI))
                .intValue();
    pointsX[3] =
        centerX
            + new Float(halfArrowWidth * java.lang.Math.sin(angleRad - java.lang.Math.PI / 2.0))
                .intValue();
    pointsY[3] =
        centerY
            - new Float(halfArrowWidth * java.lang.Math.cos(angleRad - java.lang.Math.PI / 2.0))
                .intValue();

    g.setPen(new Pen(Color.Black, Pen.SOLID, 1));
    g.setBrush(new Brush(col, Brush.SOLID));
    g.fillPolygon(pointsX, pointsY, 4);
  }

  public void setNorthCentered(boolean nc) {
    northCentered = nc;
    if (northCentered != Global.getPref().northCenteredGoto) {
      Global.getPref().northCenteredGoto = northCentered;
      Global.getPref().savePreferences();
    }
    refresh();
  }

  public boolean isNorthCentered() {
    return northCentered;
  }

  public static Font GetCorrectedFont(Graphics g, String name, int style, int size) {
    Font newFont = new Font(name, style, size);
    FontMetrics metrics = g.getFontMetrics(newFont);
    int fontHeight = metrics.getHeight();

    float ratio = (float) fontHeight / (float) size;
    if (ratio < 0.9 || ratio > 1.1) {
      size = (int) (size / ratio + 0.5);
      if (size < 5) size = 5;
      newFont = new Font(name, style, size);
    }

    return newFont;
  }
}
  /**
   * Create GotoPanel
   *
   * @param Preferences global preferences
   * @param MainTab reference to MainTable
   * @param DetailsPanel reference to DetailsPanel
   * @param Vector cacheDB
   */
  public GotoPanel(Navigate nav) {
    myNavigation = nav;
    pref = Global.getPref();
    profile = Global.getProfile();
    mainT = Global.mainTab;
    detP = mainT.detP;
    cacheDB = profile.cacheDB;

    // Button
    ButtonP.addNext(
        btnGPS = new mButton(MyLocale.getMsg(1504, "Start")),
        CellConstants.DONTSTRETCH,
        (CellConstants.DONTFILL | CellConstants.WEST));
    ButtonP.addNext(
        btnCenter = new mButton(MyLocale.getMsg(309, "Centre")),
        CellConstants.DONTSTRETCH,
        (CellConstants.DONTFILL | CellConstants.WEST));
    ButtonP.addLast(
        btnSave = new mButton(MyLocale.getMsg(311, "Create Waypoint")),
        CellConstants.DONTSTRETCH,
        (CellConstants.DONTFILL | CellConstants.WEST));
    // ButtonP.addLast(btnMap = new mButton(MyLocale.getMsg(1506,"Map")),CellConstants.DONTSTRETCH,
    // (CellConstants.DONTFILL|CellConstants.WEST));

    // Format selection for coords
    // context menu
    mnuContextFormt = new Menu();
    currFormatSel = 1; // default to d° m.m
    mnuContextFormt.addItem(miCooformat[0] = new MenuItem("d.d°"));
    miCooformat[0].modifiers &= ~MenuItem.Checked;
    mnuContextFormt.addItem(miCooformat[1] = new MenuItem("d°m.m\'"));
    miCooformat[1].modifiers |= MenuItem.Checked; // default
    mnuContextFormt.addItem(miCooformat[2] = new MenuItem("d°m\'s\""));
    miCooformat[2].modifiers &= ~MenuItem.Checked;
    mnuContextFormt.addItems(TransformCoordinates.getProjectedSystemNames());

    // Create context menu for compass rose: select luminary for orientation
    mnuContextRose = new Menu();
    for (int i = 0; i < SkyOrientation.LUMINARY_NAMES.length; i++) {
      mnuContextRose.addItem(miLuminary[i] = new MenuItem(SkyOrientation.getLuminaryName(i)));
      if (i == myNavigation.luminary) miLuminary[i].modifiers |= MenuItem.Checked;
      else miLuminary[i].modifiers &= MenuItem.Checked;
    }

    // Coords
    CoordsP.addNext(
        lblGPS = new mLabel("GPS: "),
        CellConstants.DONTSTRETCH,
        (CellConstants.DONTFILL | CellConstants.WEST));
    lblGPS.backGround = RED;
    lblGPS.setMenu(mnuContextFormt);
    lblGPS.modifyAll(ControlConstants.WantHoldDown, 0);

    lblPosition =
        new mLabel(myNavigation.gpsPos.toString(CoordsScreen.getLocalSystem(currFormatSel)));
    lblPosition.anchor = CellConstants.CENTER;
    lblPosition.setMenu(mnuContextFormt);
    lblPosition.modifyAll(ControlConstants.WantHoldDown, 0);
    CoordsP.addLast(
        lblPosition, CellConstants.HSTRETCH, (CellConstants.HFILL | CellConstants.WEST));

    CoordsP.addNext(
        lblDST = new mLabel(MyLocale.getMsg(1500, "DST:")),
        CellConstants.DONTSTRETCH,
        (CellConstants.DONTFILL | CellConstants.WEST));
    lblDST.backGround = new Color(0, 0, 255);
    lblDST.setMenu(mnuContextFormt);
    lblDST.modifyAll(ControlConstants.WantHoldDown, 0);

    CoordsP.addLast(
        btnGoto = new mButton(getGotoBtnText()),
        CellConstants.HSTRETCH,
        (CellConstants.HFILL | CellConstants.WEST));

    // Rose for bearing
    // compassRose = new GotoRose("rose.png");
    compassRose = new GotoRose();
    icRose = new ImageControl(compassRose);
    icRose.setMenu(mnuContextRose);
    icRose.modifyAll(
        ControlConstants.WantHoldDown,
        0); // this is necessary in order to make PenHold on a PDA work as right click
    roseP.addLast(
        icRose, CellConstants.DONTSTRETCH, (CellConstants.DONTFILL | CellConstants.NORTH));

    mnuContextRose.addItem(new MenuItem("", MenuItem.Separator, null));
    mnuContextRose.addItem(miNorthCentered = new MenuItem(MyLocale.getMsg(1503, "North Centered")));
    if (compassRose.isNorthCentered()) miNorthCentered.modifiers |= MenuItem.Checked;
    else miNorthCentered.modifiers &= MenuItem.Checked;

    // add Panels
    HeadP.addLast(ButtonP, CellConstants.HSTRETCH, CellConstants.DONTFILL | CellConstants.WEST)
        .setTag(SPAN, new Dimension(2, 1));
    HeadP.addLast(CoordsP, CellConstants.HSTRETCH, CellConstants.HFILL | CellConstants.NORTH)
        .setTag(SPAN, new Dimension(2, 1));
    this.addNext(HeadP, CellConstants.HSTRETCH, CellConstants.WEST)
        .setTag(SPAN, new Dimension(2, 1));
    this.addLast(
            btnMap = new mButton(MyLocale.getMsg(1506, "Map") + " "),
            CellConstants.HSTRETCH,
            CellConstants.VFILL | CellConstants.RIGHT)
        .setTag(SPAN, new Dimension(2, 1));
    this.addLast(roseP, CellConstants.DONTSTRETCH, CellConstants.DONTFILL | CellConstants.WEST)
        .setTag(SPAN, new Dimension(2, 1));
    btnMap.backGround = GREEN;
  }
  public static Image createImage(String source, String iconSrc, int alpha) {
    Image image = new Image(source);

    int imageW = image.getWidth();
    int imageH = image.getHeight();
    Image icon = null;
    if (iconSrc != null) {
      icon = new Image(iconSrc);
      int iconW = icon.getWidth();
      int iconH = icon.getHeight();
      if (iconH <= imageH && iconW <= imageW) {
        int offsetx = (imageW - iconW) / 2;
        int offsety = (imageH - iconH) / 2;

        // not so nice solution to have the icon at the left side
        if (offsetx > offsety) {
          offsetx = offsety;
        }

        int[] iconPixels = icon.getPixels(null, 0, 0, 0, iconW, iconH, 0);
        int[] imagePixels = image.getPixels(null, 0, 0, 0, imageW, imageH, 0);

        for (int y = 0; y < imageH; y++) {
          for (int x = 0; x < imageW; x++) {

            if (y >= offsety && x >= offsetx && y < offsety + iconH && x < offsetx + iconW) {

              int iconx = x - offsetx;
              int icony = y - offsety;

              int index = y * imageW + x;
              int iconIndex = icony * iconW + iconx;
              int alphaval = (iconPixels[iconIndex] >> 24) & 0xff;

              if (alphaval > 127) {
                imagePixels[index] = iconPixels[iconIndex];
              }
            }
          }
        }

        image.setPixels(imagePixels, 0, 0, 0, imageW, imageH, 0);

      } else
        Global.getPref()
            .log("icon " + iconSrc + " is bigger than " + source + "! Icon not loaded", null);
    }

    if (alpha >= 0 && alpha < 256) {
      alpha = alpha << 24;

      int[] imageBits = image.getPixels(null, 0, 0, 0, image.getWidth(), image.getHeight(), 0);
      for (int i = 0; i < imageBits.length; i++) {
        if (imageBits[i] != 0) {
          imageBits[i] &= 0xffffff;
          imageBits[i] |= alpha;
        }
      }
      image.setPixels(imageBits, 0, 0, 0, image.getWidth(), image.getHeight(), 0);
      image.enableAlpha();
    }

    return image;
  }
/**
 * class which represents a item which can be displayed on the map
 *
 * @author Hälmchen
 */
public abstract class MovingMapControlItem {

  public static final int DISPLAY_FROM_TOP = 0x10;
  public static final int DISPLAY_FROM_BOTTOM = 0x20;
  public static final int DISPLAY_FROM_RIGHT = 0x40;
  public static final int DISPLAY_FROM_LEFT = 0x80;

  public static final int IS_PLACE_HOLDER = 0x2000;
  public static final int IS_ICON_WITH_COMMAND = 0x4000;
  public static final int IS_ICON_WITH_TEXT = 0x8000;
  public static final int IS_ICON_WITH_FRONTLINE = 0x10000;

  public static final int ICON_TEXT_LEFT = 0x20000;
  public static final int ICON_TEXT_HORIZONTAL_CENTER = 0x40000;
  public static final int ICON_TEXT_RIGHT = 0x80000;

  public static final int ICON_TEXT_TOP = 0x100000;
  public static final int ICON_TEXT_VERTICAL_CENTER = 0x200000;
  public static final int ICON_TEXT_BOTTOM = 0x400000;

  public int xProperties = 0x0;
  protected Preferences pref = Global.getPref();

  private String helpText = null;
  private int xPos;
  private int yPos;
  private Hashtable roles = new Hashtable();
  private String role;

  public static Image createImage(String source, String iconSrc, int alpha) {
    Image image = new Image(source);

    int imageW = image.getWidth();
    int imageH = image.getHeight();
    Image icon = null;
    if (iconSrc != null) {
      icon = new Image(iconSrc);
      int iconW = icon.getWidth();
      int iconH = icon.getHeight();
      if (iconH <= imageH && iconW <= imageW) {
        int offsetx = (imageW - iconW) / 2;
        int offsety = (imageH - iconH) / 2;

        // not so nice solution to have the icon at the left side
        if (offsetx > offsety) {
          offsetx = offsety;
        }

        int[] iconPixels = icon.getPixels(null, 0, 0, 0, iconW, iconH, 0);
        int[] imagePixels = image.getPixels(null, 0, 0, 0, imageW, imageH, 0);

        for (int y = 0; y < imageH; y++) {
          for (int x = 0; x < imageW; x++) {

            if (y >= offsety && x >= offsetx && y < offsety + iconH && x < offsetx + iconW) {

              int iconx = x - offsetx;
              int icony = y - offsety;

              int index = y * imageW + x;
              int iconIndex = icony * iconW + iconx;
              int alphaval = (iconPixels[iconIndex] >> 24) & 0xff;

              if (alphaval > 127) {
                imagePixels[index] = iconPixels[iconIndex];
              }
            }
          }
        }

        image.setPixels(imagePixels, 0, 0, 0, imageW, imageH, 0);

      } else
        Global.getPref()
            .log("icon " + iconSrc + " is bigger than " + source + "! Icon not loaded", null);
    }

    if (alpha >= 0 && alpha < 256) {
      alpha = alpha << 24;

      int[] imageBits = image.getPixels(null, 0, 0, 0, image.getWidth(), image.getHeight(), 0);
      for (int i = 0; i < imageBits.length; i++) {
        if (imageBits[i] != 0) {
          imageBits[i] &= 0xffffff;
          imageBits[i] |= alpha;
        }
      }
      image.setPixels(imageBits, 0, 0, 0, image.getWidth(), image.getHeight(), 0);
      image.enableAlpha();
    }

    return image;
  }

  public abstract int getWidth();

  public abstract int getHeight();

  public abstract AniImage getImage();

  public abstract void setText(String text);

  public int getActionCommand() {
    return -1;
  }

  public String getContent() {
    return null;
  }

  public String getText() {
    return null;
  }

  public String getHelp() {

    return helpText;
  }

  public void setHelpText(String helpText) {
    this.helpText = helpText;
  }

  public void setAdditionalProperty(int prop) {}

  public void setPosition(int xpos, int ypos) {
    this.xPos = xpos;
    this.yPos = ypos;
  }

  public void addXtraProperties(int xProps) {
    xProperties |= xProps;
  }

  public void setVisibilityRole(String visibility) {
    String[] parts = mString.split(visibility, '+');

    for (int i = 0; i < parts.length; i++) {
      String part = parts[i];
      if (part.startsWith("!")) {
        roles.put(part.substring(1), Boolean.FALSE);
      } else {
        roles.put(part, Boolean.TRUE);
      }
    }
  }

  public boolean isVisible(Hashtable overallRoles) {

    if (roles.size() == 0) {
      return false;
    }

    Enumeration keys = roles.keys();

    while (keys.hasMoreElements()) {
      String nextKey = (String) keys.nextElement();

      Boolean thisElement = (Boolean) roles.get(nextKey);
      if (!overallRoles.containsKey(nextKey)) {
        Global.getPref().log("Lookup role " + nextKey + " not possible", null);
        return false;
      }

      Role overallElement = (Role) overallRoles.get(nextKey);
      if (thisElement.booleanValue() != overallElement.getState()) {
        return false;
      }
    }

    return true;
  }

  public int getxPos() {
    return xPos;
  }

  public int getyPos() {
    return yPos;
  }

  public String getRoleToChange() {
    return role;
  }

  public void setRole(String role) {
    this.role = role;
  }
}
Example #10
0
/** Mainform is responsible for building the user interface. Class ID = 5000 */
public class MainForm extends Editor {
  // The next three declares are for the cachelist
  public boolean cacheListVisible = false;
  public CacheList cacheList;
  SplittablePanel split;

  StatusBar statBar = null;
  Preferences pref = Global.getPref(); // Singleton pattern
  Profile profile = Global.getProfile();
  MainTab mTab;
  MainMenu mMenu;

  /**
   * Constructor for MainForm
   *
   * <p>Loads preferences and the cache index list. Then constructs a MainMenu and the tabbed Panel
   * (MainTab). MainTab holds the different tab panels. MainMenu contains the menu entries.
   *
   * @see MainMenu
   * @see MainTab
   */
  public MainForm() {
    doIt();
  }

  public MainForm(boolean dbg, String pathtoprefxml) {
    pref.debug = dbg;
    pref.setPathToConfigFile(pathtoprefxml); // in case pathtoprefxml ==
    // null the preferences will
    // determine the path itself
    doIt();
  }

  protected boolean canExit(int exitCode) {
    mTab.saveUnsavedChanges(true);
    return true;
  }

  public void doIt() {
    // CellPanel [] p = addToolbar();
    Global.mainForm = this;
    // this.title = "CacheWolf " + Version.getRelease();
    this.exitSystemOnClose = true;
    this.resizable = true;
    this.moveable = true;
    this.windowFlagsToSet = WindowConstants.FLAG_MAXIMIZE_ON_PDA;
    // Rect screen = ((ewe.fx.Rect)
    // (Window.getGuiInfo(WindowConstants.INFO_SCREEN_RECT,null,new
    // ewe.fx.Rect(),0)));
    // if ( screen.height >= 600 && screen.width >= 800)
    // this.setPreferredSize(800, 600);
    this.resizeOnSIP = true;
    InfoBox infB = null;
    try {
      pref.readPrefFile();
      if (MyLocale.initErrors.length() != 0) {
        new MessageBox("Error", MyLocale.initErrors, FormBase.OKB).execute();
      }
      if (Vm.isMobile() == true) {
        // this.windowFlagsToSet |=Window.FLAG_FULL_SCREEN;
        this.resizable = false;
        this.moveable = false;
      } else {
        int h, w;
        h = pref.myAppHeight;
        if (h > MyLocale.getScreenHeight()) h = MyLocale.getScreenHeight();
        w = pref.myAppWidth;
        if (w > MyLocale.getScreenWidth()) w = MyLocale.getScreenWidth();
        this.setPreferredSize(w, h);
      }
      addGuiFont();
      if (!pref.selectProfile(profile, Preferences.PROFILE_SELECTOR_ONOROFF, true))
        ewe.sys.Vm.exit(0); // User MUST select or create a profile
      Vm.showWait(true);

      // Replace buildt-in symbols with customized images
      GuiImageBroker.customizedSymbols();

      // Load CacheList
      infB = new InfoBox("CacheHound", MyLocale.getMsg(5000, "Loading Cache-List"));
      infB.exec();
      infB.waitUntilPainted(100);
      profile.readIndex(infB);
      pref.setCurCenter(new CWPoint(profile.getCenter()));
      profile.updateBearingDistance();
      setTitle("CacheHound " + Version.getRelease() + " - " + profile.name);
    } catch (Exception e) {
      if (pref.debug == true) Vm.debug("MainForm:: Exception:: " + e.toString());
    }

    if (pref.showStatus) statBar = new StatusBar(pref, profile.cacheDB);
    mMenu = new MainMenu(this);
    mTab = new MainTab(mMenu, statBar);
    split = new SplittablePanel(PanelSplitter.HORIZONTAL);
    split.theSplitter.thickness = 0;
    split.theSplitter.modify(Invisible, 0);
    CellPanel pnlCacheList = split.getNextPanel();
    CellPanel pnlMainTab = split.getNextPanel();
    split.setSplitter(
        PanelSplitter.MIN_SIZE | PanelSplitter.BEFORE,
        PanelSplitter.HIDDEN | PanelSplitter.BEFORE,
        PanelSplitter.CLOSED);
    pnlCacheList.addLast(cacheList = new CacheList(), STRETCH, FILL);
    pnlMainTab.addLast(mTab, STRETCH, FILL);

    mTab.dontAutoScroll = true;

    this.addLast(split, STRETCH, FILL);
    /*
     * if (pref.menuAtTop) { this.addLast(mMenu,CellConstants.DONTSTRETCH,
     * CellConstants.FILL); this.addLast(split,STRETCH,FILL); } else {
     * this.addLast(split,STRETCH,FILL);
     * this.addLast(mMenu,CellConstants.DONTSTRETCH, CellConstants.FILL); }
     */
    mMenu.setTablePanel(mTab.getTablePanel());
    if (infB != null) infB.close(0);
    mTab.tbP.refreshTable();
    mTab.tbP.selectFirstRow();
    // mTab.tbP.tc.paintSelection();
    Vm.showWait(false);
  }

  private void addGuiFont() {
    Font defaultGuiFont = mApp.findFont("gui");
    int sz = (pref.fontSize);
    Font newGuiFont = new Font(defaultGuiFont.getName(), defaultGuiFont.getStyle(), sz);
    mApp.addFont(newGuiFont, "gui");
    mApp.fontsChanged();
    mApp.mainApp.font = newGuiFont;
  }

  public void doPaint(Graphics g, Rect r) {
    pref.myAppHeight = this.height;
    pref.myAppWidth = this.width;
    super.doPaint(g, r);
  }

  public void onEvent(Event ev) { // Preferences have been changed by
    // PreferencesScreen
    if (pref.dirty == true) {
      mTab.getTablePanel().myMod.setColumnNamesAndWidths();
      mTab.getTablePanel().refreshControl();
      // mTab.getTablePanel().refreshTable();
      pref.dirty = false;
    }
    super.onEvent(ev);
  }

  public void toggleCacheListVisible() {
    cacheListVisible = !cacheListVisible;
    if (cacheListVisible) {
      // Make the splitterbar visible with a width of 6
      split.theSplitter.modify(0, Invisible);
      split.theSplitter.resizeTo(6, split.theSplitter.getRect().height);
      Global.mainForm.mMenu.cacheTour.modifiers |= MenuItem.Checked;
    } else {
      // Hide the splitterbar and set width to 0
      split.theSplitter.modify(Invisible, 0);
      split.theSplitter.resizeTo(0, split.theSplitter.getRect().height);
      Global.mainForm.mMenu.cacheTour.modifiers &= ~MenuItem.Checked;
    }
    split.theSplitter.doOpenClose(cacheListVisible);
    Global.mainForm.mMenu.repaint();
  }
}
  public void doIt() {
    CacheHolderDetail det;
    CacheHolder ch;
    ProgressBarForm pbf = new ProgressBarForm();
    Handle h = new Handle();
    int exportErrors = 0;

    new String();
    FileChooser fc = new FileChooser(FileChooserBase.DIRECTORY_SELECT, pref.getExportPath(expName));
    fc.setTitle("Select target directory:");
    String targetDir;
    if (fc.execute() != FormBase.IDCANCEL) {
      targetDir = fc.getChosen() + "/";
      pref.setExportPath(expName, targetDir);
      Vector cache_index = new Vector();
      Vector cacheImg = new Vector();
      Vector logImg = new Vector();
      Vector mapImg = new Vector();
      Vector usrImg = new Vector();
      Vector logIcons = new Vector(15);
      String icon;

      Hashtable varParams;
      Hashtable imgParams;
      Hashtable logImgParams;
      Hashtable usrImgParams;
      Hashtable mapImgParams;

      // Generate index page
      int counter = cacheDB.countVisible();

      pbf.showMainTask = false;
      pbf.setTask(h, "Exporting ...");
      pbf.exec();

      for (int i = 0; i < counter; i++) {
        h.progress = (float) (i + 1) / (float) counter;
        h.changed();

        ch = cacheDB.get(i);
        if (ch.isVisible()) {
          if (ch.is_incomplete()) {
            exportErrors++;
            Global.getPref()
                .log("HTMLExport: skipping export of incomplete waypoint " + ch.getWayPoint());
            continue;
          }
          det = ch.getCacheDetails(false, false);
          varParams = new Hashtable();
          varParams.put("TYPE", CacheType.cw2ExportString(ch.getType()));
          varParams.put("WAYPOINT", ch.getWayPoint());
          varParams.put("NAME", ch.getCacheName());
          varParams.put("OWNER", ch.getCacheOwner());
          if (ch.isAddiWpt() || CacheType.CW_TYPE_CUSTOM == ch.getType()) {
            varParams.put("SIZE", "");
            varParams.put("DIFFICULTY", "");
            varParams.put("TERRAIN", "");
          } else {
            varParams.put(
                "SIZE",
                CacheSize.isValidSize(ch.getCacheSize())
                    ? CacheSize.cw2ExportString(ch.getCacheSize())
                    : "");
            varParams.put(
                "DIFFICULTY",
                CacheTerrDiff.isValidTD(ch.getHard()) ? CacheTerrDiff.longDT(ch.getHard()) : "");
            varParams.put(
                "TERRAIN",
                CacheTerrDiff.isValidTD(ch.getTerrain())
                    ? CacheTerrDiff.longDT(ch.getTerrain())
                    : "");
          }
          varParams.put("DISTANCE", ch.getDistance());
          varParams.put("BEARING", ch.bearing);
          varParams.put("LATLON", ch.LatLon);
          varParams.put("STATUS", ch.getCacheStatus());
          varParams.put("DATE", ch.getDateHidden());
          cache_index.add(varParams);
          // We can generate the individual page here!
          try {
            Template page_tpl = new Template(template_init_page);
            page_tpl.setParam("TYPE", varParams.get("TYPE").toString());
            page_tpl.setParam("SIZE", varParams.get("SIZE").toString());
            page_tpl.setParam("WAYPOINT", ch.getWayPoint());
            page_tpl.setParam("NAME", ch.getCacheName());
            page_tpl.setParam("OWNER", ch.getCacheOwner());
            page_tpl.setParam("DIFFICULTY", varParams.get("DIFFICULTY").toString());
            page_tpl.setParam("TERRAIN", varParams.get("TERRAIN").toString());
            page_tpl.setParam("DISTANCE", ch.getDistance());
            page_tpl.setParam("BEARING", ch.bearing);
            page_tpl.setParam("LATLON", ch.LatLon);
            page_tpl.setParam("STATUS", ch.getCacheStatus());
            page_tpl.setParam("DATE", ch.getDateHidden());
            if (det != null) {
              if (ch.is_HTML()) {
                page_tpl.setParam("DESCRIPTION", modifyLongDesc(det, targetDir));
              } else {
                page_tpl.setParam(
                    "DESCRIPTION", STRreplace.replace(det.LongDescription, "\n", "<br>"));
              }
              page_tpl.setParam("HINTS", det.Hints);
              page_tpl.setParam("DECRYPTEDHINTS", Common.rot13(det.Hints));

              StringBuffer sb = new StringBuffer(2000);
              for (int j = 0; j < det.CacheLogs.size(); j++) {
                sb.append(
                    STRreplace.replace(
                        det.CacheLogs.getLog(j).toHtml(),
                        "http://www.geocaching.com/images/icons/",
                        null));
                sb.append("<br>");
                icon = det.CacheLogs.getLog(j).getIcon();
                if (logIcons.find(icon) < 0)
                  logIcons.add(icon); // Add the icon to list of icons to copy to dest directory
              }

              page_tpl.setParam("LOGS", sb.toString());
              page_tpl.setParam("NOTES", STRreplace.replace(det.getCacheNotes(), "\n", "<br>"));

              cacheImg.clear();
              for (int j = 0; j < det.images.size(); j++) {
                imgParams = new Hashtable();
                String imgFile = new String(det.images.get(j).getFilename());
                imgParams.put("FILE", imgFile);
                imgParams.put("TEXT", det.images.get(j).getTitle());
                if (DataMover.copy(profile.dataDir + imgFile, targetDir + imgFile))
                  cacheImg.add(imgParams);
                else exportErrors++;
              }
              page_tpl.setParam("cacheImg", cacheImg);

              // Log images
              logImg.clear();
              for (int j = 0; j < det.logImages.size(); j++) {
                logImgParams = new Hashtable();
                String logImgFile = det.logImages.get(j).getFilename();
                logImgParams.put("FILE", logImgFile);
                logImgParams.put("TEXT", det.logImages.get(j).getTitle());
                if (DataMover.copy(profile.dataDir + logImgFile, targetDir + logImgFile))
                  logImg.add(logImgParams);
                else exportErrors++;
              }
              page_tpl.setParam("logImg", logImg);

              // User images
              usrImg.clear();
              for (int j = 0; j < det.userImages.size(); j++) {
                usrImgParams = new Hashtable();
                String usrImgFile = new String(det.userImages.get(j).getFilename());
                usrImgParams.put("FILE", usrImgFile);
                usrImgParams.put("TEXT", det.userImages.get(j).getTitle());
                if (DataMover.copy(profile.dataDir + usrImgFile, targetDir + usrImgFile))
                  usrImg.add(usrImgParams);
                else exportErrors++;
              }
              page_tpl.setParam("userImg", usrImg);

              // Map images
              mapImg.clear();
              mapImgParams = new Hashtable();

              String mapImgFile = new String(ch.getWayPoint() + "_map.gif");
              // check if map file exists
              File test = new File(profile.dataDir + mapImgFile);

              if (test.exists()) {
                mapImgParams.put("FILE", mapImgFile);
                mapImgParams.put("TEXT", mapImgFile);
                if (DataMover.copy(profile.dataDir + mapImgFile, targetDir + mapImgFile))
                  mapImg.add(mapImgParams);
                else exportErrors++;

                mapImgParams = new Hashtable();
                mapImgFile = ch.getWayPoint() + "_map_2.gif";
                mapImgParams.put("FILE", mapImgFile);
                mapImgParams.put("TEXT", mapImgFile);
                if (DataMover.copy(profile.dataDir + mapImgFile, targetDir + mapImgFile))
                  mapImg.add(mapImgParams);
                else exportErrors++;

                page_tpl.setParam("mapImg", mapImg);
              }
            } else {
              page_tpl.setParam("DESCRIPTION", "");
              page_tpl.setParam("HINTS", "");
              page_tpl.setParam("DECRYPTEDHINTS", "");
              page_tpl.setParam("LOGS", "");
              page_tpl.setParam("NOTES", "");
              page_tpl.setParam("cacheImg", cacheImg);
              page_tpl.setParam("logImg", ""); // ???
              page_tpl.setParam("userImg", ""); // ???
              page_tpl.setParam("mapImg", ""); // ???
              exportErrors++;
            }

            PrintWriter pagefile =
                new PrintWriter(
                    new BufferedWriter(new FileWriter(targetDir + ch.getWayPoint() + ".html")));
            pagefile.print(page_tpl.output());
            pagefile.close();
          } catch (IllegalArgumentException e) {
            exportErrors++;
            ch.setIncomplete(true);
            Global.getPref()
                .log(
                    "HTMLExport: " + ch.getWayPoint() + " is incomplete reason: ",
                    e,
                    Global.getPref().debug);
          } catch (Exception e) {
            exportErrors++;
            Global.getPref()
                .log(
                    "HTMLExport: error wehen exporting " + ch.getWayPoint() + " reason: ",
                    e,
                    Global.getPref().debug);
          }
        } // if is black, filtered
      }

      // Copy the log-icons to the destination directory
      for (int j = 0; j < logIcons.size(); j++) {
        icon = (String) logIcons.elementAt(j);
        if (!DataMover.copy(FileBase.getProgramDirectory() + "/" + icon, targetDir + icon))
          exportErrors++;
      }
      if (!DataMover.copy(
          FileBase.getProgramDirectory() + "/recommendedlog.gif", targetDir + "recommendedlog.gif"))
        exportErrors++;

      try {
        Template tpl = new Template(template_init_index);
        tpl.setParam("cache_index", cache_index);
        PrintWriter detfile;
        detfile = new PrintWriter(new BufferedWriter(new FileWriter(targetDir + "/index.html")));
        detfile.print(tpl.output());
        detfile.close();
        // sort by waypoint
        sortAndPrintIndex(tpl, cache_index, targetDir + "/index_wp.html", "WAYPOINT");
        // sort by name
        sortAndPrintIndex(tpl, cache_index, targetDir + "/index_alpha.html", "NAME", false);
        // sort by type
        sortAndPrintIndex(tpl, cache_index, targetDir + "/index_type.html", "TYPE", true);
        // sort by size
        sortAndPrintIndex(tpl, cache_index, targetDir + "/index_size.html", "SIZE", true);
        // sort by distance
        sortAndPrintIndex(tpl, cache_index, targetDir + "/index_dist.html", "DISTANCE", 10.0);
      } catch (Exception e) {
        Vm.debug("Problem writing HTML files\n");
        e.printStackTrace();
      } // try
    } // if
    pbf.exit(0);

    if (exportErrors > 0) {
      new MessageBox(
              "Export Error",
              exportErrors + " errors during export. See log for details.",
              FormBase.OKB)
          .execute();
    }
  }