private static void paintArrowsInGraph(
     Canvas canvas,
     SpotWindData spotWindData,
     Images images,
     int startX,
     int endX,
     int xSteps,
     int startY,
     int endY,
     int stepXCount) {
   Paint paint = new Paint();
   int hourPos = 0;
   for (int x = startX; x <= endX; x += xSteps) {
     canvas.drawLine(x, startY, x, endY, paint);
     WindData windData = spotWindData.getWindData(hourPos);
     if (windData != null) {
       Matrix arrowImageMatrix = new Matrix();
       float origArrowSize = images.getArrowBitmap().getHeight();
       int arrowSize = 30;
       float arrowScale = arrowSize / origArrowSize;
       int rotation = windData.getAngle();
       arrowImageMatrix.postScale(arrowScale, arrowScale);
       arrowImageMatrix.postRotate(rotation, arrowSize / 2, arrowSize / 2);
       arrowImageMatrix.postTranslate(x - arrowSize / 2, startY + 5);
       canvas.drawBitmap(images.getArrowBitmap(), arrowImageMatrix, paint);
     }
     hourPos += 24 / stepXCount;
   }
 }
  private static void paintArrow(
      Canvas canvas,
      WidgetLayoutDetails widgetLayoutDetails,
      Images images,
      WindData windData,
      int xOffset,
      int yOffset) {
    Paint paint = new Paint();
    Matrix arrowImageMatrix = new Matrix();
    float origArrowSize = images.getArrowBitmap().getHeight();
    float arrowScale = widgetLayoutDetails.spotImageHeight / origArrowSize;
    float scaleForWind = (float) windData.getWind() / MAXWIND;
    if (scaleForWind > 1) scaleForWind = 1;
    int rotation = windData.getAngle();
    double arrowHeight = widgetLayoutDetails.spotImageHeight * scaleForWind;
    int offset = ((int) widgetLayoutDetails.spotImageHeight - (int) arrowHeight) / 2;

    arrowImageMatrix.postScale(arrowScale, arrowScale);
    arrowImageMatrix.postRotate(
        rotation, widgetLayoutDetails.spotImageHeight / 2, widgetLayoutDetails.spotImageHeight / 2);
    arrowImageMatrix.postScale(scaleForWind, scaleForWind);
    arrowImageMatrix.postTranslate(offset, offset);
    arrowImageMatrix.postTranslate(xOffset, yOffset);
    canvas.drawBitmap(images.getArrowBitmap(), arrowImageMatrix, paint);
  }
 private static Bitmap getGlobalAdviceBitmap(
     Images images, int angleAdviceLevel, int powerAdviceLevel) {
   Bitmap globalAdviceBitmap = null;
   int advice = angleAdviceLevel;
   if (advice < powerAdviceLevel) advice = powerAdviceLevel;
   switch (advice) {
     case 0:
       globalAdviceBitmap = images.getOkBitmap();
       break;
     case 1:
       globalAdviceBitmap = images.getGoodBitmap();
       break;
     case 2:
       globalAdviceBitmap = images.getSadFaceBitmap();
       break;
     case 3:
       globalAdviceBitmap = images.getWarningBitmap();
       break;
     case 4:
       globalAdviceBitmap = images.getDangerBitmap();
       break;
     case 5:
       globalAdviceBitmap = images.getUnknowmBitmap();
       break;
   }
   return globalAdviceBitmap;
 }
  public static void paintCanvas(
      Context context,
      WidgetLayoutDetails widgetLayoutDetails,
      Canvas canvas,
      SpotWindData spotWindData,
      Set<Bar> windGraphPath,
      Set<Bar> gustGraphPath,
      float touchPos,
      boolean checkOutDated) {
    // define graph boundaries
    int startGraphX = 50;
    int startGraphY = widgetLayoutDetails.spotImageHeight + 10;
    int endGraphY = widgetLayoutDetails.widgetHeight - 30;
    int endGraphX = widgetLayoutDetails.widgetWidth - 30;
    int graphWidth = endGraphX - startGraphX;
    int yOffsetImage = widgetLayoutDetails.yOffsetImage;
    int xOffsetImage = widgetLayoutDetails.xOffsetImage;

    WindData lastWindData = spotWindData.getLastWindData();
    WindData firstWindData = spotWindData.getFirstWindData();

    // calculate the time that is touched (if no data is available, use the time most nearby)
    double time =
        calculateTouchedTime(touchPos, startGraphX, graphWidth, firstWindData, lastWindData);
    double selectedPos = (time * graphWidth) / 24 + startGraphX;

    // check preconditions
    if (spotWindData == null) return;
    if (spotWindData.getSpotData() == null) return;

    // get images
    Images images = ImageStorage.getImages(context);
    if (images.getArrowBitmap() == null) return;

    // load spot bitmap
    Bitmap spotBitmap = ImageStorage.getSpotImage(context, spotWindData.getSpotData().getSiteID());
    if (spotBitmap == null) return;

    // draw white background
    if (widgetLayoutDetails.drawWhiteBackground) {
      drawWhiteBackground(widgetLayoutDetails, canvas);
    }

    // draw graph
    if (widgetLayoutDetails.drawGraph) {
      int stepXCount = calculateXCount(widgetLayoutDetails);
      int stepYCount = calculateYCount(widgetLayoutDetails);
      int xSteps = calculateXSteps(endGraphX, startGraphX, stepXCount);
      int ySteps = calculateYSteps(endGraphY, startGraphY, stepYCount);
      // recalculate endX and endY with the new xSteps
      endGraphX = startGraphX + xSteps * stepXCount;
      endGraphY = startGraphY + ySteps * stepYCount;

      // paint time mark line
      if (widgetLayoutDetails.drawTimeline) {
        paintTimeMarkLine(canvas, endGraphX, startGraphX, widgetLayoutDetails, (float) selectedPos);
      }

      // paint raster
      paintRaster(
          canvas,
          startGraphX,
          endGraphX,
          xSteps,
          endGraphY,
          startGraphY,
          stepXCount,
          ySteps,
          stepYCount);

      // paint graph
      paintGraph(canvas, windGraphPath, gustGraphPath);

      // paint all arrows
      paintArrowsInGraph(
          canvas,
          spotWindData,
          images,
          startGraphX,
          endGraphX,
          xSteps,
          startGraphY,
          endGraphY,
          stepXCount);
    }

    // get the selected windData
    WindData windData = spotWindData.getWindData(time);

    // draw the image
    if (widgetLayoutDetails.drawImage) {
      // define advice location
      int adviceStatusIconTop = 10;
      int adviceStatusIconLeft =
          (int) widgetLayoutDetails.spotImageHeight
              - widgetLayoutDetails.windSpeedCircelDiameter
              - 10;

      // draw spot
      drawSpotImage(spotBitmap, widgetLayoutDetails, canvas, xOffsetImage, yOffsetImage);

      if (windData == null) {
        paintImageTextOutdated(context, widgetLayoutDetails, canvas, xOffsetImage, yOffsetImage);
        Bitmap globalAdviceBitmap = images.getUnknowmBitmap();
        paintAdviceIcon(
            canvas,
            widgetLayoutDetails.windSpeedCircelDiameter,
            globalAdviceBitmap,
            adviceStatusIconLeft,
            adviceStatusIconTop,
            xOffsetImage,
            yOffsetImage);
      }

      if (windData != null) {

        // find windData
        double windDataTime = windData.getEndHour() + (double) windData.getEndMinute() / 60;
        double currentTime = Util.calculateTime(new Date());
        double diffTime = (currentTime - windDataTime);
        boolean outDated = diffTime > 1;

        if (outDated && checkOutDated) {
          paintImageTextOutdated(context, widgetLayoutDetails, canvas, xOffsetImage, yOffsetImage);
          Bitmap globalAdviceBitmap = images.getUnknowmBitmap();
          paintAdviceIcon(
              canvas,
              widgetLayoutDetails.windSpeedCircelDiameter,
              globalAdviceBitmap,
              adviceStatusIconLeft,
              adviceStatusIconTop,
              xOffsetImage,
              yOffsetImage);
        } else {

          // paint the arrow
          paintArrow(canvas, widgetLayoutDetails, images, windData, xOffsetImage, yOffsetImage);

          // check aanlandig/sideshore/aflandig
          WIND_DIRECTORION windDirectorion = calculateWindAngleStatus(windData, spotWindData);
          WIND_POWER windPower = calculateWindPower(context, windData);
          int angleAdviceLevel = getAngleAdviceLevel(windDirectorion);
          int powerAdviceLevel = getWindPowerAdviceLevel(windPower);
          String windDateText = getAngleAdviceText(context, windDirectorion);
          int windPowerColor = getWindPowerColor(windPower);

          // define global advice
          Bitmap globalAdviceBitmap =
              getGlobalAdviceBitmap(images, angleAdviceLevel, powerAdviceLevel);

          // print circel for wind
          if (widgetLayoutDetails.drawWindInCorner) {
            int wind = (int) Math.round(windData.getWind());
            paintWindInCorner(
                canvas,
                widgetLayoutDetails.windSpeedCircelDiameter,
                wind,
                xOffsetImage,
                yOffsetImage);
          }

          paintAdviceIcon(
              canvas,
              widgetLayoutDetails.windSpeedCircelDiameter,
              globalAdviceBitmap,
              adviceStatusIconLeft,
              adviceStatusIconTop,
              xOffsetImage,
              yOffsetImage);

          if (widgetLayoutDetails.drawImageText) {
            paintImageText(
                context, widgetLayoutDetails, canvas, windData, xOffsetImage, yOffsetImage);
          }
        }
      }
    }
  }