@Override
    public void _setOkBadge(IdeFrame frame, boolean visible) {
      if (!isValid(frame)) {
        return;
      }

      Object icon = null;

      if (visible) {
        synchronized (Win7AppIcon.class) {
          if (myOkIcon == null) {
            try {
              BufferedImage image = ImageIO.read(getClass().getResource("/mac/appIconOk512.png"));
              ByteArrayOutputStream bytes = new ByteArrayOutputStream();
              Sanselan.writeImage(image, bytes, ImageFormat.IMAGE_FORMAT_ICO, new HashMap());
              myOkIcon = Win7TaskBar.createIcon(bytes.toByteArray());
            } catch (Throwable e) {
              LOG.error(e);
              myOkIcon = null;
            }
          }

          icon = myOkIcon;
        }
      }

      try {
        Win7TaskBar.setOverlayIcon(frame, icon, false);
      } catch (Throwable e) {
        LOG.error(e);
      }
    }
    @Override
    public boolean _setProgress(
        IdeFrame frame,
        Object processId,
        AppIconScheme.Progress scheme,
        double value,
        boolean isOk) {
      myCurrentProcessId = processId;

      if (Math.abs(myLastValue - value) < 0.02d) {
        return true;
      }

      try {
        if (isValid(frame)) {
          Win7TaskBar.setProgress(frame, value, isOk);
        }
      } catch (Throwable e) {
        LOG.error(e);
      }

      myLastValue = value;
      myCurrentProcessId = null;
      return true;
    }
    @Override
    public void _setTextBadge(IdeFrame frame, String text) {
      if (!isValid(frame)) {
        return;
      }

      Object icon = null;

      if (text != null) {
        try {
          int size = 55;
          BufferedImage image = UIUtil.createImage(size, size, BufferedImage.TYPE_INT_ARGB);
          Graphics2D g = image.createGraphics();

          int roundSize = 40;
          g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
          g.setPaint(ERROR_COLOR);
          g.fillRoundRect(
              size / 2 - roundSize / 2, size / 2 - roundSize / 2, roundSize, roundSize, size, size);

          g.setColor(Color.white);
          Font font = g.getFont();
          g.setFont(new Font(font.getName(), font.getStyle(), 22));
          FontMetrics fontMetrics = g.getFontMetrics();
          int width = fontMetrics.stringWidth(text);
          g.drawString(
              text,
              size / 2 - width / 2,
              size / 2 - fontMetrics.getHeight() / 2 + fontMetrics.getAscent());

          ByteArrayOutputStream bytes = new ByteArrayOutputStream();
          Sanselan.writeImage(image, bytes, ImageFormat.IMAGE_FORMAT_ICO, new HashMap());
          icon = Win7TaskBar.createIcon(bytes.toByteArray());
        } catch (Throwable e) {
          LOG.error(e);
        }
      }

      try {
        Win7TaskBar.setOverlayIcon(frame, icon, icon != null);
      } catch (Throwable e) {
        LOG.error(e);
      }
    }
 @Override
 public void _requestAttention(IdeFrame frame, boolean critical) {
   try {
     if (isValid(frame)) {
       Win7TaskBar.attention(frame, critical);
     }
   } catch (Throwable e) {
     LOG.error(e);
   }
 }
    @Override
    public boolean _hideProgress(IdeFrame frame, Object processId) {
      if (myCurrentProcessId != null && !myCurrentProcessId.equals(processId)) {
        return false;
      }

      try {
        if (isValid(frame)) {
          Win7TaskBar.hideProgress(frame);
        }
      } catch (Throwable e) {
        LOG.error(e);
      }

      myCurrentProcessId = null;
      myLastValue = 0;
      return true;
    }