@Override
 public Dimension getMinimumSize(JComponent c) {
   AbstractButton b = (AbstractButton) c;
   String style = (String) c.getClientProperty("Quaqua.Button.style");
   if (style == null) {
     style = "push";
   }
   if (style.equals("help")) {
     return getPreferredSize(c);
   }
   Dimension d = super.getMinimumSize(c);
   if (isFixedHeight(c)) {
     Dimension p = getPreferredSize(c);
     if (d != null && p != null) {
       d.height = Math.max(d.height, p.height);
     }
   }
   if (!QuaquaUtilities.isSmallSizeVariant(c)
       && style.equals("push") //
       && b.getIcon() == null
       && b.getText() != null) {
     if (d != null) {
       d.width = Math.max(d.width, UIManager.getInt("Button.minimumWidth"));
     }
   }
   return d;
 }
 @Override
 public Dimension getMaximumSize(JComponent c) {
   String style = (String) c.getClientProperty("Quaqua.Button.style");
   if (style != null && style.equals("help")) {
     return getPreferredSize(c);
   }
   Dimension d = super.getMaximumSize(c);
   if (isFixedHeight(c)) {
     Dimension p = getPreferredSize(c);
     d.height = Math.max(d.height, p.height);
   }
   return d;
 }
  protected void paintToImage(Component c, Graphics gr, int width, int height, Object args) {
    // Cast Graphics to Graphics2D
    // Workaround for Java 1.4 and 1.4 on Mac OS X 10.4. We create a new
    // Graphics object instead of just casting the provided one. This is
    // because drawing texture paints appears to confuse the Graphics object.
    Graphics2D g = (Graphics2D) gr.create();

    // Convert image to buffered image (and keep the buffered image).
    image = Images.toBufferedImage(image);
    BufferedImage img = (BufferedImage) image;

    // Set some variables for easy access of insets and image size
    int top = imageInsets.top;
    int left = imageInsets.left;
    int bottom = imageInsets.bottom;
    int right = imageInsets.right;
    int imgWidth = img.getWidth();
    int imgHeight = img.getHeight();

    // Optimisation: Draw image directly if it fits into the component
    if (fillContentArea) {
      if (width == imgWidth && height == imgHeight) {
        g.drawImage(img, 0, 0, c);
        g.dispose();
        return;
      }
    }

    // Optimisation: Remove insets, if image width or image height fits
    if (width == imgWidth) {
      left = imgWidth;
      right = 0;
    }
    if (height == imgHeight) {
      top = imgHeight;
      bottom = 0;
    }

    // Adjust insets if component is too small
    if (width < left + right) {
      left = Math.min(left, width / 2); // Math.max(0, left + (width - left - right) / 2);
      right = width - left;
    }
    if (height < top + bottom) {
      top = Math.min(top, height / 2); // Math.max(0, top + (height - top - bottom) / 2);
      bottom = height - top;
    }

    // Draw the Corners
    if (top > 0 && left > 0) {
      g.drawImage(img, 0, 0, left, top, 0, 0, left, top, c);
    }
    if (top > 0 && right > 0) {
      // g.fillRect(x+width-right, y, x+width, y+top);
      g.drawImage(img, width - right, 0, width, top, imgWidth - right, 0, imgWidth, top, c);
    }
    if (bottom > 0 && left > 0) {
      g.drawImage(img, 0, height - bottom, left, height, 0, imgHeight - bottom, left, imgHeight, c);
    }
    if (bottom > 0 && right > 0) {
      g.drawImage(
          img,
          width - right,
          height - bottom,
          width,
          height,
          imgWidth - right,
          imgHeight - bottom,
          imgWidth,
          imgHeight,
          c);
    }

    // Draw the edges
    BufferedImage subImg = null;
    TexturePaint paint;

    // North
    if (top > 0 && left + right < width) {
      if (imgWidth > right + left) {
        subImg = img.getSubimage(left, 0, imgWidth - right - left, top);
        paint = new TexturePaint(subImg, new Rectangle(left, 0, imgWidth - left - right, top));
        g.setPaint(paint);
        g.fillRect(left, 0, width - left - right, top);
      }
    }
    // South
    if (bottom > 0 && left + right < width) {
      if (imgHeight > bottom && imgWidth > right + left) {
        subImg = img.getSubimage(left, imgHeight - bottom, imgWidth - right - left, bottom);
        paint =
            new TexturePaint(
                subImg, new Rectangle(left, height - bottom, imgWidth - left - right, bottom));
        g.setPaint(paint);
        g.fillRect(left, height - bottom, width - left - right, bottom);
      }
    }
    // West
    if (left > 0 && top + bottom < height) {
      if (imgHeight > top + bottom) {
        subImg = img.getSubimage(0, top, left, imgHeight - top - bottom);
        paint = new TexturePaint(subImg, new Rectangle(0, top, left, imgHeight - top - bottom));
        g.setPaint(paint);
        g.fillRect(0, top, left, height - top - bottom);
      }
    }
    // East
    if (right > 0 && top + bottom < height) {
      if (imgWidth > right && imgHeight > top + bottom) {
        subImg = img.getSubimage(imgWidth - right, top, right, imgHeight - top - bottom);
        paint =
            new TexturePaint(
                subImg, new Rectangle(width - right, top, right, imgHeight - top - bottom));
        g.setPaint(paint);
        g.fillRect(width - right, top, right, height - top - bottom);
      }
    }

    // Fill the center
    if (fillContentArea) {
      if (left + right < imgWidth && top + bottom < imgHeight) {
        subImg = img.getSubimage(left, top, imgWidth - right - left, imgHeight - top - bottom);
        paint =
            new TexturePaint(
                subImg,
                new Rectangle(left, top, imgWidth - right - left, imgHeight - top - bottom));
        g.setPaint(paint);
        g.fillRect(left, top, width - right - left, height - top - bottom);
      }
    }
    g.dispose();
  }
  public static Dimension getPreferredSize(AbstractButton b) {
    String style = (String) b.getClientProperty("Quaqua.Button.style");
    if (style == null) {
      style = "push";
    }
    if (style.equals("help")) {
      Icon helpIcon = UIManager.getIcon("Button.helpIcon");
      Insets insets = b.getInsets();

      return new Dimension(
          helpIcon.getIconWidth() + insets.left + insets.right,
          helpIcon.getIconHeight() + insets.top + insets.bottom);
    }
    if (b.getComponentCount() > 0) {
      return null;
    }

    int textIconGap = Methods.invokeGetter(b, "getIconTextGap", 4);
    Icon icon = (Icon) b.getIcon();
    String text = b.getText();

    Font font = b.getFont();
    FontMetrics fm = b.getFontMetrics(font);

    viewR.x = viewR.y = 0;
    viewR.width = Short.MAX_VALUE;
    viewR.height = Short.MAX_VALUE;
    iconR.x = iconR.y = iconR.width = iconR.height = 0;
    textR.x = textR.y = textR.width = textR.height = 0;

    SwingUtilities.layoutCompoundLabel(
        (JComponent) b,
        fm,
        text,
        icon,
        b.getVerticalAlignment(),
        b.getHorizontalAlignment(),
        b.getVerticalTextPosition(),
        b.getHorizontalTextPosition(),
        viewR,
        iconR,
        textR,
        (text == null ? 0 : textIconGap));

    /* The preferred size of the button is the size of
     * the text and icon rectangles plus the buttons insets.
     */

    Rectangle r = iconR.union(textR);

    // if (b.isBorderPainted()) {
    Insets insets = b.getInsets();
    r.width += insets.left + insets.right;
    r.height += insets.top + insets.bottom;
    // }
    if (!QuaquaUtilities.isSmallSizeVariant(b)
        && style.equals("push")
        && b.getIcon() == null
        && b.getText() != null) {
      r.width = Math.max(r.width, UIManager.getInt("Button.minimumWidth"));
    }
    return r.getSize();
  }